From f64c92ef555b1c4d6eccdd66c70c0ea79222d0a7 Mon Sep 17 00:00:00 2001 From: "mati108@gmail.com" <34651529+matbenitez@users.noreply.github.com> Date: Wed, 13 Feb 2019 17:24:17 -0300 Subject: [PATCH 01/73] Updating to axios and new sing method on key vault --- Exchange/ExchangeAPI.js | 51 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index 2ad5eddfd..3dde860f9 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -7,7 +7,7 @@ */ const _ = require('lodash') const isValidOrder = require('./exchangeUtils').isValidOrder - const graphqlClient = require('graphql-client') + const axios = require('axios') const appRoot = require('app-root-path') const auth = require(`${appRoot}/utils/auth`) @@ -55,37 +55,38 @@ function createKeyVaultAPIClient(authToken) { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Entering function."); } - const keyVaultAPI = graphqlClient({ - url: global.GATEWAY_ENDPOINT, - headers: { - Authorization: 'Bearer ' + authToken - } - }); - + const keyVaultAPI = {} keyVaultAPI.signTransaction = function (transaction, next) { - let variables = { - botId: bot.codeName, - transaction: transaction - } + axios({ + url: global.GATEWAY_ENDPOINT, + method: 'post', + data: { + query: ` + mutation keyVault_SignTransaction($keyId: String!, $cloneId: String!, $transaction: String!){ + keyVault_SignTransaction(keyId: $keyId, cloneId: $cloneId, transaction: $transaction){ + key, + signature, + date + } + } + `, + variables: { + keyId: process.env.KEY_ID, + cloneId: process.env.CLONE_ID, + transaction: transaction + } + }, + headers: { + authorization: 'Bearer ' + authToken + } - keyVaultAPI.query(` - mutation($botId: String, $transaction: String!){ - keyVault_SignTransaction(botId: $botId, transaction: $transaction){ - key, - signature, - date - } - }`, variables, function (req, res) { - if (res.status === 401) { - next(undefined, 'Error from graphql: Not authorized'); - } }).then(res => { if (res.errors) { next(undefined, 'Error from graphql: ' + res.errors); } else { let signature = { - Key: res.data.keyVault_SignTransaction.key, - Sign: res.data.keyVault_SignTransaction.signature + Key: res.data.data.keyVault_SignTransaction.key, + Sign: res.data.data.keyVault_SignTransaction.signature } next(signature) } From 4d040981541e5bffdd07d6f5495b0ff260cae353 Mon Sep 17 00:00:00 2001 From: "mati108@gmail.com" <34651529+matbenitez@users.noreply.github.com> Date: Wed, 13 Feb 2019 17:25:06 -0300 Subject: [PATCH 02/73] Not loging all the response from the exchanges --- Exchange/wrappers/poloniexClient.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Exchange/wrappers/poloniexClient.js b/Exchange/wrappers/poloniexClient.js index 7476728c1..368ce01cc 100644 --- a/Exchange/wrappers/poloniexClient.js +++ b/Exchange/wrappers/poloniexClient.js @@ -6,7 +6,7 @@ */ const FULL_LOG = true; - const LOG_FILE_CONTENT = true; + const LOG_FILE_CONTENT = false; const MODULE_NAME = "poloniexClient"; const retry = require('../exchangeUtils').retry; @@ -300,7 +300,7 @@ try { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeErr = " + stringExchangeErr); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeResponse = " + stringExchangeResponse); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeResponse = " + stringExchangeResponse); } if (exchangeErr) { error = global.DEFAULT_FAIL_RESPONSE; From e9e4d6456f551a13da64e5ac8b956eb53fab6583 Mon Sep 17 00:00:00 2001 From: "mati108@gmail.com" <34651529+matbenitez@users.noreply.github.com> Date: Wed, 13 Feb 2019 17:25:31 -0300 Subject: [PATCH 03/73] Removing graphql-client lib --- package-lock.json | 377 ++++++++++++++++++++-------------------------- package.json | 1 - 2 files changed, 165 insertions(+), 213 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb0afbaa8..81321f1c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,10 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "apollo-boost": { @@ -31,14 +31,14 @@ "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.1.16.tgz", "integrity": "sha512-ppnQr90n2cn0ZMveEbqxW6NxmskIpThiLziLlRpRLy4keoAICg1NZecxJQmeaBLMtyhf5UholAjpS2SLmEJeHg==", "requires": { - "apollo-cache": "1.1.17", - "apollo-cache-inmemory": "1.2.10", - "apollo-client": "2.4.2", - "apollo-link": "1.2.3", - "apollo-link-error": "1.1.1", - "apollo-link-http": "1.5.5", - "apollo-link-state": "0.4.2", - "graphql-tag": "2.10.0" + "apollo-cache": "^1.1.17", + "apollo-cache-inmemory": "^1.2.10", + "apollo-client": "^2.4.2", + "apollo-link": "^1.0.6", + "apollo-link-error": "^1.0.3", + "apollo-link-http": "^1.3.1", + "apollo-link-state": "^0.4.0", + "graphql-tag": "^2.4.2" } }, "apollo-cache": { @@ -46,7 +46,7 @@ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.17.tgz", "integrity": "sha512-7sp24n2HZO4vXgTaKNomLyIfGxG4gDdDkBB0jkRzRi7HhnKmfwhiF/RCiKNbgLdrPX151INdls0KwIVliD0dHQ==", "requires": { - "apollo-utilities": "1.0.21" + "apollo-utilities": "^1.0.21" } }, "apollo-cache-inmemory": { @@ -54,9 +54,9 @@ "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.2.10.tgz", "integrity": "sha512-eBusPFVtYIuo+PIfJdAwUCQ4cs7AJ4mB7sTdXxNQCXToYw8mzE6EfHnV37kdVfBXSaa82BzE2rb/YUq/duuamw==", "requires": { - "apollo-cache": "1.1.17", - "apollo-utilities": "1.0.21", - "graphql-anywhere": "4.1.19" + "apollo-cache": "^1.1.17", + "apollo-utilities": "^1.0.21", + "graphql-anywhere": "^4.1.19" } }, "apollo-client": { @@ -65,13 +65,13 @@ "integrity": "sha512-g1z23umaVSoKLj9xNl0aAnk2KBF4JeBi7MeKFc9CGTixH7TkqeQUQtxcjrC7j2h4KmDbuhOAHOFUGf8YshN+ag==", "requires": { "@types/async": "2.0.49", - "@types/zen-observable": "0.8.0", + "@types/zen-observable": "^0.8.0", "apollo-cache": "1.1.17", - "apollo-link": "1.2.3", - "apollo-link-dedup": "1.0.10", + "apollo-link": "^1.0.0", + "apollo-link-dedup": "^1.0.0", "apollo-utilities": "1.0.21", - "symbol-observable": "1.2.0", - "zen-observable": "0.8.9" + "symbol-observable": "^1.0.2", + "zen-observable": "^0.8.0" } }, "apollo-link": { @@ -79,8 +79,8 @@ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.3.tgz", "integrity": "sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==", "requires": { - "apollo-utilities": "1.0.21", - "zen-observable-ts": "0.8.10" + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.10" } }, "apollo-link-dedup": { @@ -88,7 +88,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz", "integrity": "sha512-tpUI9lMZsidxdNygSY1FxflXEkUZnvKRkMUsXXuQUNoSLeNtEvUX7QtKRAl4k9ubLl8JKKc9X3L3onAFeGTK8w==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-link-error": { @@ -96,7 +96,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-error/-/apollo-link-error-1.1.1.tgz", "integrity": "sha512-/yPcaQWcBdB94vpJ4FsiCJt1dAGGRm+6Tsj3wKwP+72taBH+UsGRQQZk7U/1cpZwl1yqhHZn+ZNhVOebpPcIlA==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-link-http": { @@ -104,8 +104,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.5.tgz", "integrity": "sha512-C5N6N/mRwmepvtzO27dgMEU3MMtRKSqcljBkYNZmWwH11BxkUQ5imBLPM3V4QJXNE7NFuAQAB5PeUd4ligivTQ==", "requires": { - "apollo-link": "1.2.3", - "apollo-link-http-common": "0.2.5" + "apollo-link": "^1.2.3", + "apollo-link-http-common": "^0.2.5" } }, "apollo-link-http-common": { @@ -113,7 +113,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.5.tgz", "integrity": "sha512-6FV1wr5AqAyJ64Em1dq5hhGgiyxZE383VJQmhIoDVc3MyNcFL92TkhxREOs4rnH2a9X2iJMko7nodHSGLC6d8w==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-link-state": { @@ -121,8 +121,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-state/-/apollo-link-state-0.4.2.tgz", "integrity": "sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw==", "requires": { - "apollo-utilities": "1.0.21", - "graphql-anywhere": "4.1.19" + "apollo-utilities": "^1.0.8", + "graphql-anywhere": "^4.1.0-alpha.0" } }, "apollo-utilities": { @@ -130,8 +130,8 @@ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.21.tgz", "integrity": "sha512-ZcxELlEl+sDCYBgEMdNXJAsZtRVm8wk4HIA58bMsqYfd1DSAJQEtZ93F0GZgYNAGy3QyaoBeZtbb0/01++G8JQ==", "requires": { - "fast-json-stable-stringify": "2.0.0", - "fclone": "1.0.11" + "fast-json-stable-stringify": "^2.0.0", + "fclone": "^1.0.11" } }, "app-root-path": { @@ -144,7 +144,7 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "~2.1.0" } }, "assert": { @@ -165,7 +165,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { - "lodash": "4.17.11" + "lodash": "^4.17.10" } }, "asynckit": { @@ -188,8 +188,8 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { - "follow-redirects": "1.6.1", - "is-buffer": "1.1.6" + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" } }, "azure-storage": { @@ -197,17 +197,17 @@ "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.2.tgz", "integrity": "sha512-pOyGPya9+NDpAfm5YcFfklo57HfjDbYLXxs4lomPwvRxmb0Di/A+a+RkUmEFzaQ8S13CqxK40bRRB0sjj2ZQxA==", "requires": { - "browserify-mime": "1.2.9", - "extend": "3.0.2", + "browserify-mime": "~1.2.9", + "extend": "^3.0.2", "json-edm-parser": "0.1.2", "md5.js": "1.3.4", - "readable-stream": "2.0.6", - "request": "2.88.0", - "underscore": "1.8.3", - "uuid": "3.3.2", - "validator": "9.4.1", + "readable-stream": "~2.0.0", + "request": "^2.86.0", + "underscore": "~1.8.3", + "uuid": "^3.0.0", + "validator": "~9.4.1", "xml2js": "0.2.8", - "xmlbuilder": "9.0.7" + "xmlbuilder": "^9.0.7" }, "dependencies": { "underscore": { @@ -223,7 +223,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "browserify-mime": { @@ -251,8 +251,8 @@ "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", "requires": { - "color-convert": "1.9.3", - "color-string": "1.5.3" + "color-convert": "^1.9.1", + "color-string": "^1.5.2" } }, "color-convert": { @@ -273,8 +273,8 @@ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "requires": { - "color-name": "1.1.3", - "simple-swizzle": "0.2.2" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, "colornames": { @@ -292,8 +292,8 @@ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", "requires": { - "color": "3.0.0", - "text-hex": "1.0.0" + "color": "3.0.x", + "text-hex": "1.0.x" } }, "combined-stream": { @@ -301,7 +301,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "core-util-is": { @@ -314,7 +314,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "debug": { @@ -335,9 +335,9 @@ "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", "requires": { - "colorspace": "1.1.1", - "enabled": "1.0.2", - "kuler": "1.0.1" + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" } }, "dotenv": { @@ -351,8 +351,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "optional": true, "requires": { - "jsbn": "0.1.1", - "safer-buffer": "2.1.2" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "ecdsa-sig-formatter": { @@ -360,7 +360,7 @@ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "enabled": { @@ -368,15 +368,7 @@ "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", "requires": { - "env-variable": "0.0.5" - } - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "0.4.24" + "env-variable": "0.0.x" } }, "env-variable": { @@ -424,7 +416,7 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "requires": { - "debug": "3.1.0" + "debug": "=3.1.0" } }, "forever-agent": { @@ -437,9 +429,9 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.20" + "mime-types": "^2.1.12" }, "dependencies": { "combined-stream": { @@ -447,7 +439,7 @@ "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } } } @@ -457,7 +449,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "graphql": { @@ -465,7 +457,7 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", "requires": { - "iterall": "1.2.2" + "iterall": "^1.2.2" } }, "graphql-anywhere": { @@ -473,15 +465,7 @@ "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-4.1.19.tgz", "integrity": "sha512-mQlvbECzYPBcgBC9JsdM4v+DSvNmcIP+8Vwr+ij3gktbaLSE0Iza30mztuz40Jlf7ooMs+0emBZucNjLzqz7tA==", "requires": { - "apollo-utilities": "1.0.21" - } - }, - "graphql-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/graphql-client/-/graphql-client-2.0.1.tgz", - "integrity": "sha512-XXdjUD3mwsBDcUB7g+iXQeRt+3gmIbvA/Yx1nE5aq2RQmaJwiH4hEoYw27AW8cDR90pCrPlHJAb1jJq3zUMbZA==", - "requires": { - "isomorphic-fetch": "2.2.1" + "apollo-utilities": "^1.0.21" } }, "graphql-tag": { @@ -499,8 +483,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.3.0", + "har-schema": "^2.0.0" } }, "hash-base": { @@ -508,8 +492,8 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { - "inherits": "2.0.1", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "http-signature": { @@ -517,17 +501,9 @@ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.2" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": "2.1.2" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "inherits": { @@ -560,15 +536,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "1.7.3", - "whatwg-fetch": "3.0.0" - } - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -590,7 +557,7 @@ "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", "requires": { - "jsonparse": "1.2.0" + "jsonparse": "~1.2.0" } }, "json-schema": { @@ -618,15 +585,15 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", "requires": { - "jws": "3.2.1", - "lodash.includes": "4.3.0", - "lodash.isboolean": "3.0.3", - "lodash.isinteger": "4.0.4", - "lodash.isnumber": "3.0.3", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.once": "4.1.1", - "ms": "2.1.1" + "jws": "^3.1.5", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1" }, "dependencies": { "ms": { @@ -654,7 +621,7 @@ "requires": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.10", - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "jws": { @@ -662,8 +629,8 @@ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", "requires": { - "jwa": "1.2.0", - "safe-buffer": "5.1.2" + "jwa": "^1.2.0", + "safe-buffer": "^5.0.1" } }, "kuler": { @@ -671,7 +638,7 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", "requires": { - "colornames": "1.1.1" + "colornames": "^1.1.1" } }, "lodash": { @@ -719,11 +686,11 @@ "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", "requires": { - "colors": "1.3.3", - "fast-safe-stringify": "2.0.6", - "fecha": "2.3.3", - "ms": "2.1.1", - "triple-beam": "1.3.0" + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.2.0" }, "dependencies": { "ms": { @@ -738,8 +705,8 @@ "resolved": "http://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.1" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "mime-db": { @@ -752,7 +719,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", "requires": { - "mime-db": "1.36.0" + "mime-db": "~1.36.0" } }, "ms": { @@ -760,15 +727,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" - } - }, "nodemailer": { "version": "4.6.8", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.8.tgz", @@ -824,12 +782,12 @@ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.1", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" } }, "request": { @@ -837,26 +795,26 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.8.0", - "caseless": "0.12.0", - "combined-stream": "1.0.7", - "extend": "3.0.2", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.1.0", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.20", - "oauth-sign": "0.9.0", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.2", - "tough-cookie": "2.4.3", - "tunnel-agent": "0.6.0", - "uuid": "3.3.2" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" } }, "retry": { @@ -884,7 +842,7 @@ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { - "is-arrayish": "0.3.2" + "is-arrayish": "^0.3.1" } }, "sshpk": { @@ -892,15 +850,15 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { - "asn1": "0.2.4", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.2", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.2", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "stack-trace": { @@ -928,8 +886,8 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { - "psl": "1.1.29", - "punycode": "1.4.1" + "psl": "^1.1.24", + "punycode": "^1.4.1" } }, "triple-beam": { @@ -942,7 +900,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -984,30 +942,25 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, - "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" - }, "winston": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", "requires": { - "async": "2.6.1", - "diagnostics": "1.1.1", - "is-stream": "1.1.0", - "logform": "1.10.0", + "async": "^2.6.0", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^1.9.1", "one-time": "0.0.4", - "readable-stream": "2.3.6", - "stack-trace": "0.0.10", - "triple-beam": "1.3.0", - "winston-transport": "4.3.0" + "readable-stream": "^2.3.6", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.2.0" }, "dependencies": { "inherits": { @@ -1025,13 +978,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -1039,7 +992,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } } } @@ -1049,8 +1002,8 @@ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", "requires": { - "readable-stream": "2.3.6", - "triple-beam": "1.3.0" + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" }, "dependencies": { "inherits": { @@ -1068,13 +1021,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -1082,7 +1035,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } } } @@ -1092,7 +1045,7 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", "requires": { - "sax": "0.5.8" + "sax": "0.5.x" } }, "xmlbuilder": { @@ -1110,7 +1063,7 @@ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz", "integrity": "sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==", "requires": { - "zen-observable": "0.8.9" + "zen-observable": "^0.8.0" } } } diff --git a/package.json b/package.json index fa8757b2c..76efddcc2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "azure-storage": "^2.8.2", "dotenv": "^6.0.0", "graphql": "^14.0.2", - "graphql-client": "^2.0.1", "jsonwebtoken": "^8.4.0", "lodash": "^4.17.11", "nodemailer": "^4.6.8", From 49602bf12f9b44b5d1c4fad5684320312d93374a Mon Sep 17 00:00:00 2001 From: "mati108@gmail.com" <34651529+matbenitez@users.noreply.github.com> Date: Wed, 13 Feb 2019 17:25:59 -0300 Subject: [PATCH 04/73] Moving execution update to each execution --- Root.js | 21 ++------------------- TradingBotProcessMainLoop.js | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Root.js b/Root.js index 86486ae54..aed6d7383 100644 --- a/Root.js +++ b/Root.js @@ -1,7 +1,4 @@ -const appRoot = require('app-root-path') -const operationsIntegration = require(`${appRoot}/Integrations/OperationsModuleIntegration`) - -exports.newRoot = function newRoot() { +exports.newRoot = function newRoot() { /* Callbacks default responses. */ @@ -917,21 +914,7 @@ exports.newRoot = function newRoot() { logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); logger.persist(); - } - - // Update operations module with latest context - if (context !== undefined) { - let lastExecution = context.executionHistory[context.executionHistory.length - 1] - let date = lastExecution[0] / 1000 | 0 - let buyAvgRate = lastExecution[1] - let sellAvgRate = lastExecution[2] - let marketRate = lastExecution[7] - let combinedProfitsA = lastExecution[13] - let combinedProfitsB = lastExecution[14] - - operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate, - marketRate, combinedProfitsA, combinedProfitsB) - } + } } } else { diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 31e20790b..e134dd36f 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -8,8 +8,9 @@ let USER_BOT_MODULE; let COMMONS_MODULE; - const BLOB_STORAGE = require(ROOT_DIR + 'BlobStorage'); + const operationsIntegration = require('./Integrations/OperationsModuleIntegration') + const BLOB_STORAGE = require(ROOT_DIR + 'BlobStorage'); const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. @@ -907,12 +908,26 @@ } } - function saveContext() { + async function saveContext() { try { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Entering function."); } + // Update operations module with latest context + let lastExecution = context.newHistoryRecord + let date = lastExecution.date / 1000 | 0 + let buyAvgRate = lastExecution.buyAvgRate + let sellAvgRate = lastExecution.sellAvgRate + let marketRate = lastExecution.marketRate + let combinedProfitsA = lastExecution.combinedProfitsA + let combinedProfitsB = lastExecution.combinedProfitsB + + await operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate, + marketRate, combinedProfitsA, combinedProfitsB) + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Execution Results updated."); } + context.saveThemAll(onFinished); function onFinished(err) { From 8bfe11a902b0669738e9659f101781cd42929c7c Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 15 Feb 2019 10:37:59 -0300 Subject: [PATCH 05/73] Removing logger logs for now --- Integrations/OperationsModuleIntegration.js | 11 +++-------- utils/auth.js | 4 ---- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Integrations/OperationsModuleIntegration.js b/Integrations/OperationsModuleIntegration.js index b8de71616..efdb623ac 100644 --- a/Integrations/OperationsModuleIntegration.js +++ b/Integrations/OperationsModuleIntegration.js @@ -1,13 +1,10 @@ const axios = require('axios') const appRoot = require('app-root-path') -const { logger } = require(`${appRoot}/utils/logger`) const auth = require(`${appRoot}/utils/auth`) exports.updateExecutionResults = async function (summaryDate, buyAverage, sellAverage, marketRate, combinedProfitsA, combinedProfitsB) { - logger.debug('updateExecutionResults -> Entering Function.') - try { const accessToken = await auth.authenticate() @@ -50,12 +47,10 @@ exports.updateExecutionResults = async function (summaryDate, buyAverage, sellAv } }) - if (!operationsResponse.data.errors) - logger.debug('updateExecutionResults -> Operations Module Response: %s', operationsResponse.data.data.operations_UpdateExecutionSummary) - else throw new Error(operationsResponse.data.errors[0].message) + if (operationsResponse.data.errors) + throw new Error(operationsResponse.data.errors[0].message) } catch (error) { - logger.error('updateExecutionResults -> Error: ' + error.stack) - throw new Error('There has been an error updating the execution report: ' + error) + throw new Error('There has been an error updating the execution on the clone: ' + error) } } \ No newline at end of file diff --git a/utils/auth.js b/utils/auth.js index c7f0b8d87..be0145a1f 100644 --- a/utils/auth.js +++ b/utils/auth.js @@ -1,12 +1,9 @@ const axios = require('axios') -const appRoot = require('app-root-path') -const { logger } = require(`${appRoot}/utils/logger`) exports.authenticate = async function () { try { if (!global.ACCESS_TOKEN) { - logger.debug('authenticate -> Entering Function.') const authBody = '{"client_id":"' + process.env.AUTH_CLIENT_ID + '","client_secret": "' + process.env.AUTH_CLIENT_SECRET @@ -33,7 +30,6 @@ exports.authenticate = async function () { return global.ACCESS_TOKEN } catch (error) { - logger.error('authenticate -> Error: ' + error.stack) throw new Error('There has been an error on the authentication: ' + error) } } \ No newline at end of file From 6bc057d8d493f002db9cf5563b4dfaab65258781 Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 12:09:08 -0300 Subject: [PATCH 06/73] Removing app root --- Integrations/OperationsModuleIntegration.js | 3 +-- package-lock.json | 5 ----- package.json | 1 - utils/logger.js | 3 +-- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Integrations/OperationsModuleIntegration.js b/Integrations/OperationsModuleIntegration.js index efdb623ac..43001d62c 100644 --- a/Integrations/OperationsModuleIntegration.js +++ b/Integrations/OperationsModuleIntegration.js @@ -1,6 +1,5 @@ const axios = require('axios') -const appRoot = require('app-root-path') -const auth = require(`${appRoot}/utils/auth`) +const auth = require('../utils/auth') exports.updateExecutionResults = async function (summaryDate, buyAverage, sellAverage, marketRate, combinedProfitsA, combinedProfitsB) { diff --git a/package-lock.json b/package-lock.json index 81321f1c6..72604727b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -134,11 +134,6 @@ "fclone": "^1.0.11" } }, - "app-root-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", - "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=" - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", diff --git a/package.json b/package.json index 76efddcc2..90a19c944 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "license": "ISC", "dependencies": { "apollo-boost": "^0.1.16", - "app-root-path": "^2.1.0", "assert": "^1.4.1", "axios": "^0.18.0", "azure-storage": "^2.8.2", diff --git a/utils/logger.js b/utils/logger.js index 1cc942d0c..da3df770b 100644 --- a/utils/logger.js +++ b/utils/logger.js @@ -1,11 +1,10 @@ const winston = require('winston') -const appRoot = require('app-root-path') const util = require('util') const options = { file: { level: 'info', - filename: `${appRoot}/logs/app.log`, + filename: '../logs/app.log', handleExceptions: true, json: true, maxsize: 5242880, // 5MB From 26df38ea658828ae522d48f3f453d32d1c224cd6 Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 12:09:36 -0300 Subject: [PATCH 07/73] Update execution only when running a clone in cloud --- TradingBotProcessMainLoop.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index e134dd36f..634c1aeff 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -295,7 +295,7 @@ clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_OK_RESPONSE, context); + callBackFunction(global.DEFAULT_OK_RESPONSE); return; } } @@ -347,7 +347,7 @@ clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_OK_RESPONSE, context); + callBackFunction(global.DEFAULT_OK_RESPONSE); return; } } @@ -914,19 +914,21 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Entering function."); } - // Update operations module with latest context - let lastExecution = context.newHistoryRecord - let date = lastExecution.date / 1000 | 0 - let buyAvgRate = lastExecution.buyAvgRate - let sellAvgRate = lastExecution.sellAvgRate - let marketRate = lastExecution.marketRate - let combinedProfitsA = lastExecution.combinedProfitsA - let combinedProfitsB = lastExecution.combinedProfitsB + if (global.CURRENT_EXECUTION_AT === "Cloud") { + // Update operations module with latest context + let lastExecution = context.newHistoryRecord + let date = lastExecution.date / 1000 | 0 + let buyAvgRate = lastExecution.buyAvgRate + let sellAvgRate = lastExecution.sellAvgRate + let marketRate = lastExecution.marketRate + let combinedProfitsA = lastExecution.combinedProfitsA + let combinedProfitsB = lastExecution.combinedProfitsB - await operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate, - marketRate, combinedProfitsA, combinedProfitsB) + await operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate, + marketRate, combinedProfitsA, combinedProfitsB) - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Execution Results updated."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Execution Results updated."); } + } context.saveThemAll(onFinished); @@ -1018,7 +1020,7 @@ clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_OK_RESPONSE, context); + callBackFunction(global.DEFAULT_OK_RESPONSE); return; } From 2b7a824c814cf9e4ce62184e6677bbac296eb900 Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 12:10:09 -0300 Subject: [PATCH 08/73] Using exchangeAPI from the browser --- Exchange/ExchangeAPI.js | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index 3dde860f9..d2c1e7071 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -8,9 +8,6 @@ const _ = require('lodash') const isValidOrder = require('./exchangeUtils').isValidOrder const axios = require('axios') - const appRoot = require('app-root-path') - const auth = require(`${appRoot}/utils/auth`) - let MODULE_NAME = "Exchange API"; let thisObject = { @@ -34,14 +31,11 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - // TODO integrate with financial beings module to get the exchange let botExchange = 'Poloniex'; let exchange = botExchange.toLowerCase() + 'Client.js'; - let api = require('./wrappers/' + exchange); + let api = require('./Wrappers/' + exchange); - const accessToken = await auth.authenticate() - - let keyVaultAPI = createKeyVaultAPIClient(accessToken) + let keyVaultAPI = createKeyVaultAPIClient() apiClient = api.newAPIClient(keyVaultAPI, logger); callBackFunction(global.DEFAULT_OK_RESPONSE); @@ -52,9 +46,23 @@ } } - function createKeyVaultAPIClient(authToken) { + function createKeyVaultAPIClient() { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Entering function."); } + let accessToken + let keyId + let cloneId + if (global.CURRENT_EXECUTION_AT === "Cloud") { + keyId = process.env.KEY_ID + cloneId = process.env.CLONE_ID + + let auth = require('../utils/auth') + let authToken = await auth.authenticate() + accessToken = 'Bearer ' + authToken + } else if (global.CURRENT_EXECUTION_AT === "Browser") { + accessToken = window.localStorage.getItem('access_token') + } + const keyVaultAPI = {} keyVaultAPI.signTransaction = function (transaction, next) { axios({ @@ -62,8 +70,8 @@ method: 'post', data: { query: ` - mutation keyVault_SignTransaction($keyId: String!, $cloneId: String!, $transaction: String!){ - keyVault_SignTransaction(keyId: $keyId, cloneId: $cloneId, transaction: $transaction){ + mutation keyVault_SignTransaction($transaction: String!, $keyId: String, $cloneId: String){ + keyVault_SignTransaction(transaction: $transaction, keyId: $keyId, cloneId: $cloneId){ key, signature, date @@ -71,13 +79,13 @@ } `, variables: { - keyId: process.env.KEY_ID, - cloneId: process.env.CLONE_ID, - transaction: transaction + transaction: transaction, + keyId: keyId, + cloneId: cloneId } }, headers: { - authorization: 'Bearer ' + authToken + authorization: accessToken } }).then(res => { From c05319061f0f577c7e8f94f7b6fe5e6c30c22078 Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 12:10:49 -0300 Subject: [PATCH 09/73] Updating browser execution configuration --- Root.js | 90 +++++++++++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/Root.js b/Root.js index aed6d7383..54f0992c0 100644 --- a/Root.js +++ b/Root.js @@ -341,53 +341,27 @@ if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> listItem.process = " + listItem.process); } let processConfig = botConfig.processes[i]; - processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration - try { - - /* - - When running at the browser, the endUser can override the configured setting for the bot. In this scenario we use the commands - sent from the User Interface. - - */ - - if (UI_COMMANDS.startMode !== undefined) { - - switch (UI_COMMANDS.startMode) { - - case "Backtest": { - - processConfig.startMode.backtest.run = "true"; - processConfig.startMode.live.run = "false"; - processConfig.startMode.competition.run = "false"; - - break; - } - - case "Live": { - - processConfig.startMode.backtest.run = "false"; - processConfig.startMode.live.run = "true"; - processConfig.startMode.competition.run = "false"; - - break; - } - - case "Competition": { - - processConfig.startMode.backtest.run = "false"; - processConfig.startMode.live.run = "false"; - processConfig.startMode.competition.run = "true"; - - break; - } - } - - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode Overwritten. "); } - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> processConfig.startMode = " + processConfig.startMode); } - + + switch (global.CURRENT_EXECUTION_AT) { + case "Cloud": { + processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration + break; } + case "Browser": { + let startMode = { + live: { run: "false" }, + backtest: { run: "false" }, + competition: { run: "false" } + } + let browserStartMode = global.CURRENT_START_MODE.toLowerCase() + startMode[browserStartMode].run = "true" + processConfig.startMode = startMode + break; + } + } + try { + /* We test each type of start Mode to get what to run and how. */ if (processConfig.startMode.allMonths !== undefined) { @@ -525,7 +499,7 @@ if (processConfig.startMode.live !== undefined) { - if (processConfig.startMode.live.run === "true" && global.EXECUTION_CONFIG.startMode.live.run === "true") { + if (processConfig.startMode.live.run === "true") { botConfig.startMode = "Live"; console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); @@ -533,7 +507,7 @@ let month = pad((new Date()).getUTCMonth() + 1, 2); let year = (new Date()).getUTCFullYear(); - if (processConfig.startMode.live.resumeExecution === "true" && global.EXECUTION_CONFIG.startMode.live.resumeExecution === "true") { + if (processConfig.startMode.live.resumeExecution === "true") { botConfig.hasTheBotJustStarted = false; } else { botConfig.hasTheBotJustStarted = true; @@ -553,7 +527,7 @@ if (processConfig.startMode.backtest !== undefined) { - if (processConfig.startMode.backtest.run === "true" && global.EXECUTION_CONFIG.startMode.backtest.run === "true") { + if (processConfig.startMode.backtest.run === "true") { botConfig.startMode = "Backtest"; console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); @@ -583,14 +557,14 @@ if (processConfig.startMode.competition !== undefined) { - if (processConfig.startMode.competition.run === "true" && global.EXECUTION_CONFIG.startMode.competition.run === "true") { + if (processConfig.startMode.competition.run === "true") { botConfig.startMode = "Competition"; console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); botConfig.competition = processConfig.startMode.competition; - if (processConfig.startMode.competition.resumeExecution === "false" && global.EXECUTION_CONFIG.startMode.competition.resumeExecution === "false") { + if (processConfig.startMode.competition.resumeExecution === "false") { botConfig.hasTheBotJustStarted = true; } else { botConfig.hasTheBotJustStarted = false; @@ -838,7 +812,11 @@ } - let clonName = botConfig.codeName + "-" + "Clon" + clonKey + "-" + process.env.CLONE_ID; + let clonName = botConfig.codeName + "-" + "Clon" + clonKey; + + if (global.CURRENT_EXECUTION_AT === "Cloud") { + clonName += "-" + process.env.CLONE_ID; + } botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; @@ -858,8 +836,12 @@ /* If the bot does not have any genes at all */ let genes = {}; - let clonName = botConfig.codeName + "-" + process.env.CLONE_ID; + let clonName = botConfig.codeName; + if (global.CURRENT_EXECUTION_AT === "Cloud") { + clonName += "-" + process.env.CLONE_ID; + } + botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; pBotConfig.instance = clonName; @@ -889,7 +871,7 @@ tradingBotMainLoop.run(pGenes, pTotalInstances, whenRunFinishes); - function whenRunFinishes(err, context) { + function whenRunFinishes(err) { pBotConfig.loopCounter = 0; @@ -937,7 +919,7 @@ console.log(logDisplace + "Root : [ERROR] start -> findProcess -> err.message = " + err.message); return; } - } + } } } } From 4cc17c19f8e7a028ba160a150764ae599bbb3986 Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 12:27:05 -0300 Subject: [PATCH 10/73] lowercase folder name --- Exchange/ExchangeAPI.js | 2 +- Project.njsproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index d2c1e7071..87a951530 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -33,7 +33,7 @@ let botExchange = 'Poloniex'; let exchange = botExchange.toLowerCase() + 'Client.js'; - let api = require('./Wrappers/' + exchange); + let api = require('./wrappers/' + exchange); let keyVaultAPI = createKeyVaultAPIClient() apiClient = api.newAPIClient(keyVaultAPI, logger); diff --git a/Project.njsproj b/Project.njsproj index fe4d8f923..9edd19db5 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -91,7 +91,7 @@ - + From fd16e2700c84667b72cdeba8a1b7e9af576b25f8 Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 19:15:07 -0300 Subject: [PATCH 11/73] Keys integration cloud and browser --- Exchange/ExchangeAPI.js | 36 ++++++++++++++++----------------- ExtractionBotProcessMainLoop.js | 2 +- Root.js | 2 +- TradingBotProcessMainLoop.js | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index 87a951530..3129473d6 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -1,4 +1,4 @@ -exports.newExchangeAPI = function newExchangeAPI(bot, logger) { +exports.newExchangeAPI = function newExchangeAPI(logger, authToken) { /* @@ -35,7 +35,21 @@ let exchange = botExchange.toLowerCase() + 'Client.js'; let api = require('./wrappers/' + exchange); - let keyVaultAPI = createKeyVaultAPIClient() + let accessToken + let keyId + let cloneId + if (global.CURRENT_EXECUTION_AT === "Cloud") { + keyId = process.env.KEY_ID + cloneId = process.env.CLONE_ID + + let auth = require('../utils/auth') + let authTokenCloud = await auth.authenticate() + accessToken = 'Bearer ' + authTokenCloud + } else if (global.CURRENT_EXECUTION_AT === "Browser") { + accessToken = 'Bearer ' + authToken + } + + let keyVaultAPI = createKeyVaultAPIClient(accessToken, keyId, cloneId) apiClient = api.newAPIClient(keyVaultAPI, logger); callBackFunction(global.DEFAULT_OK_RESPONSE); @@ -46,23 +60,9 @@ } } - function createKeyVaultAPIClient() { + function createKeyVaultAPIClient(accessToken, keyId, cloneId) { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Entering function."); } - - let accessToken - let keyId - let cloneId - if (global.CURRENT_EXECUTION_AT === "Cloud") { - keyId = process.env.KEY_ID - cloneId = process.env.CLONE_ID - - let auth = require('../utils/auth') - let authToken = await auth.authenticate() - accessToken = 'Bearer ' + authToken - } else if (global.CURRENT_EXECUTION_AT === "Browser") { - accessToken = window.localStorage.getItem('access_token') - } - + const keyVaultAPI = {} keyVaultAPI.signTransaction = function (transaction, next) { axios({ diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index e3caf7318..81b4b90a5 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -275,7 +275,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } - exchangeAPI = EXCHANGE_API.newExchangeAPI(bot, logger); + exchangeAPI = EXCHANGE_API.newExchangeAPI(logger); exchangeAPI.initialize(onInizialized); diff --git a/Root.js b/Root.js index 54f0992c0..e70a63ece 100644 --- a/Root.js +++ b/Root.js @@ -350,7 +350,7 @@ case "Browser": { let startMode = { live: { run: "false" }, - backtest: { run: "false" }, + backtest: { run: "false", waitTime: 5000 }, competition: { run: "false" } } let browserStartMode = global.CURRENT_START_MODE.toLowerCase() diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 634c1aeff..4e90cc9de 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -617,7 +617,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } - exchangeAPI = EXCHANGE_API.newExchangeAPI(bot, logger); + exchangeAPI = EXCHANGE_API.newExchangeAPI(logger); exchangeAPI.initialize(onInizialized); From c246f57c7d4c39f3011c9e0dea10b40135d028ec Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 16 Feb 2019 21:21:05 -0300 Subject: [PATCH 12/73] Removing email notification --- TradingBotProcessMainLoop.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 4e90cc9de..85ac5cab1 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -864,8 +864,7 @@ clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - assistant.sendEmail("FAIL", "Operation Failed. Aborting the process. err = " + err.message, emailList = global.EMAIL_CONFIG.adminList); + bot.enableCheckLoopHealth = false; callBackFunction(err); return; } @@ -878,7 +877,6 @@ clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); bot.enableCheckLoopHealth = false; - assistant.sendEmail("FAIL", "Operation Failed. Aborting the process. err = " + err.message, emailList = global.EMAIL_CONFIG.adminList); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } @@ -891,7 +889,6 @@ clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); bot.enableCheckLoopHealth = false; - assistant.sendEmail("FAIL", "Operation Failed. Aborting the process. err = " + err.message, emailList = global.EMAIL_CONFIG.adminList); callBackFunction(err); } } @@ -903,7 +900,6 @@ clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); bot.enableCheckLoopHealth = false; - assistant.sendEmail("FAIL", "Operation Failed. Aborting the process. err = " + err.message, emailList = global.EMAIL_CONFIG.adminList); callBackFunction(err); } } From 784445bafc740c1047c01880ceb3d238a52189d2 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 18 Feb 2019 14:46:52 +0100 Subject: [PATCH 13/73] Error text improved --- Run.js | 1 + package-lock.json | 330 +++++++++++++++++++++++----------------------- this.config.json | 7 + 3 files changed, 173 insertions(+), 165 deletions(-) diff --git a/Run.js b/Run.js index 2abe7cb4c..1f79b005c 100644 --- a/Run.js +++ b/Run.js @@ -130,6 +130,7 @@ function readExecutionConfiguration() { catch (err) { console.log("[ERROR] readExecutionConfiguration -> err = " + err.message); + console.log("[ERROR] readExecutionConfiguration -> Please verify that the Start Mode for the type of Bot configured applies to that type."); console.log("[ERROR] readExecutionConfiguration -> err = " + err.stack); } } diff --git a/package-lock.json b/package-lock.json index 72604727b..6bba6e4e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,10 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "apollo-boost": { @@ -31,14 +31,14 @@ "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.1.16.tgz", "integrity": "sha512-ppnQr90n2cn0ZMveEbqxW6NxmskIpThiLziLlRpRLy4keoAICg1NZecxJQmeaBLMtyhf5UholAjpS2SLmEJeHg==", "requires": { - "apollo-cache": "^1.1.17", - "apollo-cache-inmemory": "^1.2.10", - "apollo-client": "^2.4.2", - "apollo-link": "^1.0.6", - "apollo-link-error": "^1.0.3", - "apollo-link-http": "^1.3.1", - "apollo-link-state": "^0.4.0", - "graphql-tag": "^2.4.2" + "apollo-cache": "1.1.17", + "apollo-cache-inmemory": "1.2.10", + "apollo-client": "2.4.2", + "apollo-link": "1.2.3", + "apollo-link-error": "1.1.1", + "apollo-link-http": "1.5.5", + "apollo-link-state": "0.4.2", + "graphql-tag": "2.10.0" } }, "apollo-cache": { @@ -46,7 +46,7 @@ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.17.tgz", "integrity": "sha512-7sp24n2HZO4vXgTaKNomLyIfGxG4gDdDkBB0jkRzRi7HhnKmfwhiF/RCiKNbgLdrPX151INdls0KwIVliD0dHQ==", "requires": { - "apollo-utilities": "^1.0.21" + "apollo-utilities": "1.0.21" } }, "apollo-cache-inmemory": { @@ -54,9 +54,9 @@ "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.2.10.tgz", "integrity": "sha512-eBusPFVtYIuo+PIfJdAwUCQ4cs7AJ4mB7sTdXxNQCXToYw8mzE6EfHnV37kdVfBXSaa82BzE2rb/YUq/duuamw==", "requires": { - "apollo-cache": "^1.1.17", - "apollo-utilities": "^1.0.21", - "graphql-anywhere": "^4.1.19" + "apollo-cache": "1.1.17", + "apollo-utilities": "1.0.21", + "graphql-anywhere": "4.1.19" } }, "apollo-client": { @@ -65,13 +65,13 @@ "integrity": "sha512-g1z23umaVSoKLj9xNl0aAnk2KBF4JeBi7MeKFc9CGTixH7TkqeQUQtxcjrC7j2h4KmDbuhOAHOFUGf8YshN+ag==", "requires": { "@types/async": "2.0.49", - "@types/zen-observable": "^0.8.0", + "@types/zen-observable": "0.8.0", "apollo-cache": "1.1.17", - "apollo-link": "^1.0.0", - "apollo-link-dedup": "^1.0.0", + "apollo-link": "1.2.3", + "apollo-link-dedup": "1.0.10", "apollo-utilities": "1.0.21", - "symbol-observable": "^1.0.2", - "zen-observable": "^0.8.0" + "symbol-observable": "1.2.0", + "zen-observable": "0.8.9" } }, "apollo-link": { @@ -79,8 +79,8 @@ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.3.tgz", "integrity": "sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==", "requires": { - "apollo-utilities": "^1.0.0", - "zen-observable-ts": "^0.8.10" + "apollo-utilities": "1.0.21", + "zen-observable-ts": "0.8.10" } }, "apollo-link-dedup": { @@ -88,7 +88,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz", "integrity": "sha512-tpUI9lMZsidxdNygSY1FxflXEkUZnvKRkMUsXXuQUNoSLeNtEvUX7QtKRAl4k9ubLl8JKKc9X3L3onAFeGTK8w==", "requires": { - "apollo-link": "^1.2.3" + "apollo-link": "1.2.3" } }, "apollo-link-error": { @@ -96,7 +96,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-error/-/apollo-link-error-1.1.1.tgz", "integrity": "sha512-/yPcaQWcBdB94vpJ4FsiCJt1dAGGRm+6Tsj3wKwP+72taBH+UsGRQQZk7U/1cpZwl1yqhHZn+ZNhVOebpPcIlA==", "requires": { - "apollo-link": "^1.2.3" + "apollo-link": "1.2.3" } }, "apollo-link-http": { @@ -104,8 +104,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.5.tgz", "integrity": "sha512-C5N6N/mRwmepvtzO27dgMEU3MMtRKSqcljBkYNZmWwH11BxkUQ5imBLPM3V4QJXNE7NFuAQAB5PeUd4ligivTQ==", "requires": { - "apollo-link": "^1.2.3", - "apollo-link-http-common": "^0.2.5" + "apollo-link": "1.2.3", + "apollo-link-http-common": "0.2.5" } }, "apollo-link-http-common": { @@ -113,7 +113,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.5.tgz", "integrity": "sha512-6FV1wr5AqAyJ64Em1dq5hhGgiyxZE383VJQmhIoDVc3MyNcFL92TkhxREOs4rnH2a9X2iJMko7nodHSGLC6d8w==", "requires": { - "apollo-link": "^1.2.3" + "apollo-link": "1.2.3" } }, "apollo-link-state": { @@ -121,8 +121,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-state/-/apollo-link-state-0.4.2.tgz", "integrity": "sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw==", "requires": { - "apollo-utilities": "^1.0.8", - "graphql-anywhere": "^4.1.0-alpha.0" + "apollo-utilities": "1.0.21", + "graphql-anywhere": "4.1.19" } }, "apollo-utilities": { @@ -130,8 +130,8 @@ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.21.tgz", "integrity": "sha512-ZcxELlEl+sDCYBgEMdNXJAsZtRVm8wk4HIA58bMsqYfd1DSAJQEtZ93F0GZgYNAGy3QyaoBeZtbb0/01++G8JQ==", "requires": { - "fast-json-stable-stringify": "^2.0.0", - "fclone": "^1.0.11" + "fast-json-stable-stringify": "2.0.0", + "fclone": "1.0.11" } }, "asn1": { @@ -139,7 +139,7 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert": { @@ -160,7 +160,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "asynckit": { @@ -183,8 +183,8 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { - "follow-redirects": "^1.3.0", - "is-buffer": "^1.1.5" + "follow-redirects": "1.6.1", + "is-buffer": "1.1.6" } }, "azure-storage": { @@ -192,17 +192,17 @@ "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.2.tgz", "integrity": "sha512-pOyGPya9+NDpAfm5YcFfklo57HfjDbYLXxs4lomPwvRxmb0Di/A+a+RkUmEFzaQ8S13CqxK40bRRB0sjj2ZQxA==", "requires": { - "browserify-mime": "~1.2.9", - "extend": "^3.0.2", + "browserify-mime": "1.2.9", + "extend": "3.0.2", "json-edm-parser": "0.1.2", "md5.js": "1.3.4", - "readable-stream": "~2.0.0", - "request": "^2.86.0", - "underscore": "~1.8.3", - "uuid": "^3.0.0", - "validator": "~9.4.1", + "readable-stream": "2.0.6", + "request": "2.88.0", + "underscore": "1.8.3", + "uuid": "3.3.2", + "validator": "9.4.1", "xml2js": "0.2.8", - "xmlbuilder": "^9.0.7" + "xmlbuilder": "9.0.7" }, "dependencies": { "underscore": { @@ -218,7 +218,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "browserify-mime": { @@ -246,8 +246,8 @@ "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-convert": "1.9.3", + "color-string": "1.5.3" } }, "color-convert": { @@ -268,8 +268,8 @@ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" } }, "colornames": { @@ -287,8 +287,8 @@ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" + "color": "3.0.0", + "text-hex": "1.0.0" } }, "combined-stream": { @@ -296,7 +296,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "core-util-is": { @@ -309,7 +309,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "debug": { @@ -330,9 +330,9 @@ "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" + "colorspace": "1.1.1", + "enabled": "1.0.2", + "kuler": "1.0.1" } }, "dotenv": { @@ -346,8 +346,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "ecdsa-sig-formatter": { @@ -355,7 +355,7 @@ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "enabled": { @@ -363,7 +363,7 @@ "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", "requires": { - "env-variable": "0.0.x" + "env-variable": "0.0.5" } }, "env-variable": { @@ -411,7 +411,7 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "requires": { - "debug": "=3.1.0" + "debug": "3.1.0" } }, "forever-agent": { @@ -424,9 +424,9 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "^0.4.0", + "asynckit": "0.4.0", "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "mime-types": "2.1.20" }, "dependencies": { "combined-stream": { @@ -434,7 +434,7 @@ "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } } } @@ -444,7 +444,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "graphql": { @@ -452,7 +452,7 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", "requires": { - "iterall": "^1.2.2" + "iterall": "1.2.2" } }, "graphql-anywhere": { @@ -460,7 +460,7 @@ "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-4.1.19.tgz", "integrity": "sha512-mQlvbECzYPBcgBC9JsdM4v+DSvNmcIP+8Vwr+ij3gktbaLSE0Iza30mztuz40Jlf7ooMs+0emBZucNjLzqz7tA==", "requires": { - "apollo-utilities": "^1.0.21" + "apollo-utilities": "1.0.21" } }, "graphql-tag": { @@ -478,8 +478,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "hash-base": { @@ -487,8 +487,8 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "2.0.1", + "safe-buffer": "5.1.2" } }, "http-signature": { @@ -496,9 +496,9 @@ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" } }, "inherits": { @@ -552,7 +552,7 @@ "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", "requires": { - "jsonparse": "~1.2.0" + "jsonparse": "1.2.0" } }, "json-schema": { @@ -580,15 +580,15 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", "requires": { - "jws": "^3.1.5", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1" + "jws": "3.2.1", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.1.1" }, "dependencies": { "ms": { @@ -616,7 +616,7 @@ "requires": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.10", - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "jws": { @@ -624,8 +624,8 @@ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", "requires": { - "jwa": "^1.2.0", - "safe-buffer": "^5.0.1" + "jwa": "1.2.0", + "safe-buffer": "5.1.2" } }, "kuler": { @@ -633,7 +633,7 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", "requires": { - "colornames": "^1.1.1" + "colornames": "1.1.1" } }, "lodash": { @@ -681,11 +681,11 @@ "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.2.0" + "colors": "1.3.3", + "fast-safe-stringify": "2.0.6", + "fecha": "2.3.3", + "ms": "2.1.1", + "triple-beam": "1.3.0" }, "dependencies": { "ms": { @@ -700,8 +700,8 @@ "resolved": "http://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "3.0.4", + "inherits": "2.0.1" } }, "mime-db": { @@ -714,7 +714,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", "requires": { - "mime-db": "~1.36.0" + "mime-db": "1.36.0" } }, "ms": { @@ -777,12 +777,12 @@ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" } }, "request": { @@ -790,26 +790,26 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" } }, "retry": { @@ -837,7 +837,7 @@ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { - "is-arrayish": "^0.3.1" + "is-arrayish": "0.3.2" } }, "sshpk": { @@ -845,15 +845,15 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "stack-trace": { @@ -881,8 +881,8 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "1.1.29", + "punycode": "1.4.1" } }, "triple-beam": { @@ -895,7 +895,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -937,9 +937,9 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "winston": { @@ -947,15 +947,15 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", "requires": { - "async": "^2.6.0", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^1.9.1", + "async": "2.6.1", + "diagnostics": "1.1.1", + "is-stream": "1.1.0", + "logform": "1.10.0", "one-time": "0.0.4", - "readable-stream": "^2.3.6", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.2.0" + "readable-stream": "2.3.6", + "stack-trace": "0.0.10", + "triple-beam": "1.3.0", + "winston-transport": "4.3.0" }, "dependencies": { "inherits": { @@ -973,13 +973,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -987,7 +987,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -997,8 +997,8 @@ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", "requires": { - "readable-stream": "^2.3.6", - "triple-beam": "^1.2.0" + "readable-stream": "2.3.6", + "triple-beam": "1.3.0" }, "dependencies": { "inherits": { @@ -1016,13 +1016,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -1030,7 +1030,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -1040,7 +1040,7 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", "requires": { - "sax": "0.5.x" + "sax": "0.5.8" } }, "xmlbuilder": { @@ -1058,7 +1058,7 @@ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz", "integrity": "sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==", "requires": { - "zen-observable": "^0.8.0" + "zen-observable": "0.8.9" } } } diff --git a/this.config.json b/this.config.json index d4a37b864..9f33a2962 100644 --- a/this.config.json +++ b/this.config.json @@ -47,6 +47,13 @@ "bot": "AAOlivia", "process": "Multi-Period-Market", "repo": "AAOlivia-Indicator-Bot" + }, + { + "enabled": "true", + "devTeam": "AAMasters", + "bot": "AAChris", + "process": "Multi-Period-Market", + "repo": "AAOlivia-Indicator-Bot" } ], "stopGracefully": false, From db65c47b8d51a536906df61fd92f63401c8f9357 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Thu, 21 Feb 2019 14:32:54 +0100 Subject: [PATCH 14/73] Some helper code to load the bot code from the file system for local testing --- CloudRequire.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/CloudRequire.js b/CloudRequire.js index 1597614d5..7bc874962 100644 --- a/CloudRequire.js +++ b/CloudRequire.js @@ -38,7 +38,28 @@ let USER_BOT_MODULE = {}; USER_BOT_MODULE.newUserBot = eval(text); - callBackFunction(global.DEFAULT_OK_RESPONSE, USER_BOT_MODULE); + /* + This following code is to load the bot code from a file on the file system. + It is useful for when you are activelly changing the code and dont wont to upload it to the storage at every run + */ + + /* + let fs = require('fs'); + try { + let fileName = "C:/Users/Luis/source/repos/Bots/AAMasters/AAChris-Indicator-Bot/Multi-Period-Daily/User.Bot.js"; + fs.readFile(fileName, onFileRead); + + function onFileRead(err, file) { + let fileString = file.toString(); + USER_BOT_MODULE.newUserBot = eval(fileString); + callBackFunction(global.DEFAULT_OK_RESPONSE, USER_BOT_MODULE); + } + } + catch(err) { + console.log("ERROR LOADING FILE FROM FILE SYSTEM"); + } + */ + callBackFunction(global.DEFAULT_OK_RESPONSE, USER_BOT_MODULE); // Coment this when loading from file system. } catch (err) { logger.write(MODULE_NAME, "[ERROR] downloadBot -> onFileReceived -> err.message = " + err.message); From 866137040b62d1c713b086aa41059939ba5e4b44 Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 22 Feb 2019 18:07:03 -0300 Subject: [PATCH 15/73] Hardcoded bot version --- Root.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Root.js b/Root.js index e70a63ece..17ca233a9 100644 --- a/Root.js +++ b/Root.js @@ -813,6 +813,7 @@ } let clonName = botConfig.codeName + "-" + "Clon" + clonKey; + clonName += ".1.0"; if (global.CURRENT_EXECUTION_AT === "Cloud") { clonName += "-" + process.env.CLONE_ID; @@ -842,6 +843,8 @@ clonName += "-" + process.env.CLONE_ID; } + clonName += ".1.0"; + botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; pBotConfig.instance = clonName; From 17036c6cc8b38021a567ff6f59bcdae615d52118 Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 22 Feb 2019 18:12:52 -0300 Subject: [PATCH 16/73] Ignored files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7ab8c3a90..d9ffcb1be 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ configs/Email.Config.json configs/User.Profile.json configs/Execution.Config.json configs/Secret.Keys.json -.env +*.env +*.vscode* \ No newline at end of file From a2db8302272fbce59a9f9868216f0b12cec4c458 Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 5 Mar 2019 18:23:07 -0300 Subject: [PATCH 17/73] Correcting bot type name --- Run.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Run.js b/Run.js index 1f79b005c..0b8d69e0a 100644 --- a/Run.js +++ b/Run.js @@ -80,7 +80,7 @@ function readExecutionConfiguration() { backtest: backtest, competition: competition } - } else if (process.env.TYPE === 'Indicator' || process.env.TYPE === 'Extractor') { + } else if (process.env.TYPE === 'Indicator' || process.env.TYPE === 'Extraction') { let allMonths = { run: "false", minYear: process.env.MIN_YEAR, @@ -136,8 +136,6 @@ function readExecutionConfiguration() { } function readStoragePermissions() { - let filePath; - try { console.log( "[INFO] Run -> readStoragePermissions -> Entering function. "); @@ -187,10 +185,8 @@ function readStoragePermissions() { startRoot(); } - } - catch (err) { + } catch (err) { console.log("[ERROR] Run -> readStoragePermissions -> err = " + err.message); - console.log("[HINT] Run -> readStoragePermissions -> You need to have a file at this path -> " + filePath); } } From fc59aa290cac449b51407c96f3996e6b0e77d034 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 11 Mar 2019 14:11:45 +0100 Subject: [PATCH 18/73] Failure to update Clones Module does not stop trading bot execution. --- TradingBotProcessMainLoop.js | 55 ++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 85ac5cab1..9d6e6cab5 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -904,28 +904,12 @@ } } - async function saveContext() { + function saveContext() { try { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Entering function."); } - if (global.CURRENT_EXECUTION_AT === "Cloud") { - // Update operations module with latest context - let lastExecution = context.newHistoryRecord - let date = lastExecution.date / 1000 | 0 - let buyAvgRate = lastExecution.buyAvgRate - let sellAvgRate = lastExecution.sellAvgRate - let marketRate = lastExecution.marketRate - let combinedProfitsA = lastExecution.combinedProfitsA - let combinedProfitsB = lastExecution.combinedProfitsB - - await operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate, - marketRate, combinedProfitsA, combinedProfitsB) - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> Execution Results updated."); } - } - context.saveThemAll(onFinished); function onFinished(err) { @@ -938,7 +922,7 @@ case global.DEFAULT_OK_RESPONSE.result: { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> onFinished -> Execution finished well."); } nextWaitTime = 'Normal'; - loopControl(nextWaitTime); + updateClonesModule(); return; } case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. @@ -997,6 +981,41 @@ } } + async function updateClonesModule() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> updateClonesModule -> Entering function."); } + + if (global.CURRENT_EXECUTION_AT === "Cloud") { + + // Update clones module with latest context informations + + let lastExecution = context.newHistoryRecord + let date = lastExecution.date / 1000 | 0 + let buyAvgRate = lastExecution.buyAvgRate + let sellAvgRate = lastExecution.sellAvgRate + let marketRate = lastExecution.marketRate + let combinedProfitsA = lastExecution.combinedProfitsA + let combinedProfitsB = lastExecution.combinedProfitsB + + await operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate, + marketRate, combinedProfitsA, combinedProfitsB) + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> updateClonesModule -> Clones Module Updated."); } + } + + nextWaitTime = 'Normal'; + loopControl(nextWaitTime); + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> Execution will continue anyways. "); + nextWaitTime = 'Normal'; + loopControl(nextWaitTime); + } + } + function loopControl(nextWaitTime) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); } From 1324881882135368f9ed65fbb79010e06e493a96 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 08:51:30 +0100 Subject: [PATCH 19/73] Data Dependencies implemented on Indicator Loop --- DataDependencies.js | 7 +++ IndicatorBotProcessMainLoop.js | 81 +++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/DataDependencies.js b/DataDependencies.js index db08c5a77..0660226b9 100644 --- a/DataDependencies.js +++ b/DataDependencies.js @@ -23,6 +23,13 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + if (pDataDependenciesConfig === undefined) { + + // We allow old indicators not to declare their data dependencies. + + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + } /* For each dependency declared at the bot config, we will initialize a DataSet as part of this initialization process. diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 5ed0969df..88347779d 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -175,6 +175,8 @@ const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies'); + const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies'); + const DATA_SET = require(ROOT_DIR + 'DataSet'); /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ @@ -189,6 +191,7 @@ let userBot; let statusDependencies; + let dataDependencies; let nextWaitTime; @@ -213,7 +216,7 @@ switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> onInizialized -> Execution finished well."); - initializeUserBot(); + initializeDataDependencies(); return; } case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. @@ -269,6 +272,80 @@ } } + function initializeDataDependencies() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> Entering function."); } + + dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET, BLOB_STORAGE, UTILITIES); + + dataDependencies.initialize(processConfig.dataDependencies, onInizialized); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); } + initializeUserBot(); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err.message = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + function initializeUserBot() { try { @@ -277,7 +354,7 @@ usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); - usertBot.initialize(statusDependencies, pMonth, pYear, onInizialized); + usertBot.initialize(statusDependencies, pMonth, pYear, onInizialized, dataDependencies); function onInizialized(err) { From 9c92069b5d07d753dbbcebdc2d6ae7a686950045 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 09:50:23 +0100 Subject: [PATCH 20/73] Framework for Multi Period Market Processes added. INitializar Function ready --- Multi-Period-Market.js | 924 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 924 insertions(+) create mode 100644 Multi-Period-Market.js diff --git a/Multi-Period-Market.js b/Multi-Period-Market.js new file mode 100644 index 000000000..75e4236c7 --- /dev/null +++ b/Multi-Period-Market.js @@ -0,0 +1,924 @@ +exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, FILE_STORAGE) { + + const FULL_LOG = true; + const LOG_FILE_CONTENT = false; + + const MODULE_NAME = "User Bot"; + + const EXCHANGE_NAME = "Poloniex"; + + const LRC_FOLDER_NAME = "LRC-Points"; + const PERCENTAGE_BANDWIDTH_FOLDER_NAME = "Percentage-Bandwidth"; + const BOLLINGER_BANDS_FOLDER_NAME = "Bollinger-Bands"; + const BOLLINGER_CHANNELS_FOLDER_NAME = "Bollinger-Channels"; + const BOLLINGER_SUB_CHANNELS_FOLDER_NAME = "Bollinger-Sub-Channels"; + const CANDLES_FOLDER_NAME = "Candles"; + const SIMULATED_RECORDS_FOLDER_NAME = "Trading-Simulation"; + const CONDITIONS_FOLDER_NAME = "Simulation-Conditions"; + + const commons = COMMONS.newCommons(bot, logger, UTILITIES); + + thisObject = { + initialize: initialize, + start: start + }; + + let gaussStorage = BLOB_STORAGE.newBlobStorage(bot, logger); + let chrisStorage = BLOB_STORAGE.newBlobStorage(bot, logger); + let oliviaStorage = BLOB_STORAGE.newBlobStorage(bot, logger); + let jasonStorage = BLOB_STORAGE.newBlobStorage(bot, logger); + + let utilities = UTILITIES.newCloudUtilities(bot, logger); + + let statusDependencies; + let dataDependencies; + let storages = []; + + return thisObject; + + function initialize(pStatusDependencies, pDataDependencies, pMonth, pYear, callBackFunction) { + + try { + + logger.fileName = MODULE_NAME; + logger.initialize(); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + + statusDependencies = pStatusDependencies; + dataDependencies = pDataDependencies; + + for (let i = 0; i < dataDependencies.length; i++) { + + let key; + let storage; + + key = dataDependencies.devTeam + "-" + + dataDependencies.bot + "-" + + dataDependencies.product + "-" + + dataDependencies.dataSet + "-" + + dataDependencies.dataSetVersion + + storage = dataDependencies.dataSets.get(key); + + storages.push(storage); + + } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + + + function start(callBackFunction) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); } + + let market = global.MARKET; + + buildRecords(); + + function buildRecords() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> Entering function."); } + + try { + + let n; + + periodsLoop(); + + function periodsLoop() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> periodsLoop -> Entering function."); } + + /* + + We will iterate through all posible periods. + + */ + + n = 0 // loop Variable representing each possible period as defined at the periods array. + + loopBody(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> periodsLoop -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function loopBody() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> Entering function."); } + + const outputPeriod = global.marketFilesPeriods[n][0]; + const timePeriod = global.marketFilesPeriods[n][1]; + + let marketFile; + + + + + + + + let LRCMap = new Map(); + let percentageBandwidthMap = new Map(); + let bollingerBandsMap = new Map(); + let bollingerChannelsArray = []; + let bollingerSubChannelsArray = []; + + let candles = []; + let recordsArray = []; + let conditionsArray = []; + let simulationLogic = {}; + + nextLRC(); + + function nextLRC() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextLRC -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = "AAVikings" + "/" + "AAGauss" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + LRC_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + gaussStorage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + marketFile = JSON.parse(text); + + buildLRC(); + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextLRC -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildLRC() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildLRC -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < marketFile.length; i++) { + + let LRC = { + begin: marketFile[i][0], + end: marketFile[i][1], + _15: marketFile[i][2], + _30: marketFile[i][3], + _60: marketFile[i][4] + }; + + if (previous !== undefined) { + + if (previous._15 > LRC._15) { LRC.direction15 = 'down'; } + if (previous._15 < LRC._15) { LRC.direction15 = 'up'; } + if (previous._15 === LRC._15) { LRC.direction15 = 'side'; } + + if (previous._30 > LRC._30) { LRC.direction30 = 'down'; } + if (previous._30 < LRC._30) { LRC.direction30 = 'up'; } + if (previous._30 === LRC._30) { LRC.direction30 = 'side'; } + + if (previous._60 > LRC._60) { LRC.direction60 = 'down'; } + if (previous._60 < LRC._60) { LRC.direction60 = 'up'; } + if (previous._60 === LRC._60) { LRC.direction60 = 'side'; } + + } + + LRC.previous = previous; + + LRCMap.set(LRC.begin, LRC); + + previous = LRC; + } + + nextPercentageBandwidth(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildLRC -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function nextPercentageBandwidth() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = bot.devTeam + "/" + "AAChris" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + PERCENTAGE_BANDWIDTH_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + marketFile = JSON.parse(text); + + buildPercentageBandwidthMap(); + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildPercentageBandwidthMap() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildPercentageBandwidthMap -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < marketFile.length; i++) { + + let percentageBandwidth = { + begin: marketFile[i][0], + end: marketFile[i][1], + value: marketFile[i][2], + movingAverage: marketFile[i][3], + bandwidth: marketFile[i][4] + }; + + if (previous !== undefined) { + + if (previous.movingAverage > percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'down'; } + if (previous.movingAverage < percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'up'; } + if (previous.movingAverage === percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'side'; } + + } + + percentageBandwidth.previous = previous; + + percentageBandwidthMap.set(percentageBandwidth.begin, percentageBandwidth); + + previous = percentageBandwidth; + } + + nextBollingerBands(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildPercentageBandwidthMap -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function nextBollingerBands() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerBands -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = bot.devTeam + "/" + "AAChris" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + BOLLINGER_BANDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + marketFile = JSON.parse(text); + + buildBollingerBandsMap(); + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerBands -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildBollingerBandsMap() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildBollingerBandsMap -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < marketFile.length; i++) { + + let bollingerBand = { + begin: marketFile[i][0], + end: marketFile[i][1], + movingAverage: marketFile[i][2], + standardDeviation: marketFile[i][3], + deviation: marketFile[i][4] + }; + + if (previous !== undefined) { + + if (previous.movingAverage > bollingerBand.movingAverage) { bollingerBand.direction = 'down'; } + if (previous.movingAverage < bollingerBand.movingAverage) { bollingerBand.direction = 'up'; } + if (previous.movingAverage === bollingerBand.movingAverage) { bollingerBand.direction = 'side'; } + + } + + bollingerBand.previous = previous; + + bollingerBandsMap.set(bollingerBand.begin, bollingerBand); + + previous = bollingerBand; + } + + nextBollingerChannels(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildBollingerBandsMap -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function nextBollingerChannels() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerChannels -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = bot.devTeam + "/" + "AAPaula" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + BOLLINGER_CHANNELS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + marketFile = JSON.parse(text); + + buildBollingerChannelsArray(); + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerChannels -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildBollingerChannelsArray() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildBollingerChannelsArray -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < marketFile.length; i++) { + + let bollingerChannel = { + begin: marketFile[i][0], + end: marketFile[i][1], + direction: marketFile[i][2], + period: marketFile[i][3], + firstMovingAverage: marketFile[i][4], + lastMovingAverage: marketFile[i][5], + firstDeviation: marketFile[i][6], + lastDeviation: marketFile[i][7] + }; + + bollingerChannel.previous = previous; + + bollingerChannelsArray.push(bollingerChannel); + + previous = bollingerChannel; + } + + nextBollingerSubChannels(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildBollingerChannelsArray -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function nextBollingerSubChannels() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = bot.devTeam + "/" + "AAPaula" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + BOLLINGER_SUB_CHANNELS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + marketFile = JSON.parse(text); + + buildBollingerSubChannelsArray(); + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildBollingerSubChannelsArray() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildBollingerSubChannelsArray -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < marketFile.length; i++) { + + let bollingerSubChannel = { + begin: marketFile[i][0], + end: marketFile[i][1], + direction: marketFile[i][2], + slope: marketFile[i][3], + period: marketFile[i][4], + firstMovingAverage: marketFile[i][5], + lastMovingAverage: marketFile[i][6], + firstDeviation: marketFile[i][7], + lastDeviation: marketFile[i][8] + }; + + bollingerSubChannel.previous = previous; + + bollingerSubChannelsArray.push(bollingerSubChannel); + + previous = bollingerSubChannel; + } + + nextCandlesFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildBollingerSubChannelsArray -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function nextCandlesFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextCandlesFile -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = bot.devTeam + "/" + "AAOlivia" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + oliviaStorage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + marketFile = JSON.parse(text); + + buildCandles(); + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextCandlesFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildCandles() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildCandles -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < marketFile.length; i++) { + + let candle = { + open: undefined, + close: undefined, + min: 10000000000000, + max: 0, + begin: undefined, + end: undefined, + direction: undefined + }; + + candle.min = marketFile[i][0]; + candle.max = marketFile[i][1]; + + candle.open = marketFile[i][2]; + candle.close = marketFile[i][3]; + + candle.begin = marketFile[i][4]; + candle.end = marketFile[i][5]; + + if (candle.open > candle.close) { candle.direction = 'down'; } + if (candle.open < candle.close) { candle.direction = 'up'; } + if (candle.open === candle.close) { candle.direction = 'side'; } + + candle.previous = previous; + + candles.push(candle); + + previous = candle; + } + + commons.runSimulation( + candles, + bollingerBandsMap, + percentageBandwidthMap, + LRCMap, + bollingerChannelsArray, + bollingerSubChannelsArray, + recordsArray, + conditionsArray, + simulationLogic, + outputPeriod, + writeRecordsFile) + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildCandles -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeRecordsFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeRecordsFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < recordsArray.length; i++) { + + let record = recordsArray[i]; + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + record.type + "," + + record.rate + "," + + record.amount + "," + + record.balanceA + "," + + record.balanceB + "," + + record.profit + "," + + record.lastProfit + "," + + record.stopLoss + "," + + record.roundtrips + "," + + record.hits + "," + + record.fails + "," + + record.hitRatio + "," + + record.ROI + "," + + record.periods + "," + + record.days + "," + + record.anualizedRateOfReturn + "," + + record.sellRate + "," + + record.lastProfitPercent + "," + + record.strategy + "," + + record.strategyPhase + "," + + record.buyOrder + "," + + record.stopLossPhase + "," + + record.buyOrderPhase + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + jasonStorage.createTextFile(filePath, fileName, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeConditionsFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeConditionsFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeConditionsFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < conditionsArray.length; i++) { + + let record = conditionsArray[i]; + + let conditions = ""; + let conditionsSeparator = ""; + + for (let j = 0; j < record.length - 1; j++) { + conditions = conditions + conditionsSeparator + record[j]; + if (conditionsSeparator === "") { conditionsSeparator = ","; } + } + + conditions = conditions + conditionsSeparator + '[' + record[record.length - 1] + ']'; // The last item contains an Array of condition values. + + fileContent = fileContent + separator + '[' + conditions + ']'; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + fileContent = "[" + JSON.stringify(simulationLogic) + "," + fileContent + "]"; + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; + + jasonStorage.createTextFile(filePath, fileName, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + controlLoop(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function controlLoop() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> controlLoop -> Entering function."); } + + n++; + + if (n < global.marketFilesPeriods.length) { + + loopBody(); + + } else { + + writeStatusReport(callBackFunction); + + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> controlLoop -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeStatusReport(callBack) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> Entering function."); } + + try { + + let reportKey = "AAMasters" + "-" + "AAJason" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1"; + let thisReport = statusDependencies.statusReports.get(reportKey); + + thisReport.file.lastExecution = bot.processDatetime; + thisReport.save(callBack); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } +}; From fa5f4cb2f5060d4cbcc372f25521e9c156d2f290 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 10:30:31 +0100 Subject: [PATCH 21/73] Get Files Function --- Multi-Period-Market.js | 342 +++++++++-------------------------------- 1 file changed, 70 insertions(+), 272 deletions(-) diff --git a/Multi-Period-Market.js b/Multi-Period-Market.js index 75e4236c7..71dc66beb 100644 --- a/Multi-Period-Market.js +++ b/Multi-Period-Market.js @@ -33,6 +33,7 @@ let statusDependencies; let dataDependencies; let storages = []; + let marketFiles = []; return thisObject; @@ -52,12 +53,13 @@ let key; let storage; + let dependency = dataDependencies[i]; - key = dataDependencies.devTeam + "-" + - dataDependencies.bot + "-" + - dataDependencies.product + "-" + - dataDependencies.dataSet + "-" + - dataDependencies.dataSetVersion + key = dependency.devTeam + "-" + + dependency.bot + "-" + + dependency.product + "-" + + dependency.dataSet + "-" + + dependency.dataSetVersion storage = dataDependencies.dataSets.get(key); @@ -126,12 +128,73 @@ const outputPeriod = global.marketFilesPeriods[n][0]; const timePeriod = global.marketFilesPeriods[n][1]; - - let marketFile; + let fileCount = 0; + + for (let i = 0; i < dataDependencies.length; i++) { + + let dependency = dataDependencies[i]; + let storage = storages[i]; + + getFile(); + + function getFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> getFile -> Entering function."); } + + let fileName = market.assetA + '_' + market.assetB + ".json"; + + let filePathRoot = dependency.devTeam + "/" + dependency.bot + "." + dependency.botVersion.major + "." + dependency.botVersion.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + dependency.dataSetVersion; + let filePath = filePathRoot + "/Output/" + dependency.product + "/" + "Multi-Period-Market" + "/" + timePeriod; + + storage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + let marketFile = JSON.parse(text); + marketFiles.push(marketFile); + fileCount++; + + callTheBot(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> getFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + } + + function callTheBot() { + + if (fileCount === dataDependencies.length + 1) { + } + } @@ -148,51 +211,7 @@ nextLRC(); - function nextLRC() { - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextLRC -> Entering function."); } - - let fileName = market.assetA + '_' + market.assetB + ".json"; - - let filePathRoot = "AAVikings" + "/" + "AAGauss" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + LRC_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - gaussStorage.getTextFile(filePath, fileName, onFileReceived, true); - - function onFileReceived(err, text) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> text = " + text); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; - - } - - marketFile = JSON.parse(text); - - buildLRC(); - - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextLRC -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextLRC -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } function buildLRC() { @@ -244,51 +263,7 @@ } } - function nextPercentageBandwidth() { - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> Entering function."); } - - let fileName = market.assetA + '_' + market.assetB + ".json"; - - let filePathRoot = bot.devTeam + "/" + "AAChris" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + PERCENTAGE_BANDWIDTH_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); - - function onFileReceived(err, text) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> text = " + text); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; - - } - - marketFile = JSON.parse(text); - - buildPercentageBandwidthMap(); - - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextPercentageBandwidth -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } function buildPercentageBandwidthMap() { @@ -332,51 +307,7 @@ } } - function nextBollingerBands() { - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerBands -> Entering function."); } - - let fileName = market.assetA + '_' + market.assetB + ".json"; - - let filePathRoot = bot.devTeam + "/" + "AAChris" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + BOLLINGER_BANDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); - - function onFileReceived(err, text) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> text = " + text); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; - - } - - marketFile = JSON.parse(text); - - buildBollingerBandsMap(); - - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerBands -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerBands -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } function buildBollingerBandsMap() { @@ -420,51 +351,7 @@ } } - function nextBollingerChannels() { - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerChannels -> Entering function."); } - - let fileName = market.assetA + '_' + market.assetB + ".json"; - - let filePathRoot = bot.devTeam + "/" + "AAPaula" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + BOLLINGER_CHANNELS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); - - function onFileReceived(err, text) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> text = " + text); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; - - } - - marketFile = JSON.parse(text); - - buildBollingerChannelsArray(); - - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerChannels -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerChannels -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } function buildBollingerChannelsArray() { @@ -503,51 +390,7 @@ } } - function nextBollingerSubChannels() { - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> Entering function."); } - - let fileName = market.assetA + '_' + market.assetB + ".json"; - - let filePathRoot = bot.devTeam + "/" + "AAPaula" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + BOLLINGER_SUB_CHANNELS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - chrisStorage.getTextFile(filePath, fileName, onFileReceived, true); - - function onFileReceived(err, text) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> text = " + text); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; - - } - - marketFile = JSON.parse(text); - - buildBollingerSubChannelsArray(); - - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextBollingerSubChannels -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } function buildBollingerSubChannelsArray() { @@ -587,51 +430,6 @@ } } - function nextCandlesFile() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextCandlesFile -> Entering function."); } - - let fileName = market.assetA + '_' + market.assetB + ".json"; - - let filePathRoot = bot.devTeam + "/" + "AAOlivia" + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - oliviaStorage.getTextFile(filePath, fileName, onFileReceived, true); - - function onFileReceived(err, text) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> text = " + text); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; - - } - - marketFile = JSON.parse(text); - - buildCandles(); - - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextCandlesFile -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> nextCandlesFile -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } function buildCandles() { From 2e476b39b61a423295eae76eabf53a931e20ced7 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 10:57:38 +0100 Subject: [PATCH 22/73] Initialize Function done --- Multi-Period-Market.js | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/Multi-Period-Market.js b/Multi-Period-Market.js index 71dc66beb..bce2f7c45 100644 --- a/Multi-Period-Market.js +++ b/Multi-Period-Market.js @@ -1,4 +1,4 @@ -exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, FILE_STORAGE) { +exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, FILE_STORAGE, USER_BOT_MODULE, COMMONS_MODULE) { const FULL_LOG = true; const LOG_FILE_CONTENT = false; @@ -7,15 +7,6 @@ const EXCHANGE_NAME = "Poloniex"; - const LRC_FOLDER_NAME = "LRC-Points"; - const PERCENTAGE_BANDWIDTH_FOLDER_NAME = "Percentage-Bandwidth"; - const BOLLINGER_BANDS_FOLDER_NAME = "Bollinger-Bands"; - const BOLLINGER_CHANNELS_FOLDER_NAME = "Bollinger-Channels"; - const BOLLINGER_SUB_CHANNELS_FOLDER_NAME = "Bollinger-Sub-Channels"; - const CANDLES_FOLDER_NAME = "Candles"; - const SIMULATED_RECORDS_FOLDER_NAME = "Trading-Simulation"; - const CONDITIONS_FOLDER_NAME = "Simulation-Conditions"; - const commons = COMMONS.newCommons(bot, logger, UTILITIES); thisObject = { @@ -23,11 +14,6 @@ start: start }; - let gaussStorage = BLOB_STORAGE.newBlobStorage(bot, logger); - let chrisStorage = BLOB_STORAGE.newBlobStorage(bot, logger); - let oliviaStorage = BLOB_STORAGE.newBlobStorage(bot, logger); - let jasonStorage = BLOB_STORAGE.newBlobStorage(bot, logger); - let utilities = UTILITIES.newCloudUtilities(bot, logger); let statusDependencies; @@ -35,6 +21,8 @@ let storages = []; let marketFiles = []; + let usertBot; + return thisObject; function initialize(pStatusDependencies, pDataDependencies, pMonth, pYear, callBackFunction) { @@ -67,7 +55,8 @@ } - callBackFunction(global.DEFAULT_OK_RESPONSE); + usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); + usertBot.initialize(dataDependencies, pMonth, pYear, callBackFunction); } catch (err) { logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.message); From 07a766296c013b204698d62e05c76bef7a8375f2 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 11:40:36 +0100 Subject: [PATCH 23/73] Update Multi-Period-Market.js --- Multi-Period-Market.js | 501 +++-------------------------------------- 1 file changed, 35 insertions(+), 466 deletions(-) diff --git a/Multi-Period-Market.js b/Multi-Period-Market.js index bce2f7c45..49b62d192 100644 --- a/Multi-Period-Market.js +++ b/Multi-Period-Market.js @@ -64,8 +64,6 @@ } } - - function start(callBackFunction) { try { @@ -74,11 +72,11 @@ let market = global.MARKET; - buildRecords(); + processTimePeriods(); - function buildRecords() { + function processTimePeriods() { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> Entering function."); } try { @@ -90,7 +88,7 @@ try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> periodsLoop -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoop -> Entering function."); } /* @@ -104,7 +102,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> periodsLoop -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -113,7 +111,7 @@ try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> Entering function."); } const outputPeriod = global.marketFilesPeriods[n][0]; const timePeriod = global.marketFilesPeriods[n][1]; @@ -131,7 +129,7 @@ try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> getFile -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> getFile -> Entering function."); } let fileName = market.assetA + '_' + market.assetB + ".json"; @@ -144,12 +142,12 @@ try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> text = " + text); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> text = " + text); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> err = " + err.message); callBackFunction(err); return; @@ -163,13 +161,13 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> getFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> getFile -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> getFile -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -178,476 +176,47 @@ function callTheBot() { - if (fileCount === dataDependencies.length + 1) { - - - - } - } - - - - let LRCMap = new Map(); - let percentageBandwidthMap = new Map(); - let bollingerBandsMap = new Map(); - let bollingerChannelsArray = []; - let bollingerSubChannelsArray = []; - - let candles = []; - let recordsArray = []; - let conditionsArray = []; - let simulationLogic = {}; - - nextLRC(); - - - - function buildLRC() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildLRC -> Entering function."); } - try { - let previous; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> callTheBot -> Entering function."); } - for (let i = 0; i < marketFile.length; i++) { + if (fileCount === dataDependencies.length + 1) { - let LRC = { - begin: marketFile[i][0], - end: marketFile[i][1], - _15: marketFile[i][2], - _30: marketFile[i][3], - _60: marketFile[i][4] - }; + const outputPeriod = global.marketFilesPeriods[n][0]; + const timePeriod = global.marketFilesPeriods[n][1]; - if (previous !== undefined) { + usertBot.initialize(marketFiles, outputPeriod, timePeriod, callBackFunction); - if (previous._15 > LRC._15) { LRC.direction15 = 'down'; } - if (previous._15 < LRC._15) { LRC.direction15 = 'up'; } - if (previous._15 === LRC._15) { LRC.direction15 = 'side'; } + function onBotFinished(err) { - if (previous._30 > LRC._30) { LRC.direction30 = 'down'; } - if (previous._30 < LRC._30) { LRC.direction30 = 'up'; } - if (previous._30 === LRC._30) { LRC.direction30 = 'side'; } + try { - if (previous._60 > LRC._60) { LRC.direction60 = 'down'; } - if (previous._60 < LRC._60) { LRC.direction60 = 'up'; } - if (previous._60 === LRC._60) { LRC.direction60 = 'side'; } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> callTheBot -> onBotFinished -> Entering function."); } - } + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - LRC.previous = previous; - - LRCMap.set(LRC.begin, LRC); - - previous = LRC; - } - - nextPercentageBandwidth(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildLRC -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - - - function buildPercentageBandwidthMap() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildPercentageBandwidthMap -> Entering function."); } - - try { - - let previous; - - for (let i = 0; i < marketFile.length; i++) { - - let percentageBandwidth = { - begin: marketFile[i][0], - end: marketFile[i][1], - value: marketFile[i][2], - movingAverage: marketFile[i][3], - bandwidth: marketFile[i][4] - }; - - if (previous !== undefined) { - - if (previous.movingAverage > percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'down'; } - if (previous.movingAverage < percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'up'; } - if (previous.movingAverage === percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'side'; } - - } - - percentageBandwidth.previous = previous; - - percentageBandwidthMap.set(percentageBandwidth.begin, percentageBandwidth); - - previous = percentageBandwidth; - } - - nextBollingerBands(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildPercentageBandwidthMap -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - - - function buildBollingerBandsMap() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildBollingerBandsMap -> Entering function."); } - - try { - - let previous; - - for (let i = 0; i < marketFile.length; i++) { - - let bollingerBand = { - begin: marketFile[i][0], - end: marketFile[i][1], - movingAverage: marketFile[i][2], - standardDeviation: marketFile[i][3], - deviation: marketFile[i][4] - }; - - if (previous !== undefined) { - - if (previous.movingAverage > bollingerBand.movingAverage) { bollingerBand.direction = 'down'; } - if (previous.movingAverage < bollingerBand.movingAverage) { bollingerBand.direction = 'up'; } - if (previous.movingAverage === bollingerBand.movingAverage) { bollingerBand.direction = 'side'; } - - } - - bollingerBand.previous = previous; - - bollingerBandsMap.set(bollingerBand.begin, bollingerBand); - - previous = bollingerBand; - } - - nextBollingerChannels(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildBollingerBandsMap -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - - - function buildBollingerChannelsArray() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildBollingerChannelsArray -> Entering function."); } - - try { - - let previous; - - for (let i = 0; i < marketFile.length; i++) { - - let bollingerChannel = { - begin: marketFile[i][0], - end: marketFile[i][1], - direction: marketFile[i][2], - period: marketFile[i][3], - firstMovingAverage: marketFile[i][4], - lastMovingAverage: marketFile[i][5], - firstDeviation: marketFile[i][6], - lastDeviation: marketFile[i][7] - }; - - bollingerChannel.previous = previous; - - bollingerChannelsArray.push(bollingerChannel); - - previous = bollingerChannel; - } - - nextBollingerSubChannels(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildBollingerChannelsArray -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - - - function buildBollingerSubChannelsArray() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildBollingerSubChannelsArray -> Entering function."); } - - try { - - let previous; - - for (let i = 0; i < marketFile.length; i++) { - - let bollingerSubChannel = { - begin: marketFile[i][0], - end: marketFile[i][1], - direction: marketFile[i][2], - slope: marketFile[i][3], - period: marketFile[i][4], - firstMovingAverage: marketFile[i][5], - lastMovingAverage: marketFile[i][6], - firstDeviation: marketFile[i][7], - lastDeviation: marketFile[i][8] - }; - - bollingerSubChannel.previous = previous; - - bollingerSubChannelsArray.push(bollingerSubChannel); - - previous = bollingerSubChannel; - } - - nextCandlesFile(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildBollingerSubChannelsArray -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - - function buildCandles() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> buildCandles -> Entering function."); } - - try { - - let previous; - - for (let i = 0; i < marketFile.length; i++) { - - let candle = { - open: undefined, - close: undefined, - min: 10000000000000, - max: 0, - begin: undefined, - end: undefined, - direction: undefined - }; - - candle.min = marketFile[i][0]; - candle.max = marketFile[i][1]; - - candle.open = marketFile[i][2]; - candle.close = marketFile[i][3]; - - candle.begin = marketFile[i][4]; - candle.end = marketFile[i][5]; - - if (candle.open > candle.close) { candle.direction = 'down'; } - if (candle.open < candle.close) { candle.direction = 'up'; } - if (candle.open === candle.close) { candle.direction = 'side'; } - - candle.previous = previous; - - candles.push(candle); - - previous = candle; - } - - commons.runSimulation( - candles, - bollingerBandsMap, - percentageBandwidthMap, - LRCMap, - bollingerChannelsArray, - bollingerSubChannelsArray, - recordsArray, - conditionsArray, - simulationLogic, - outputPeriod, - writeRecordsFile) - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> buildCandles -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function writeRecordsFile() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeRecordsFile -> Entering function."); } - - let separator = ""; - let fileRecordCounter = 0; - - let fileContent = ""; - - for (let i = 0; i < recordsArray.length; i++) { - - let record = recordsArray[i]; - - fileContent = fileContent + separator + '[' + - record.begin + "," + - record.end + "," + - record.type + "," + - record.rate + "," + - record.amount + "," + - record.balanceA + "," + - record.balanceB + "," + - record.profit + "," + - record.lastProfit + "," + - record.stopLoss + "," + - record.roundtrips + "," + - record.hits + "," + - record.fails + "," + - record.hitRatio + "," + - record.ROI + "," + - record.periods + "," + - record.days + "," + - record.anualizedRateOfReturn + "," + - record.sellRate + "," + - record.lastProfitPercent + "," + - record.strategy + "," + - record.strategyPhase + "," + - record.buyOrder + "," + - record.stopLossPhase + "," + - record.buyOrderPhase + "]"; - - if (separator === "") { separator = ","; } - - fileRecordCounter++; - - } - - fileContent = "[" + fileContent + "]"; - - let fileName = '' + market.assetA + '_' + market.assetB + '.json'; - - let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - jasonStorage.createTextFile(filePath, fileName, fileContent + '\n', onFileCreated); - - function onFileCreated(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> fileContent = " + fileContent); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> filePath = " + filePath); - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); - - callBackFunction(err); - return; + callBackFunction(err); + return; + } + controlLoop(); } - - writeConditionsFile(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> onFileCreated -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeRecordsFile -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function writeConditionsFile() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeConditionsFile -> Entering function."); } - - let separator = ""; - let fileRecordCounter = 0; - - let fileContent = ""; - - for (let i = 0; i < conditionsArray.length; i++) { - - let record = conditionsArray[i]; - - let conditions = ""; - let conditionsSeparator = ""; - - for (let j = 0; j < record.length - 1; j++) { - conditions = conditions + conditionsSeparator + record[j]; - if (conditionsSeparator === "") { conditionsSeparator = ","; } - } - - conditions = conditions + conditionsSeparator + '[' + record[record.length - 1] + ']'; // The last item contains an Array of condition values. - - fileContent = fileContent + separator + '[' + conditions + ']'; - - if (separator === "") { separator = ","; } - - fileRecordCounter++; - - } - - fileContent = "[" + fileContent + "]"; - fileContent = "[" + JSON.stringify(simulationLogic) + "," + fileContent + "]"; - let fileName = '' + market.assetA + '_' + market.assetB + '.json'; - - let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriod; - - jasonStorage.createTextFile(filePath, fileName, fileContent + '\n', onFileCreated); - - function onFileCreated(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> fileContent = " + fileContent); } - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> filePath = " + filePath); - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); - - callBackFunction(err); - return; - + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> callTheBot -> onBotFinished -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); } - - controlLoop(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> onFileCreated -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } + } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> writeConditionsFile -> err = " + err.message); + catch(err){ + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> callTheBot -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> loopBody -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -656,7 +225,7 @@ try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildRecords -> controlLoop -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> controlLoop -> Entering function."); } n++; @@ -671,14 +240,14 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> controlLoop -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> buildRecords -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } From fdbfad1e6753799abc9446298e77fda883302e51 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 12:38:13 +0100 Subject: [PATCH 24/73] Debugging, Data Confirg added at data Dependencies --- DataDependencies.js | 13 +- IndicatorBotProcessMainLoop.js | 246 +++++++++++++++++- ...i-Period-Market.js => MultiPeriodMarket.js | 6 +- Project.njsproj | 3 + 4 files changed, 258 insertions(+), 10 deletions(-) rename Multi-Period-Market.js => MultiPeriodMarket.js (97%) diff --git a/DataDependencies.js b/DataDependencies.js index 0660226b9..df98108cc 100644 --- a/DataDependencies.js +++ b/DataDependencies.js @@ -9,6 +9,7 @@ let ownerBot; // This is the bot owner of the Data Set. let thisObject = { + config: undefined, dataSets: new Map(), initialize: initialize, keys: [] @@ -23,7 +24,9 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - if (pDataDependenciesConfig === undefined) { + thisObject.config = pDataDependenciesConfig; + + if (thisObject.config === undefined) { // We allow old indicators not to declare their data dependencies. @@ -38,11 +41,11 @@ let alreadyCalledBack = false; let addCount = 0; - for (let i = 0; i < pDataDependenciesConfig.length; i++) { + for (let i = 0; i < thisObject.config.length; i++) { let dataSetModule = DATA_SET.newDataSet(BOT, logger, BLOB_STORAGE, UTILITIES); - dataSetModule.initialize(pDataDependenciesConfig[i], onInitilized); + dataSetModule.initialize(thisObject.config[i], onInitilized); function onInitilized(err) { @@ -65,14 +68,14 @@ let key; - key = pDataDependenciesConfig[i].devTeam + "-" + pDataDependenciesConfig[i].bot + "-" + pDataDependenciesConfig[i].product + "-" + pDataDependenciesConfig[i].dataSet + "-" + pDataDependenciesConfig[i].dataSetVersion; + key = thisObject.config[i].devTeam + "-" + thisObject.config[i].bot + "-" + thisObject.config[i].product + "-" + thisObject.config[i].dataSet + "-" + thisObject.config[i].dataSetVersion; thisObject.keys.push(key); thisObject.dataSets.set(key, dataSetModule); if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> addDataSet -> DataSet added to Map. -> key = " + key); } - if (addCount === pDataDependenciesConfig.length) { + if (addCount === thisObject.config.length) { if (alreadyCalledBack === false) { callBackFunction(global.DEFAULT_OK_RESPONSE); return; diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 88347779d..0b1b0013a 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -9,6 +9,7 @@ let COMMONS_MODULE; const BLOB_STORAGE = require(ROOT_DIR + 'BlobStorage'); + const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket'); const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. @@ -190,6 +191,7 @@ /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ let userBot; + let multiPeriodMarket; let statusDependencies; let dataDependencies; @@ -291,7 +293,16 @@ switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); } - initializeUserBot(); + + /* If the process is configured to run inside a framework, we continue there, otherwise we run the bot directly. */ + + switch (processConfig.framework) { + case 'Multi-Period-Market': { + intitializeMultiPeriodMarket(); + break; + } + default: { initializeUserBot();} + } return; } case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. @@ -354,7 +365,7 @@ usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); - usertBot.initialize(statusDependencies, pMonth, pYear, onInizialized, dataDependencies); + usertBot.initialize(statusDependencies, pMonth, pYear, onInizialized); function onInizialized(err) { @@ -577,6 +588,237 @@ } } + function intitializeMultiPeriodMarket() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> Entering function."); } + + multiPeriodMarket = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); + + multiPeriodMarket.initialize(statusDependencies, dataDependencies, pMonth, pYear, onInizialized, dataDependencies); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Execution finished well."); + startMultiPeriodMarket(); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + case global.CUSTOM_OK_RESPONSE.result: { + + switch (err.message) { + case "Too far in the future.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeMultiPeriodMarket -> onInizialized > Too far in the future. This Loop will enter in coma."); + nextWaitTime = 'Coma'; + loopControl(nextWaitTime); + return; + } + case "Not needed now, but soon.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeMultiPeriodMarket -> onInizialized > Not needed now, but soon. This Loop will continue with Normal wait time."); + nextWaitTime = 'Normal'; + loopControl(nextWaitTime); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized > Unhandled custom response received. -> err.message = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Unhandled err.result received. -> err.message = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function startMultiPeriodMarket() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startMultiPeriodMarket -> Entering function."); } + + multiPeriodMarket.start(onFinished); + + function onFinished(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startMultiPeriodMarket -> onFinished -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> startMultiPeriodMarket -> onFinished -> Execution finished well."); + nextWaitTime = 'Normal'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + case global.CUSTOM_OK_RESPONSE.result: { + + switch (err.message) { + case "Dependency does not exist.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Dependency does not exist. This Loop will go to sleep."); + nextWaitTime = 'Sleep'; + loopControl(nextWaitTime); + return; + } + case "Dependency not ready.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Dependency not ready. This Loop will go to sleep."); + nextWaitTime = 'Sleep'; + loopControl(nextWaitTime); + return; + } + case "Month before it is needed.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Month before it is needed. This Loop will be terminated."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + } + case "Month fully processed.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Month fully processed. This Loop will be terminated."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + } + case "End of the month reached.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> End of the month reached. This Loop will be terminated."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Unhandled custom response received. -> err.message = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Unhandled err.result received. -> err.message = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + function loopControl(nextWaitTime) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); } diff --git a/Multi-Period-Market.js b/MultiPeriodMarket.js similarity index 97% rename from Multi-Period-Market.js rename to MultiPeriodMarket.js index 49b62d192..719ea5683 100644 --- a/Multi-Period-Market.js +++ b/MultiPeriodMarket.js @@ -1,9 +1,9 @@ -exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, FILE_STORAGE, USER_BOT_MODULE, COMMONS_MODULE) { +exports.newMultiPeriodMarket = function newMultiPeriodMarket(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, FILE_STORAGE, USER_BOT_MODULE, COMMONS_MODULE) { const FULL_LOG = true; const LOG_FILE_CONTENT = false; - const MODULE_NAME = "User Bot"; + const MODULE_NAME = "Multi Period Market"; const EXCHANGE_NAME = "Poloniex"; @@ -37,7 +37,7 @@ statusDependencies = pStatusDependencies; dataDependencies = pDataDependencies; - for (let i = 0; i < dataDependencies.length; i++) { + for (let i = 0; i < dataDependencies.dataSets.Entries.length; i++) { let key; let storage; diff --git a/Project.njsproj b/Project.njsproj index 9edd19db5..3c981ef93 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -33,6 +33,9 @@ Code + + Code + Code From 03ea78988a79d2a3777d9f04469b8a6a28bdbbf5 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 13:12:23 +0100 Subject: [PATCH 25/73] For transformed into a Loop --- DataSet.js | 1 - IndicatorBotProcessMainLoop.js | 2 +- MultiPeriodMarket.js | 168 +++++++++++++++++++-------------- 3 files changed, 100 insertions(+), 71 deletions(-) diff --git a/DataSet.js b/DataSet.js index 074135d0a..215137939 100644 --- a/DataSet.js +++ b/DataSet.js @@ -5,7 +5,6 @@ let bot = BOT; let thisObject = { - file: undefined, // Here we have the JSON object representing the file content. initialize: initialize, getTextFile: getTextFile, createTextFile: createTextFile diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 0b1b0013a..0aa0046e0 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -594,7 +594,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> Entering function."); } - multiPeriodMarket = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); + multiPeriodMarket = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE); multiPeriodMarket.initialize(statusDependencies, dataDependencies, pMonth, pYear, onInizialized, dataDependencies); diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 719ea5683..e3840bfb4 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -1,4 +1,4 @@ -exports.newMultiPeriodMarket = function newMultiPeriodMarket(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, FILE_STORAGE, USER_BOT_MODULE, COMMONS_MODULE) { +exports.newMultiPeriodMarket = function newMultiPeriodMarket(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE) { const FULL_LOG = true; const LOG_FILE_CONTENT = false; @@ -37,11 +37,11 @@ statusDependencies = pStatusDependencies; dataDependencies = pDataDependencies; - for (let i = 0; i < dataDependencies.dataSets.Entries.length; i++) { + for (let i = 0; i < dataDependencies.config.length; i++) { let key; let storage; - let dependency = dataDependencies[i]; + let dependency = dataDependencies.config[i]; key = dependency.devTeam + "-" + dependency.bot + "-" + @@ -98,7 +98,7 @@ n = 0 // loop Variable representing each possible period as defined at the periods array. - loopBody(); + periodsLoopBody(); } catch (err) { @@ -107,131 +107,161 @@ } } - function loopBody() { + function periodsLoopBody() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); } const outputPeriod = global.marketFilesPeriods[n][0]; const timePeriod = global.marketFilesPeriods[n][1]; - let fileCount = 0; + let dependencyIndex = 0; + dependencyLoopBody(); - for (let i = 0; i < dataDependencies.length; i++) { + function dependencyLoopBody() { - let dependency = dataDependencies[i]; - let storage = storages[i]; + try { - getFile(); + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> Entering function."); } - function getFile() { + let dependency = dataDependencies.config[dependencyIndex]; + let storage = storages[dependencyIndex]; - try { + getFile(); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> getFile -> Entering function."); } + function getFile() { - let fileName = market.assetA + '_' + market.assetB + ".json"; + try { - let filePathRoot = dependency.devTeam + "/" + dependency.bot + "." + dependency.botVersion.major + "." + dependency.botVersion.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + dependency.dataSetVersion; - let filePath = filePathRoot + "/Output/" + dependency.product + "/" + "Multi-Period-Market" + "/" + timePeriod; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> Entering function."); } - storage.getTextFile(filePath, fileName, onFileReceived, true); + let fileName = market.assetA + '_' + market.assetB + ".json"; - function onFileReceived(err, text) { + let filePathRoot = dependency.devTeam + "/" + dependency.bot + "." + dependency.botVersion.major + "." + dependency.botVersion.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + dependency.dataSetVersion; + let filePath = filePathRoot + "/Output/" + dependency.product + "/" + "Multi-Period-Market" + "/" + timePeriod; - try { + storage.getTextFile(filePath, fileName, onFileReceived, true); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> Entering function."); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> text = " + text); } + function onFileReceived(err, text) { - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + try { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> err = " + err.message); - callBackFunction(err); - return; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = " + err.message); + callBackFunction(err); + return; + + } + + let marketFile = JSON.parse(text); + marketFiles.push(marketFile); + fileCount++; + + callTheBot(); } - - let marketFile = JSON.parse(text); - marketFiles.push(marketFile); - fileCount++; - - callTheBot(); - - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> getFile -> onFileReceived -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } } } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> getFile -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> dependencyLoopBody -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } } + function dependencyControlLoop() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> dependencyControlLoop -> Entering function."); } + + dependencyIndex++; + + if (dependencyIndex < dataDependencies.config.length) { + + dependencyLoopBody(); + + } else { + + callTheBot(); + + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> dependencyControlLoop -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + function callTheBot() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> callTheBot -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); } - if (fileCount === dataDependencies.length + 1) { + const outputPeriod = global.marketFilesPeriods[n][0]; + const timePeriod = global.marketFilesPeriods[n][1]; - const outputPeriod = global.marketFilesPeriods[n][0]; - const timePeriod = global.marketFilesPeriods[n][1]; + usertBot.initialize(marketFiles, outputPeriod, timePeriod, callBackFunction); - usertBot.initialize(marketFiles, outputPeriod, timePeriod, callBackFunction); + function onBotFinished(err) { - function onBotFinished(err) { + try { - try { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> Entering function."); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> loopBody -> callTheBot -> onBotFinished -> Entering function."); } + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - callBackFunction(err); - return; - } - - controlLoop(); - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> callTheBot -> onBotFinished -> err = " + err.message); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); + callBackFunction(err); + return; } + + periodsControlLoop(); + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } - } catch(err){ - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> callTheBot -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> loopBody -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } - function controlLoop() { + function periodsControlLoop() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> controlLoop -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsControlLoop -> Entering function."); } n++; if (n < global.marketFilesPeriods.length) { - loopBody(); + periodsLoopBody(); } else { @@ -240,7 +270,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsControlLoop -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -258,7 +288,7 @@ try { - let reportKey = "AAMasters" + "-" + "AAJason" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1"; + let reportKey = bot.devTeam + "-" + bot.codeName + "-" + "Multi-Period-Market" + "-" + "dataSet.V1"; let thisReport = statusDependencies.statusReports.get(reportKey); thisReport.file.lastExecution = bot.processDatetime; From d2a88e2b5435296085ccc2a9bbe393a66ca90bdb Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 14:02:48 +0100 Subject: [PATCH 26/73] Multi Period Market Framework, ready! --- MultiPeriodMarket.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index e3840bfb4..b360236be 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -138,8 +138,7 @@ let fileName = market.assetA + '_' + market.assetB + ".json"; - let filePathRoot = dependency.devTeam + "/" + dependency.bot + "." + dependency.botVersion.major + "." + dependency.botVersion.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + dependency.dataSetVersion; - let filePath = filePathRoot + "/Output/" + dependency.product + "/" + "Multi-Period-Market" + "/" + timePeriod; + let filePath = dependency.product + "/" + "Multi-Period-Market" + "/" + timePeriod; storage.getTextFile(filePath, fileName, onFileReceived, true); @@ -153,16 +152,16 @@ if (err.result !== global.DEFAULT_OK_RESPONSE.result) { logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> fileName = " + fileName); callBackFunction(err); return; - } let marketFile = JSON.parse(text); marketFiles.push(marketFile); - fileCount++; - callTheBot(); + dependencyControlLoop(); } catch (err) { @@ -217,7 +216,7 @@ const outputPeriod = global.marketFilesPeriods[n][0]; const timePeriod = global.marketFilesPeriods[n][1]; - usertBot.initialize(marketFiles, outputPeriod, timePeriod, callBackFunction); + usertBot.start(marketFiles, outputPeriod, timePeriod, callBackFunction); function onBotFinished(err) { From 07144f0385042fcb44c2cb63c150125d96c132a6 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 15:36:59 +0100 Subject: [PATCH 27/73] dataFiles --- MultiPeriodMarket.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index b360236be..53d4a3776 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -19,7 +19,7 @@ let statusDependencies; let dataDependencies; let storages = []; - let marketFiles = []; + let dataFiles = []; let usertBot; @@ -159,7 +159,7 @@ } let marketFile = JSON.parse(text); - marketFiles.push(marketFile); + dataFiles.push(marketFile); dependencyControlLoop(); @@ -216,7 +216,7 @@ const outputPeriod = global.marketFilesPeriods[n][0]; const timePeriod = global.marketFilesPeriods[n][1]; - usertBot.start(marketFiles, outputPeriod, timePeriod, callBackFunction); + usertBot.start(dataFiles, outputPeriod, timePeriod, callBackFunction); function onBotFinished(err) { From 882bfe91393caa3520301429a39502d34344d13a Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 16 Mar 2019 16:01:42 +0100 Subject: [PATCH 28/73] Bug, array not being cleanned. --- MultiPeriodMarket.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 53d4a3776..a331941b8 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -117,6 +117,8 @@ const timePeriod = global.marketFilesPeriods[n][1]; let dependencyIndex = 0; + dataFiles = []; + dependencyLoopBody(); function dependencyLoopBody() { @@ -158,8 +160,8 @@ return; } - let marketFile = JSON.parse(text); - dataFiles.push(marketFile); + let dataFile = JSON.parse(text); + dataFiles.push(dataFile); dependencyControlLoop(); @@ -216,7 +218,7 @@ const outputPeriod = global.marketFilesPeriods[n][0]; const timePeriod = global.marketFilesPeriods[n][1]; - usertBot.start(dataFiles, outputPeriod, timePeriod, callBackFunction); + usertBot.start(dataFiles, outputPeriod, timePeriod, onBotFinished); function onBotFinished(err) { From a9d386a0607f9b53bddbe7d9175b36b5764d1a03 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 08:35:30 +0100 Subject: [PATCH 29/73] Multi Period Daily implemented --- MultiPeriodDaily.js | 657 ++++++++++++++++++++++++++++++++++++++++++++ Project.njsproj | 3 + 2 files changed, 660 insertions(+) create mode 100644 MultiPeriodDaily.js diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js new file mode 100644 index 000000000..9f2ef1466 --- /dev/null +++ b/MultiPeriodDaily.js @@ -0,0 +1,657 @@ +exports.newMultiPeriodDaily = function newMultiPeriodDaily(bot, logger, COMMONS, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE) { + + const FULL_LOG = true; + const LOG_FILE_CONTENT = false; + + const MODULE_NAME = "Multi Period Daily"; + + const EXCHANGE_NAME = "Poloniex"; + + const commons = COMMONS.newCommons(bot, logger, UTILITIES); + + thisObject = { + initialize: initialize, + start: start + }; + + let utilities = UTILITIES.newCloudUtilities(bot, logger); + + let statusDependencies; + let dataDependencies; + let storages = []; + let dataFiles = []; + + let usertBot; + let currentBotStorage = BLOB_STORAGE.newBlobStorage(bot, logger); + + return thisObject; + + function initialize(pStatusDependencies, pDataDependencies, pMonth, pYear, callBackFunction) { + + try { + + logger.fileName = MODULE_NAME; + logger.initialize(); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + + statusDependencies = pStatusDependencies; + dataDependencies = pDataDependencies; + + for (let i = 0; i < dataDependencies.config.length; i++) { + + let key; + let storage; + let dependency = dataDependencies.config[i]; + + key = dependency.devTeam + "-" + + dependency.bot + "-" + + dependency.product + "-" + + dependency.dataSet + "-" + + dependency.dataSetVersion + + storage = dataDependencies.dataSets.get(key); + + storages.push(storage); + + } + + currentBotStorage.initialize(bot.devTeam, onStorageInizialized); + + function onStorageInizialized(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); + usertBot.initialize(dataDependencies, pMonth, pYear, callBackFunction); + + } else { + logger.write(MODULE_NAME, "[ERROR] initialize -> onStorageInizialized -> err = " + err.message); + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function start(callBackFunction) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); } + + let market = global.MARKET; + + /* Context Variables */ + + let contextVariables = { + lastFile: undefined, // Datetime of the last file files sucessfully produced by this process. + dateBeginingOfMarket: undefined, // Datetime of the first trade file in the whole market history. + dateEndOfMarket: undefined // Datetime of the last file available to be used as an input of this process. + }; + + let previousDay; // Holds the date of the previous day relative to the processing date. + let currentDate; // Holds the processing date. + + getContextVariables(); + + function getContextVariables() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Entering function."); } + + let thisReport; + let reportKey; + let statusReport; + + /* We look first for Charly in order to get when the market starts. */ + + reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Poloniex-Historic-Trades" + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + + statusReport = statusDependencies.statusReports.get(reportKey); + + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + if (statusReport.status === "Status Report is corrupt.") { + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile === undefined) { + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet."); + + let customOK = { + result: global.CUSTOM_OK_RESPONSE.result, + message: "Dependency does not exist." + } + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK); + return; + } + + contextVariables.dateBeginingOfMarket = new Date(thisReport.lastFile.year + "-" + thisReport.lastFile.month + "-" + thisReport.lastFile.days + " " + thisReport.lastFile.hours + ":" + thisReport.lastFile.minutes + GMT_SECONDS); + + /* Second, we get the report from Olivia, to know when the marted ends. */ + + reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + + statusReport = statusDependencies.statusReports.get(reportKey); + + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + if (statusReport.status === "Status Report is corrupt.") { + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile === undefined) { + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + + let customOK = { + result: global.CUSTOM_OK_RESPONSE.result, + message: "Dependency not ready." + } + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK); + return; + } + + contextVariables.dateEndOfMarket = new Date(thisReport.lastFile.valueOf()); + + /* Finally we get our own Status Report. */ + + reportKey = bot.devTeam + "-" + bot.codeName + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + + statusReport = statusDependencies.statusReports.get(reportKey); + + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + if (statusReport.status === "Status Report is corrupt.") { + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process."); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile !== undefined) { + + contextVariables.lastFile = new Date(thisReport.lastFile); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile !== undefined"); } + + processTimePeriods(); + return; + + } else { + + /* + In the case when there is no status report, we take the date of the file with the first trades as the begining of the market. Then we will + go one day further in time, so that the previous day does fine a file at the begining of the market. + */ + + contextVariables.lastFile = new Date(contextVariables.dateBeginingOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginingOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginingOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); + contextVariables.lastFile = new Date(contextVariables.lastFile.valueOf() + ONE_DAY_IN_MILISECONDS); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile === undefined"); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> contextVariables.lastFile = " + contextVariables.lastFile); } + + processTimePeriods(); + return; + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = " + err.message); + if (err.message === "Cannot read property 'file' of undefined") { + logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. "); + logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); + } + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function processTimePeriods() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> Entering function."); } + + try { + + let n; + + advanceTime(); + + function advanceTime() { + + try { + + logger.newInternalLoop(bot.codeName, bot.process); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> Entering function."); } + + currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS); + previousDay = new Date(currentDate.valueOf() - ONE_DAY_IN_MILISECONDS); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> currentDate = " + currentDate); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> previousDay = " + previousDay); } + + /* Validation that we are not going past the head of the market. */ + + if (currentDate.valueOf() > contextVariables.dateEndOfMarket.valueOf()) { + + const logText = "Head of the market found @ " + previousDay.getUTCFullYear() + "/" + (previousDay.getUTCMonth() + 1) + "/" + previousDay.getUTCDate() + "."; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> " + logText); } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + + } + + periodsLoop(); + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> advanceTime -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function periodsLoop() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoop -> Entering function."); } + + /* + + We will iterate through all posible periods. + + */ + + n = 0 // loop Variable representing each possible period as defined at the periods array. + + periodsLoopBody(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function periodsLoopBody() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); } + + const outputPeriod = global.dailyFilesPeriods[n][0]; + const timePeriod = global.dailyFilesPeriods[n][1]; + + let dependencyIndex = 0; + dataFiles = []; + + dependencyLoopBody(); + + function dependencyLoopBody() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> Entering function."); } + + let dependency = dataDependencies.config[dependencyIndex]; + let storage = storages[dependencyIndex]; + + let previousFile; + let currentFile; + + getPreviousFile(); + + function getPreviousFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> Entering function."); } + + let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2); + let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + timePeriod + "/" + dateForPath; + let fileName = market.assetA + '_' + market.assetB + ".json"; + + storage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> fileName = " + fileName); + callBackFunction(err); + return; + } + + previousFile = JSON.parse(text); + + getCurrentFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function getCurrentFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> Entering function."); } + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2); + let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + timePeriod + "/" + dateForPath; + let fileName = market.assetA + '_' + market.assetB + ".json"; + + storage.getTextFile(filePath, fileName, onFileReceived, true); + + function onFileReceived(err, text) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> text = " + text); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> fileName = " + fileName); + callBackFunction(err); + return; + } + + currentFile = JSON.parse(text); + + let datafile = previousFile.concat(currentFile); + + dataFiles.push(dataFile); + dependencyControlLoop(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> dependencyLoopBody -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function dependencyControlLoop() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> dependencyControlLoop -> Entering function."); } + + dependencyIndex++; + + if (dependencyIndex < dataDependencies.config.length) { + + dependencyLoopBody(); + + } else { + + callTheBot(); + + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> dependencyControlLoop -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function callTheBot() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); } + + const outputPeriod = global.dailyFilesPeriods[n][0]; + const timePeriod = global.dailyFilesPeriods[n][1]; + + usertBot.start(dataFiles, outputPeriod, timePeriod, onBotFinished); + + function onBotFinished(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + callBackFunction(err); + return; + } + + periodsControlLoop(); + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function periodsControlLoop() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsControlLoop -> Entering function."); } + + n++; + + if (n < global.dailyFilesPeriods.length) { + + periodsLoopBody(); + + } else { + + n = 0; + + writeDataRanges(onWritten); + + function onWritten(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> controlLoop -> onWritten -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = " + err.message); + callBackFunction(err); + return; + } + + writeStatusReport(currentDate, advanceTime); + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsControlLoop -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeDataRanges(callBack) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRanges -> Entering function."); } + + let productIndex = 0; + productLoopBody(); + + function productLoopBody() { + + let folderName = bot.products[productIndex].codeName; + + writeDataRange(contextVariables.dateBeginingOfMarket, currentDate, folderName, controlLoop); + } + + function controlLoop() { + + productIndex++; + + if (productIndex < bot.products.length) { + productLoopBody(); + } else { + callBack(global.DEFAULT_OK_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeDataRanges -> err = " + err.message); + callBack(global.DEFAULT_FAIL_RESPONSE); + } + + } + + function writeDataRange(pBegin, pEnd, pProductFolder, callBack) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> Entering function."); } + + let dataRange = { + begin: pBegin.valueOf(), + end: pEnd.valueOf() + }; + + let fileContent = JSON.stringify(dataRange); + + let fileName = 'Data.Range.' + market.assetA + '_' + market.assetB + '.json'; + let filePath = bot.filePathRoot + "/Output/" + pProductFolder + "/" + bot.process; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> fileName = " + fileName); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> filePath = " + filePath); } + + currentBotStorage.createTextFile(filePath, fileName, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Entering function."); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> onFileCreated -> err = " + err.message); + callBack(err); + return; + } + + if (LOG_FILE_CONTENT === true) { + logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Content written = " + fileContent); + } + + callBack(global.DEFAULT_OK_RESPONSE); + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> err = " + err.message); + callBack(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeStatusReport(lastFileDate, callBack) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> lastFileDate = " + lastFileDate); } + + try { + + let reportKey = bot.devTeam + "-" + bot.codeName + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; + let thisReport = statusDependencies.statusReports.get(reportKey); + + thisReport.file.lastExecution = bot.currentDatetime; + thisReport.file.lastFile = lastFileDate; + thisReport.save(callBack); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } +}; diff --git a/Project.njsproj b/Project.njsproj index 3c981ef93..c9cb27126 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -33,6 +33,9 @@ Code + + Code + Code From a3ddec4831d3572e91f3a0c3e9b72faa7328be91 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 08:47:59 +0100 Subject: [PATCH 30/73] processFramework Implemented --- IndicatorBotProcessMainLoop.js | 77 ++++++++++++++++++---------------- MultiPeriodDaily.js | 4 +- MultiPeriodMarket.js | 4 +- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 0aa0046e0..58f34ccce 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -10,6 +10,7 @@ const BLOB_STORAGE = require(ROOT_DIR + 'BlobStorage'); const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket'); + const MULTI_PERIOD_DAILY = require(ROOT_DIR + 'MultiPeriodDaily'); const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. @@ -191,7 +192,7 @@ /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ let userBot; - let multiPeriodMarket; + let processFramework; let statusDependencies; let dataDependencies; @@ -298,7 +299,13 @@ switch (processConfig.framework) { case 'Multi-Period-Market': { - intitializeMultiPeriodMarket(); + processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE); + intitializeProcessFramework(); + break; + } + case 'Multi-Period-Daily': { + processFramework = MULTI_PERIOD_DAILY.newMultiPeriodDaily(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE); + intitializeProcessFramework(); break; } default: { initializeUserBot();} @@ -588,36 +595,34 @@ } } - function intitializeMultiPeriodMarket() { + function intitializeProcessFramework() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> Entering function."); } - multiPeriodMarket = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE); - - multiPeriodMarket.initialize(statusDependencies, dataDependencies, pMonth, pYear, onInizialized, dataDependencies); + processFramework.initialize(statusDependencies, dataDependencies, onInizialized, dataDependencies); function onInizialized(err) { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Entering function."); } switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Execution finished well."); - startMultiPeriodMarket(); + logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Execution finished well."); + startProcessFramework(); return; } case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Retry Later. Requesting Execution Retry."); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Retry Later. Requesting Execution Retry."); nextWaitTime = 'Retry'; loopControl(nextWaitTime); return; } case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Operation Failed. Aborting the process."); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Operation Failed. Aborting the process."); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -630,19 +635,19 @@ switch (err.message) { case "Too far in the future.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeMultiPeriodMarket -> onInizialized > Too far in the future. This Loop will enter in coma."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeProcessFramework -> onInizialized > Too far in the future. This Loop will enter in coma."); nextWaitTime = 'Coma'; loopControl(nextWaitTime); return; } case "Not needed now, but soon.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeMultiPeriodMarket -> onInizialized > Not needed now, but soon. This Loop will continue with Normal wait time."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeProcessFramework -> onInizialized > Not needed now, but soon. This Loop will continue with Normal wait time."); nextWaitTime = 'Normal'; loopControl(nextWaitTime); return; } default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized > Unhandled custom response received. -> err.message = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized > Unhandled custom response received. -> err.message = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -654,8 +659,8 @@ } } default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> Unhandled err.result received. -> err.message = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err.message = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); @@ -668,7 +673,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> onInizialized -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -679,7 +684,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeMultiPeriodMarket -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -689,35 +694,35 @@ } } - function startMultiPeriodMarket() { + function startProcessFramework() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startMultiPeriodMarket -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> Entering function."); } - multiPeriodMarket.start(onFinished); + processFramework.start(onFinished); function onFinished(err) { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startMultiPeriodMarket -> onFinished -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Entering function."); } switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> startMultiPeriodMarket -> onFinished -> Execution finished well."); + logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Execution finished well."); nextWaitTime = 'Normal'; loopControl(nextWaitTime); return; } case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Retry Later. Requesting Execution Retry."); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Retry Later. Requesting Execution Retry."); nextWaitTime = 'Retry'; loopControl(nextWaitTime); return; } case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Operation Failed. Aborting the process."); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Operation Failed. Aborting the process."); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -730,19 +735,19 @@ switch (err.message) { case "Dependency does not exist.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Dependency does not exist. This Loop will go to sleep."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency does not exist. This Loop will go to sleep."); nextWaitTime = 'Sleep'; loopControl(nextWaitTime); return; } case "Dependency not ready.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Dependency not ready. This Loop will go to sleep."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency not ready. This Loop will go to sleep."); nextWaitTime = 'Sleep'; loopControl(nextWaitTime); return; } case "Month before it is needed.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Month before it is needed. This Loop will be terminated."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Month before it is needed. This Loop will be terminated."); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -752,7 +757,7 @@ return; } case "Month fully processed.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> Month fully processed. This Loop will be terminated."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Month fully processed. This Loop will be terminated."); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -762,7 +767,7 @@ return; } case "End of the month reached.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startMultiPeriodMarket -> onFinished -> End of the month reached. This Loop will be terminated."); + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> End of the month reached. This Loop will be terminated."); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -772,7 +777,7 @@ return; } default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Unhandled custom response received. -> err.message = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled custom response received. -> err.message = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -784,8 +789,8 @@ } } default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> Unhandled err.result received. -> err.message = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err.message = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); @@ -798,7 +803,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> onFinished -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -809,7 +814,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startMultiPeriodMarket -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = " + err.message); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 9f2ef1466..194497a1c 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -26,7 +26,7 @@ return thisObject; - function initialize(pStatusDependencies, pDataDependencies, pMonth, pYear, callBackFunction) { + function initialize(pStatusDependencies, pDataDependencies, callBackFunction) { try { @@ -63,7 +63,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); - usertBot.initialize(dataDependencies, pMonth, pYear, callBackFunction); + usertBot.initialize(dataDependencies, callBackFunction); } else { logger.write(MODULE_NAME, "[ERROR] initialize -> onStorageInizialized -> err = " + err.message); diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index a331941b8..485a087e0 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -25,7 +25,7 @@ return thisObject; - function initialize(pStatusDependencies, pDataDependencies, pMonth, pYear, callBackFunction) { + function initialize(pStatusDependencies, pDataDependencies, callBackFunction) { try { @@ -56,7 +56,7 @@ } usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE); - usertBot.initialize(dataDependencies, pMonth, pYear, callBackFunction); + usertBot.initialize(dataDependencies, callBackFunction); } catch (err) { logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.message); From f08383d65b4df330c22458ed83c03add129bcace Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 09:15:44 +0100 Subject: [PATCH 31/73] Sending current date to the bot --- MultiPeriodDaily.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 194497a1c..46e72f39b 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -463,7 +463,7 @@ const outputPeriod = global.dailyFilesPeriods[n][0]; const timePeriod = global.dailyFilesPeriods[n][1]; - usertBot.start(dataFiles, outputPeriod, timePeriod, onBotFinished); + usertBot.start(dataFiles, outputPeriod, timePeriod, currentDate, onBotFinished); function onBotFinished(err) { From 9197efc3ad9acbeded96b2c5eb758d8e668b6ce6 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 09:28:53 +0100 Subject: [PATCH 32/73] Better naming --- MultiPeriodDaily.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 46e72f39b..01108f4df 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -89,8 +89,8 @@ let contextVariables = { lastFile: undefined, // Datetime of the last file files sucessfully produced by this process. - dateBeginingOfMarket: undefined, // Datetime of the first trade file in the whole market history. - dateEndOfMarket: undefined // Datetime of the last file available to be used as an input of this process. + dateBeginingOfMarket: undefined, // Datetime of the first trade file in the whole market history. + dateEndOfMarket: undefined // Datetime of the last file available to be used as an input of this process. }; let previousDay; // Holds the date of the previous day relative to the processing date. From b6d7b6b220ab70a153bbe449a3f563e21c27f39a Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 09:45:58 +0100 Subject: [PATCH 33/73] Missing parts added --- MultiPeriodDaily.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 01108f4df..7fd39a18f 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -2,12 +2,11 @@ const FULL_LOG = true; const LOG_FILE_CONTENT = false; - const MODULE_NAME = "Multi Period Daily"; - const EXCHANGE_NAME = "Poloniex"; - const commons = COMMONS.newCommons(bot, logger, UTILITIES); + const GMT_SECONDS = ':00.000 GMT+0000'; + const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000; thisObject = { initialize: initialize, @@ -243,6 +242,7 @@ try { let n; + currentDate = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop. advanceTime(); From bf8c8fbd2b04263b0752ee87b8aa46568111ef35 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 10:23:59 +0100 Subject: [PATCH 34/73] Loading Dependencies and merging files --- MultiPeriodDaily.js | 56 ++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 7fd39a18f..b3f46f47a 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -93,7 +93,7 @@ }; let previousDay; // Holds the date of the previous day relative to the processing date. - let currentDate; // Holds the processing date. + let currentDay; // Holds the processing date. getContextVariables(); @@ -142,8 +142,9 @@ } contextVariables.dateBeginingOfMarket = new Date(thisReport.lastFile.year + "-" + thisReport.lastFile.month + "-" + thisReport.lastFile.days + " " + thisReport.lastFile.hours + ":" + thisReport.lastFile.minutes + GMT_SECONDS); + contextVariables.dateBeginingOfMarket = new Date("2018-01-01"); // Remove this temporaty patch. - /* Second, we get the report from Olivia, to know when the marted ends. */ + /* Second, we get the report from Olivia, to know when the martet ends. */ reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } @@ -242,7 +243,9 @@ try { let n; - currentDate = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop. + let botNeverRan = true; + + currentDay = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop. advanceTime(); @@ -254,15 +257,15 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> Entering function."); } - currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS); - previousDay = new Date(currentDate.valueOf() - ONE_DAY_IN_MILISECONDS); + currentDay = new Date(currentDay.valueOf() + ONE_DAY_IN_MILISECONDS); + previousDay = new Date(currentDay.valueOf() - ONE_DAY_IN_MILISECONDS); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> currentDate = " + currentDate); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> currentDay = " + currentDay); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> previousDay = " + previousDay); } /* Validation that we are not going past the head of the market. */ - if (currentDate.valueOf() > contextVariables.dateEndOfMarket.valueOf()) { + if (currentDay.valueOf() > contextVariables.dateEndOfMarket.valueOf()) { const logText = "Head of the market found @ " + previousDay.getUTCFullYear() + "/" + (previousDay.getUTCMonth() + 1) + "/" + previousDay.getUTCDate() + "."; if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> " + logText); } @@ -309,9 +312,9 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); } - const outputPeriod = global.dailyFilesPeriods[n][0]; - const timePeriod = global.dailyFilesPeriods[n][1]; - + const outputPeriod = global.dailyFilePeriods[n][0]; + const timePeriod = global.dailyFilePeriods[n][1]; + let dependencyIndex = 0; dataFiles = []; @@ -350,6 +353,22 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> Entering function."); } if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> text = " + text); } + if (err.message === "File does not exist." && botNeverRan === true) { + + /* + Sometimes one of the dependencies of an indicator for some reasons are not calculated from the begining of the market. + When that happens we can not find those files. What we do in this situation is to move the time fordward until we can find + all the dependencies and the first run of the bot is successful. + + After that, we will not accept more missing files on any of the dependencies, and if any is missing we will abort the processing. + */ + logger.write(MODULE_NAME, "[WARN] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> Skipping day because file " + filePath + "/" + fileName + " was not found."); + + advanceTime(); + return; + } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err.message); @@ -406,7 +425,7 @@ currentFile = JSON.parse(text); - let datafile = previousFile.concat(currentFile); + let dataFile = previousFile.concat(currentFile); dataFiles.push(dataFile); dependencyControlLoop(); @@ -460,10 +479,10 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); } - const outputPeriod = global.dailyFilesPeriods[n][0]; - const timePeriod = global.dailyFilesPeriods[n][1]; + const outputPeriod = global.dailyFilePeriods[n][0]; + const timePeriod = global.dailyFilePeriods[n][1]; - usertBot.start(dataFiles, outputPeriod, timePeriod, currentDate, onBotFinished); + usertBot.start(dataFiles, outputPeriod, timePeriod, currentDay, onBotFinished); function onBotFinished(err) { @@ -477,6 +496,7 @@ return; } + botNeverRan = false; periodsControlLoop(); } catch (err) { @@ -505,7 +525,7 @@ n++; - if (n < global.dailyFilesPeriods.length) { + if (n < global.dailyFilePeriods.length) { periodsLoopBody(); @@ -527,7 +547,7 @@ return; } - writeStatusReport(currentDate, advanceTime); + writeStatusReport(currentDay, advanceTime); } catch (err) { logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = " + err.message); @@ -562,7 +582,7 @@ let folderName = bot.products[productIndex].codeName; - writeDataRange(contextVariables.dateBeginingOfMarket, currentDate, folderName, controlLoop); + writeDataRange(contextVariables.dateBeginingOfMarket, currentDay, folderName, controlLoop); } function controlLoop() { @@ -637,7 +657,7 @@ let reportKey = bot.devTeam + "-" + bot.codeName + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; let thisReport = statusDependencies.statusReports.get(reportKey); - thisReport.file.lastExecution = bot.currentDatetime; + thisReport.file.lastExecution = bot.currentDaytime; thisReport.file.lastFile = lastFileDate; thisReport.save(callBack); From 664b688820d100825127133a9de15ec749400d0c Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 17 Mar 2019 15:47:08 +0100 Subject: [PATCH 35/73] TimePeriod corrected --- IndicatorBotProcessMainLoop.js | 2 +- MultiPeriodDaily.js | 40 +++++++++++++++++++++------------- MultiPeriodMarket.js | 14 ++++++------ StatusDependencies.js | 3 +++ 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 58f34ccce..45e6cf024 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -601,7 +601,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> Entering function."); } - processFramework.initialize(statusDependencies, dataDependencies, onInizialized, dataDependencies); + processFramework.initialize(processConfig, statusDependencies, dataDependencies, onInizialized, dataDependencies); function onInizialized(err) { diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index b3f46f47a..c9c8fe1cf 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -23,9 +23,11 @@ let usertBot; let currentBotStorage = BLOB_STORAGE.newBlobStorage(bot, logger); + let pProcessConfig; + return thisObject; - function initialize(pStatusDependencies, pDataDependencies, callBackFunction) { + function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, callBackFunction) { try { @@ -36,6 +38,7 @@ statusDependencies = pStatusDependencies; dataDependencies = pDataDependencies; + processConfig = pProcessConfig; for (let i = 0; i < dataDependencies.config.length; i++) { @@ -107,9 +110,14 @@ let reportKey; let statusReport; - /* We look first for Charly in order to get when the market starts. */ + /* + We look first for the bot who knows the begining of the marke in order to get when the market starts. + */ - reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Poloniex-Historic-Trades" + "-" + "dataSet.V1"; + let botWhoKnowsTheBeginingOfTheMarket = statusDependencies.config[processConfig.statusDependenciesIndexBegingOfMarket]; + let botWhoKnowsTheEndOfTheMarket = statusDependencies.config[processConfig.statusDependenciesIndexEndOfMarket]; + + reportKey = botWhoKnowsTheBeginingOfTheMarket.devTeam + "-" + botWhoKnowsTheBeginingOfTheMarket.bot + "-" + botWhoKnowsTheBeginingOfTheMarket.process + "-" + "dataSet.V1"; if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } statusReport = statusDependencies.statusReports.get(reportKey); @@ -142,15 +150,17 @@ } contextVariables.dateBeginingOfMarket = new Date(thisReport.lastFile.year + "-" + thisReport.lastFile.month + "-" + thisReport.lastFile.days + " " + thisReport.lastFile.hours + ":" + thisReport.lastFile.minutes + GMT_SECONDS); - contextVariables.dateBeginingOfMarket = new Date("2018-01-01"); // Remove this temporaty patch. + //contextVariables.dateBeginingOfMarket = new Date("2018-01-01"); // TODO: Remove this temporaty patch. - /* Second, we get the report from Olivia, to know when the martet ends. */ + /* + Here we get the status report from the bot who knows which is the end of the market. + */ - reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1"; + reportKey = botWhoKnowsTheEndOfTheMarket.devTeam + "-" + botWhoKnowsTheEndOfTheMarket.bot + "-" + botWhoKnowsTheEndOfTheMarket.process + "-" + "dataSet.V1"; if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } statusReport = statusDependencies.statusReports.get(reportKey); - + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); callBackFunction(global.DEFAULT_RETRY_RESPONSE); @@ -312,8 +322,8 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); } - const outputPeriod = global.dailyFilePeriods[n][0]; - const timePeriod = global.dailyFilePeriods[n][1]; + const timePeriod = global.dailyFilePeriods[n][0]; + const outputPeriodLabel = global.dailyFilePeriods[n][1]; let dependencyIndex = 0; dataFiles = []; @@ -341,7 +351,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> Entering function."); } let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2); - let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + timePeriod + "/" + dateForPath; + let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; let fileName = market.assetA + '_' + market.assetB + ".json"; storage.getTextFile(filePath, fileName, onFileReceived, true); @@ -401,8 +411,8 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> Entering function."); } - let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2); - let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + timePeriod + "/" + dateForPath; + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; let fileName = market.assetA + '_' + market.assetB + ".json"; storage.getTextFile(filePath, fileName, onFileReceived, true); @@ -479,10 +489,10 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); } - const outputPeriod = global.dailyFilePeriods[n][0]; - const timePeriod = global.dailyFilePeriods[n][1]; + const timePeriod = global.dailyFilePeriods[n][0]; + const outputPeriodLabel = global.dailyFilePeriods[n][1]; - usertBot.start(dataFiles, outputPeriod, timePeriod, currentDay, onBotFinished); + usertBot.start(dataFiles, timePeriod, outputPeriodLabel, currentDay, onBotFinished); function onBotFinished(err) { diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 485a087e0..f0e3ffccb 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -25,7 +25,7 @@ return thisObject; - function initialize(pStatusDependencies, pDataDependencies, callBackFunction) { + function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, callBackFunction) { try { @@ -113,8 +113,8 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); } - const outputPeriod = global.marketFilesPeriods[n][0]; - const timePeriod = global.marketFilesPeriods[n][1]; + const timePeriod = global.marketFilesPeriods[n][0]; + const outputPeriodLabel = global.marketFilesPeriods[n][1]; let dependencyIndex = 0; dataFiles = []; @@ -140,7 +140,7 @@ let fileName = market.assetA + '_' + market.assetB + ".json"; - let filePath = dependency.product + "/" + "Multi-Period-Market" + "/" + timePeriod; + let filePath = dependency.product + "/" + "Multi-Period-Market" + "/" + outputPeriodLabel; storage.getTextFile(filePath, fileName, onFileReceived, true); @@ -215,10 +215,10 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); } - const outputPeriod = global.marketFilesPeriods[n][0]; - const timePeriod = global.marketFilesPeriods[n][1]; + const timePeriod = global.marketFilesPeriods[n][0]; + const outputPeriodLabel = global.marketFilesPeriods[n][1]; - usertBot.start(dataFiles, outputPeriod, timePeriod, onBotFinished); + usertBot.start(dataFiles, timePeriod, outputPeriodLabel, onBotFinished); function onBotFinished(err) { diff --git a/StatusDependencies.js b/StatusDependencies.js index 635efdf37..2ce421ef8 100644 --- a/StatusDependencies.js +++ b/StatusDependencies.js @@ -6,6 +6,7 @@ const MODULE_NAME = "Status Dependencies"; let thisObject = { + config: undefined, statusReports: new Map(), initialize: initialize, keys: [] @@ -22,6 +23,8 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + thisObject.config = pStatusDependenciesConfig; + /* For each dependency declared at the bot config, we will initialize the status report, and load it as part of this initialization process. From d0a7f15c07a112e15307ec3d0f44d04331c84939 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 18 Mar 2019 15:43:29 +0100 Subject: [PATCH 36/73] You can define start dates and end dates not dependant on dependencies --- IndicatorBotProcessMainLoop.js | 18 +++- MultiPeriodDaily.js | 161 ++++++++++++++++++--------------- MultiPeriodMarket.js | 28 +++++- 3 files changed, 133 insertions(+), 74 deletions(-) diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 45e6cf024..514f6d635 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -296,8 +296,12 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); } /* If the process is configured to run inside a framework, we continue there, otherwise we run the bot directly. */ + if (processConfig.framework === undefined) { + initializeUserBot(); + return; + } - switch (processConfig.framework) { + switch (processConfig.framework.name) { case 'Multi-Period-Market': { processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, BLOB_STORAGE, USER_BOT_MODULE, COMMONS_MODULE); intitializeProcessFramework(); @@ -308,7 +312,17 @@ intitializeProcessFramework(); break; } - default: { initializeUserBot();} + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework not Supported."); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework Name = " + processConfig.framework.name); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } } return; } diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index c9c8fe1cf..0a8447ab6 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -23,7 +23,7 @@ let usertBot; let currentBotStorage = BLOB_STORAGE.newBlobStorage(bot, logger); - let pProcessConfig; + let processConfig; return thisObject; @@ -91,12 +91,12 @@ let contextVariables = { lastFile: undefined, // Datetime of the last file files sucessfully produced by this process. - dateBeginingOfMarket: undefined, // Datetime of the first trade file in the whole market history. + dateBeginOfMarket: undefined, // Datetime of the first trade file in the whole market history. dateEndOfMarket: undefined // Datetime of the last file available to be used as an input of this process. }; let previousDay; // Holds the date of the previous day relative to the processing date. - let currentDay; // Holds the processing date. + let currentDay; // Holds the processing date. getContextVariables(); @@ -110,84 +110,103 @@ let reportKey; let statusReport; - /* - We look first for the bot who knows the begining of the marke in order to get when the market starts. - */ + if (processConfig.framework.startDate.fixedDate !== undefined) { - let botWhoKnowsTheBeginingOfTheMarket = statusDependencies.config[processConfig.statusDependenciesIndexBegingOfMarket]; - let botWhoKnowsTheEndOfTheMarket = statusDependencies.config[processConfig.statusDependenciesIndexEndOfMarket]; + /* The starting date is fixed, we will start from there. */ - reportKey = botWhoKnowsTheBeginingOfTheMarket.devTeam + "-" + botWhoKnowsTheBeginingOfTheMarket.bot + "-" + botWhoKnowsTheBeginingOfTheMarket.process + "-" + "dataSet.V1"; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + contextVariables.dateBeginOfMarket = new Date(processConfig.framework.startDate.fixedDate); - statusReport = statusDependencies.statusReports.get(reportKey); + } else { - if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. - logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); - callBackFunction(global.DEFAULT_RETRY_RESPONSE); - return; - } + /* + We look first for the bot who knows the begining of the marke in order to get when the market starts. + */ - if (statusReport.status === "Status Report is corrupt.") { - logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(global.DEFAULT_RETRY_RESPONSE); - return; - } + let botWhoKnowsTheBeginingOfTheMarket = statusDependencies.config[processConfig.framework.startDate.takeItFromStatusDependency]; - thisReport = statusDependencies.statusReports.get(reportKey).file; + reportKey = botWhoKnowsTheBeginingOfTheMarket.devTeam + "-" + botWhoKnowsTheBeginingOfTheMarket.bot + "-" + botWhoKnowsTheBeginingOfTheMarket.process + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } - if (thisReport.lastFile === undefined) { - logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); - logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet."); + statusReport = statusDependencies.statusReports.get(reportKey); - let customOK = { - result: global.CUSTOM_OK_RESPONSE.result, - message: "Dependency does not exist." + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; } - logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message); - callBackFunction(customOK); - return; - } - contextVariables.dateBeginingOfMarket = new Date(thisReport.lastFile.year + "-" + thisReport.lastFile.month + "-" + thisReport.lastFile.days + " " + thisReport.lastFile.hours + ":" + thisReport.lastFile.minutes + GMT_SECONDS); - //contextVariables.dateBeginingOfMarket = new Date("2018-01-01"); // TODO: Remove this temporaty patch. - - /* - Here we get the status report from the bot who knows which is the end of the market. - */ - - reportKey = botWhoKnowsTheEndOfTheMarket.devTeam + "-" + botWhoKnowsTheEndOfTheMarket.bot + "-" + botWhoKnowsTheEndOfTheMarket.process + "-" + "dataSet.V1"; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } - - statusReport = statusDependencies.statusReports.get(reportKey); - - if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. - logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); - callBackFunction(global.DEFAULT_RETRY_RESPONSE); - return; - } - - if (statusReport.status === "Status Report is corrupt.") { - logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(global.DEFAULT_RETRY_RESPONSE); - return; - } - - thisReport = statusDependencies.statusReports.get(reportKey).file; - - if (thisReport.lastFile === undefined) { - logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); - - let customOK = { - result: global.CUSTOM_OK_RESPONSE.result, - message: "Dependency not ready." + if (statusReport.status === "Status Report is corrupt.") { + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; } - logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message); - callBackFunction(customOK); - return; + + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile === undefined) { + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet."); + + let customOK = { + result: global.CUSTOM_OK_RESPONSE.result, + message: "Dependency does not exist." + } + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK); + return; + } + + contextVariables.dateBeginOfMarket = new Date(thisReport.lastFile.year + "-" + thisReport.lastFile.month + "-" + thisReport.lastFile.days + " " + thisReport.lastFile.hours + ":" + thisReport.lastFile.minutes + GMT_SECONDS); + } - contextVariables.dateEndOfMarket = new Date(thisReport.lastFile.valueOf()); + if (processConfig.framework.endDate.fixedDate !== undefined) { + + /* The ending date is fixed, we will end there. */ + + contextVariables.dateEndOfMarket = new Date(processConfig.framework.endDate.fixedDate); + + } else { + + /* + Here we get the status report from the bot who knows which is the end of the market. + */ + + let botWhoKnowsTheEndOfTheMarket = statusDependencies.config[processConfig.framework.endDate.takeItFromStatusDependency]; + + reportKey = botWhoKnowsTheEndOfTheMarket.devTeam + "-" + botWhoKnowsTheEndOfTheMarket.bot + "-" + botWhoKnowsTheEndOfTheMarket.process + "-" + "dataSet.V1"; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); } + + statusReport = statusDependencies.statusReports.get(reportKey); + + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + if (statusReport.status === "Status Report is corrupt.") { + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile === undefined) { + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + + let customOK = { + result: global.CUSTOM_OK_RESPONSE.result, + message: "Dependency not ready." + } + logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK); + return; + } + + contextVariables.dateEndOfMarket = new Date(thisReport.lastFile.valueOf()); + } /* Finally we get our own Status Report. */ @@ -226,7 +245,7 @@ go one day further in time, so that the previous day does fine a file at the begining of the market. */ - contextVariables.lastFile = new Date(contextVariables.dateBeginingOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginingOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginingOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); + contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); contextVariables.lastFile = new Date(contextVariables.lastFile.valueOf() + ONE_DAY_IN_MILISECONDS); if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile === undefined"); } @@ -492,7 +511,7 @@ const timePeriod = global.dailyFilePeriods[n][0]; const outputPeriodLabel = global.dailyFilePeriods[n][1]; - usertBot.start(dataFiles, timePeriod, outputPeriodLabel, currentDay, onBotFinished); + usertBot.start(dataFiles, timePeriod, outputPeriodLabel, currentDay, contextVariables.dateBeginOfMarket, contextVariables.dateEndOfMarket, onBotFinished); function onBotFinished(err) { @@ -592,7 +611,7 @@ let folderName = bot.products[productIndex].codeName; - writeDataRange(contextVariables.dateBeginingOfMarket, currentDay, folderName, controlLoop); + writeDataRange(contextVariables.dateBeginOfMarket, currentDay, folderName, controlLoop); } function controlLoop() { diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index f0e3ffccb..4cda411fa 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -23,6 +23,8 @@ let usertBot; + let processConfig; + return thisObject; function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, callBackFunction) { @@ -36,6 +38,7 @@ statusDependencies = pStatusDependencies; dataDependencies = pDataDependencies; + processConfig = pProcessConfig; for (let i = 0; i < dataDependencies.config.length; i++) { @@ -72,6 +75,29 @@ let market = global.MARKET; + /* Context Variables */ + + let contextVariables = { + dateBeginOfMarket: undefined, // Datetime of the first trade file in the whole market history. + dateEndOfMarket: undefined // Datetime of the last file available to be used as an input of this process. + }; + + if (processConfig.framework.startDate.fixedDate !== undefined) { + + /* The starting date is fixed, we will start from there. */ + + contextVariables.dateBeginOfMarket = new Date(processConfig.framework.startDate.fixedDate); + + } + + if (processConfig.framework.endDate.fixedDate !== undefined) { + + /* The ending date is fixed, we will end there. */ + + contextVariables.dateEndOfMarket = new Date(processConfig.framework.endDate.fixedDate); + + } + processTimePeriods(); function processTimePeriods() { @@ -218,7 +244,7 @@ const timePeriod = global.marketFilesPeriods[n][0]; const outputPeriodLabel = global.marketFilesPeriods[n][1]; - usertBot.start(dataFiles, timePeriod, outputPeriodLabel, onBotFinished); + usertBot.start(dataFiles, timePeriod, outputPeriodLabel, contextVariables.dateBeginOfMarket, contextVariables.dateEndOfMarket, onBotFinished); function onBotFinished(err) { From aa6ea90bad9cd83a3b30f1acafbfb850555ac238 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 18 Mar 2019 21:41:27 +0100 Subject: [PATCH 37/73] Inter Process Memory Implemented --- MultiPeriodDaily.js | 28 ++++++++++++++++++++++++++-- MultiPeriodMarket.js | 8 +++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 0a8447ab6..d40f4952c 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -98,6 +98,8 @@ let previousDay; // Holds the date of the previous day relative to the processing date. let currentDay; // Holds the processing date. + let interExecutionMemoryArray; + getContextVariables(); function getContextVariables() { @@ -233,7 +235,7 @@ contextVariables.lastFile = new Date(thisReport.lastFile); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile !== undefined"); } + interExecutionMemoryArray = thisReport.interExecutionMemoryArray; processTimePeriods(); return; @@ -251,6 +253,19 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile === undefined"); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> contextVariables.lastFile = " + contextVariables.lastFile); } + /* + The first time the process is running is the right time to create the data structure that is going to be shared across different executions. + This data structure has one object per each timePeriod. + */ + + interExecutionMemoryArray = []; + + for (let i = 0; i < global.dailyFilePeriods.length; i++) + { + let emptyObject = {}; + interExecutionMemoryArray.push(emptyObject); + } + processTimePeriods(); return; } @@ -511,7 +526,15 @@ const timePeriod = global.dailyFilePeriods[n][0]; const outputPeriodLabel = global.dailyFilePeriods[n][1]; - usertBot.start(dataFiles, timePeriod, outputPeriodLabel, currentDay, contextVariables.dateBeginOfMarket, contextVariables.dateEndOfMarket, onBotFinished); + usertBot.start( + dataFiles, + timePeriod, + outputPeriodLabel, + currentDay, + contextVariables.dateBeginOfMarket, + contextVariables.dateEndOfMarket, + interExecutionMemoryArray[n], + onBotFinished); function onBotFinished(err) { @@ -688,6 +711,7 @@ thisReport.file.lastExecution = bot.currentDaytime; thisReport.file.lastFile = lastFileDate; + thisReport.file.interExecutionMemoryArray = interExecutionMemoryArray; thisReport.save(callBack); } diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 4cda411fa..20ade8176 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -244,7 +244,13 @@ const timePeriod = global.marketFilesPeriods[n][0]; const outputPeriodLabel = global.marketFilesPeriods[n][1]; - usertBot.start(dataFiles, timePeriod, outputPeriodLabel, contextVariables.dateBeginOfMarket, contextVariables.dateEndOfMarket, onBotFinished); + usertBot.start( + dataFiles, + timePeriod, + outputPeriodLabel, + contextVariables.dateBeginOfMarket, + contextVariables.dateEndOfMarket, + onBotFinished); function onBotFinished(err) { From e200c42b7296ac7dce45f3d4e4ec9fafb040f6cb Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 19 Mar 2019 17:45:49 +0100 Subject: [PATCH 38/73] Bug fixed edcase when we start we dont have a previous file --- MultiPeriodDaily.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index d40f4952c..47293e621 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -243,12 +243,11 @@ } else { /* - In the case when there is no status report, we take the date of the file with the first trades as the begining of the market. Then we will - go one day further in time, so that the previous day does fine a file at the begining of the market. + In the case when there is no status report, we assume like the last processed file is the one on the date of Begining of Market. */ contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); - contextVariables.lastFile = new Date(contextVariables.lastFile.valueOf() + ONE_DAY_IN_MILISECONDS); + //contextVariables.lastFile = new Date(contextVariables.lastFile.valueOf() + ONE_DAY_IN_MILISECONDS); if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile === undefined"); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> contextVariables.lastFile = " + contextVariables.lastFile); } @@ -376,7 +375,12 @@ let previousFile; let currentFile; - getPreviousFile(); + if (currentDay.valueOf() > contextVariables.dateBeginOfMarket.valueOf()) { + getPreviousFile(); + } else { + previousFile = []; + getCurrentFile() + } function getPreviousFile() { From d63dd016e244cc38210f22dc263db7fa00b00b94 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 20 Mar 2019 12:45:46 +0100 Subject: [PATCH 39/73] Retry when it does not have a dependency --- MultiPeriodDaily.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 47293e621..508590812 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -416,6 +416,14 @@ return; } + if (err.result === "Fail Because" && err.message === "File does not exist.") { + + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> fileName = " + fileName); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { @@ -462,6 +470,15 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> Entering function."); } if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> text = " + text); } + if (err.result === "Fail Because" && err.message === "File does not exist.") { + + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> fileName = " + fileName); + callBackFunction(global.DEFAULT_RETRY_RESPONSE); + return; + } + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err.message); From 1026c0837689e80734bc80d57fb80dea80c60add Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 22 Mar 2019 11:07:19 +0100 Subject: [PATCH 40/73] Adding Bots Execution Parameters --- Root.js | 23 +-- Run.js | 38 ++++- package-lock.json | 379 ++++++++++++++++++++++++++-------------------- package.json | 1 + 4 files changed, 264 insertions(+), 177 deletions(-) diff --git a/Root.js b/Root.js index 17ca233a9..cd1a399f4 100644 --- a/Root.js +++ b/Root.js @@ -212,7 +212,7 @@ /* The local configuration allows to select the configuration to run - locally, without overwriting the server config. + locally, without overwriting the server config. Here we check that the local configuration for the execution exist, if it doesn't exist we will take the one on the server. */ @@ -341,10 +341,13 @@ if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> listItem.process = " + listItem.process); } let processConfig = botConfig.processes[i]; - + switch (global.CURRENT_EXECUTION_AT) { case "Cloud": { processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration + if(global.EXECUTION_CONFIG.timePeriod){ + processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod + } break; } case "Browser": { @@ -361,7 +364,7 @@ } } try { - + /* We test each type of start Mode to get what to run and how. */ if (processConfig.startMode.allMonths !== undefined) { @@ -500,7 +503,7 @@ if (processConfig.startMode.live !== undefined) { if (processConfig.startMode.live.run === "true") { - + botConfig.startMode = "Live"; console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); @@ -762,9 +765,9 @@ } - /* + /* Now we have all the possible genes values in a multi-dimensional matrix. - We will go thorugh each of the elements of each dimension and get each combination possible with the other dimmensions. + We will go thorugh each of the elements of each dimension and get each combination possible with the other dimmensions. */ let combinations = []; @@ -827,7 +830,7 @@ setTimeout(execute, i * Math.random() * 10 * 1000); function execute() { - + createBotInstance(genes, combinations.length, botConfig); } @@ -842,7 +845,7 @@ if (global.CURRENT_EXECUTION_AT === "Cloud") { clonName += "-" + process.env.CLONE_ID; } - + clonName += ".1.0"; botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; @@ -899,7 +902,7 @@ logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); logger.persist(); - } + } } } else { @@ -922,7 +925,7 @@ console.log(logDisplace + "Root : [ERROR] start -> findProcess -> err.message = " + err.message); return; } - } + } } } } diff --git a/Run.js b/Run.js index 0b8d69e0a..52f7889a5 100644 --- a/Run.js +++ b/Run.js @@ -3,7 +3,7 @@ global.CURRENT_ENVIRONMENT = "Develop"; global.CURRENT_EXECUTION_AT = "Cloud"; global.SHALL_BOT_STOP = false; -global.AT_BREAKPOINT = false; // This is used only when running at the browser. +global.AT_BREAKPOINT = false; // This is used only when running at the browser. global.RUN_AS_TEAM = false; /* Default parameters can be changed by the execution configuration */ @@ -122,7 +122,8 @@ function readExecutionConfiguration() { global.EXECUTION_CONFIG = { executionList: executionList, - startMode: startMode + startMode: startMode, + timePeriod: getTimePeriod() }; readStoragePermissions(); @@ -135,6 +136,39 @@ function readExecutionConfiguration() { } } +function getTimePeriod(){ + if(process.env.EXECUTION_PARAMETERS !== undefined){ + try { + let executionParameters = JSON.parse(process.env.EXECUTION_PARAMETERS) + let timePeriodMap = new Map() + timePeriodMap.set("24-hs","86400000") + timePeriodMap.set("12-hs","43200000") + timePeriodMap.set("08-hs","28800000") + timePeriodMap.set("06-hs","21600000") + timePeriodMap.set("04-hs","14400000") + timePeriodMap.set("03-hs","10800000") + timePeriodMap.set("02-hs","7200000") + timePeriodMap.set("01-hs","3600000") + timePeriodMap.set("45-min","2700000") + timePeriodMap.set("40-min","2400000") + timePeriodMap.set("30-min","1800000") + timePeriodMap.set("20-min","1200000") + timePeriodMap.set("15-min","900000") + timePeriodMap.set("10-min","600000") + timePeriodMap.set("05-min","300000") + timePeriodMap.set("04-min","240000") + timePeriodMap.set("03-min","180000") + timePeriodMap.set("02-min","120000") + timePeriodMap.set("01-min","60000") + return timePeriodMap.get(executionParameters.timePeriod) + } catch (error) { + console.log( "[WARN] Run -> readExecutionConfiguration -> getTimePeriod -> Error: ", error); + } + } else { + return undefined + } +} + function readStoragePermissions() { try { console.log( "[INFO] Run -> readStoragePermissions -> Entering function. "); diff --git a/package-lock.json b/package-lock.json index 6bba6e4e6..1180a7ec5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,45 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@azure/ms-rest-js": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.2.3.tgz", + "integrity": "sha512-eROQ034b+9v0Hd3wETKi/EwF5pqS3VRAk1Lm8iKVPOP8v30f6Zfzsi420MRfBMsbNCx/mE2N0L65Px7tvcGfVg==", + "requires": { + "axios": "^0.18.0", + "form-data": "^2.3.2", + "tough-cookie": "^2.4.3", + "tslib": "^1.9.2", + "uuid": "^3.2.1", + "xml2js": "^0.4.19" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + } + } + }, + "@azure/storage-blob": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.3.0.tgz", + "integrity": "sha512-KZbJ3q8RpAdeIB5Em1lgXkiq7Mll9bSHHbHavOFMepkkF7HQa3Sez9FdkAVIkVVWK5YoBlshBGZ+mtiSQiS9Fw==", + "requires": { + "@azure/ms-rest-js": "1.2.3", + "events": "3.0.0", + "tslib": "^1.9.3" + } + }, "@types/async": { "version": "2.0.49", "resolved": "https://registry.npmjs.org/@types/async/-/async-2.0.49.tgz", @@ -20,10 +59,10 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "apollo-boost": { @@ -31,14 +70,14 @@ "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.1.16.tgz", "integrity": "sha512-ppnQr90n2cn0ZMveEbqxW6NxmskIpThiLziLlRpRLy4keoAICg1NZecxJQmeaBLMtyhf5UholAjpS2SLmEJeHg==", "requires": { - "apollo-cache": "1.1.17", - "apollo-cache-inmemory": "1.2.10", - "apollo-client": "2.4.2", - "apollo-link": "1.2.3", - "apollo-link-error": "1.1.1", - "apollo-link-http": "1.5.5", - "apollo-link-state": "0.4.2", - "graphql-tag": "2.10.0" + "apollo-cache": "^1.1.17", + "apollo-cache-inmemory": "^1.2.10", + "apollo-client": "^2.4.2", + "apollo-link": "^1.0.6", + "apollo-link-error": "^1.0.3", + "apollo-link-http": "^1.3.1", + "apollo-link-state": "^0.4.0", + "graphql-tag": "^2.4.2" } }, "apollo-cache": { @@ -46,7 +85,7 @@ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.17.tgz", "integrity": "sha512-7sp24n2HZO4vXgTaKNomLyIfGxG4gDdDkBB0jkRzRi7HhnKmfwhiF/RCiKNbgLdrPX151INdls0KwIVliD0dHQ==", "requires": { - "apollo-utilities": "1.0.21" + "apollo-utilities": "^1.0.21" } }, "apollo-cache-inmemory": { @@ -54,9 +93,9 @@ "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.2.10.tgz", "integrity": "sha512-eBusPFVtYIuo+PIfJdAwUCQ4cs7AJ4mB7sTdXxNQCXToYw8mzE6EfHnV37kdVfBXSaa82BzE2rb/YUq/duuamw==", "requires": { - "apollo-cache": "1.1.17", - "apollo-utilities": "1.0.21", - "graphql-anywhere": "4.1.19" + "apollo-cache": "^1.1.17", + "apollo-utilities": "^1.0.21", + "graphql-anywhere": "^4.1.19" } }, "apollo-client": { @@ -65,13 +104,13 @@ "integrity": "sha512-g1z23umaVSoKLj9xNl0aAnk2KBF4JeBi7MeKFc9CGTixH7TkqeQUQtxcjrC7j2h4KmDbuhOAHOFUGf8YshN+ag==", "requires": { "@types/async": "2.0.49", - "@types/zen-observable": "0.8.0", + "@types/zen-observable": "^0.8.0", "apollo-cache": "1.1.17", - "apollo-link": "1.2.3", - "apollo-link-dedup": "1.0.10", + "apollo-link": "^1.0.0", + "apollo-link-dedup": "^1.0.0", "apollo-utilities": "1.0.21", - "symbol-observable": "1.2.0", - "zen-observable": "0.8.9" + "symbol-observable": "^1.0.2", + "zen-observable": "^0.8.0" } }, "apollo-link": { @@ -79,8 +118,8 @@ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.3.tgz", "integrity": "sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==", "requires": { - "apollo-utilities": "1.0.21", - "zen-observable-ts": "0.8.10" + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.10" } }, "apollo-link-dedup": { @@ -88,7 +127,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz", "integrity": "sha512-tpUI9lMZsidxdNygSY1FxflXEkUZnvKRkMUsXXuQUNoSLeNtEvUX7QtKRAl4k9ubLl8JKKc9X3L3onAFeGTK8w==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-link-error": { @@ -96,7 +135,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-error/-/apollo-link-error-1.1.1.tgz", "integrity": "sha512-/yPcaQWcBdB94vpJ4FsiCJt1dAGGRm+6Tsj3wKwP+72taBH+UsGRQQZk7U/1cpZwl1yqhHZn+ZNhVOebpPcIlA==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-link-http": { @@ -104,8 +143,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.5.tgz", "integrity": "sha512-C5N6N/mRwmepvtzO27dgMEU3MMtRKSqcljBkYNZmWwH11BxkUQ5imBLPM3V4QJXNE7NFuAQAB5PeUd4ligivTQ==", "requires": { - "apollo-link": "1.2.3", - "apollo-link-http-common": "0.2.5" + "apollo-link": "^1.2.3", + "apollo-link-http-common": "^0.2.5" } }, "apollo-link-http-common": { @@ -113,7 +152,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.5.tgz", "integrity": "sha512-6FV1wr5AqAyJ64Em1dq5hhGgiyxZE383VJQmhIoDVc3MyNcFL92TkhxREOs4rnH2a9X2iJMko7nodHSGLC6d8w==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-link-state": { @@ -121,8 +160,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-state/-/apollo-link-state-0.4.2.tgz", "integrity": "sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw==", "requires": { - "apollo-utilities": "1.0.21", - "graphql-anywhere": "4.1.19" + "apollo-utilities": "^1.0.8", + "graphql-anywhere": "^4.1.0-alpha.0" } }, "apollo-utilities": { @@ -130,8 +169,8 @@ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.21.tgz", "integrity": "sha512-ZcxELlEl+sDCYBgEMdNXJAsZtRVm8wk4HIA58bMsqYfd1DSAJQEtZ93F0GZgYNAGy3QyaoBeZtbb0/01++G8JQ==", "requires": { - "fast-json-stable-stringify": "2.0.0", - "fclone": "1.0.11" + "fast-json-stable-stringify": "^2.0.0", + "fclone": "^1.0.11" } }, "asn1": { @@ -139,7 +178,7 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "~2.1.0" } }, "assert": { @@ -160,7 +199,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { - "lodash": "4.17.11" + "lodash": "^4.17.10" } }, "asynckit": { @@ -183,8 +222,8 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { - "follow-redirects": "1.6.1", - "is-buffer": "1.1.6" + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" } }, "azure-storage": { @@ -192,17 +231,17 @@ "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.2.tgz", "integrity": "sha512-pOyGPya9+NDpAfm5YcFfklo57HfjDbYLXxs4lomPwvRxmb0Di/A+a+RkUmEFzaQ8S13CqxK40bRRB0sjj2ZQxA==", "requires": { - "browserify-mime": "1.2.9", - "extend": "3.0.2", + "browserify-mime": "~1.2.9", + "extend": "^3.0.2", "json-edm-parser": "0.1.2", "md5.js": "1.3.4", - "readable-stream": "2.0.6", - "request": "2.88.0", - "underscore": "1.8.3", - "uuid": "3.3.2", - "validator": "9.4.1", + "readable-stream": "~2.0.0", + "request": "^2.86.0", + "underscore": "~1.8.3", + "uuid": "^3.0.0", + "validator": "~9.4.1", "xml2js": "0.2.8", - "xmlbuilder": "9.0.7" + "xmlbuilder": "^9.0.7" }, "dependencies": { "underscore": { @@ -218,7 +257,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "browserify-mime": { @@ -246,8 +285,8 @@ "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", "requires": { - "color-convert": "1.9.3", - "color-string": "1.5.3" + "color-convert": "^1.9.1", + "color-string": "^1.5.2" } }, "color-convert": { @@ -268,8 +307,8 @@ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "requires": { - "color-name": "1.1.3", - "simple-swizzle": "0.2.2" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, "colornames": { @@ -287,8 +326,8 @@ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", "requires": { - "color": "3.0.0", - "text-hex": "1.0.0" + "color": "3.0.x", + "text-hex": "1.0.x" } }, "combined-stream": { @@ -296,7 +335,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "core-util-is": { @@ -309,7 +348,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "debug": { @@ -330,9 +369,9 @@ "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", "requires": { - "colorspace": "1.1.1", - "enabled": "1.0.2", - "kuler": "1.0.1" + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" } }, "dotenv": { @@ -346,8 +385,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "optional": true, "requires": { - "jsbn": "0.1.1", - "safer-buffer": "2.1.2" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, "ecdsa-sig-formatter": { @@ -355,7 +394,7 @@ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "enabled": { @@ -363,7 +402,7 @@ "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", "requires": { - "env-variable": "0.0.5" + "env-variable": "0.0.x" } }, "env-variable": { @@ -371,6 +410,11 @@ "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -411,7 +455,7 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "requires": { - "debug": "3.1.0" + "debug": "=3.1.0" } }, "forever-agent": { @@ -424,9 +468,9 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.20" + "mime-types": "^2.1.12" }, "dependencies": { "combined-stream": { @@ -434,7 +478,7 @@ "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } } } @@ -444,7 +488,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "graphql": { @@ -452,7 +496,7 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", "requires": { - "iterall": "1.2.2" + "iterall": "^1.2.2" } }, "graphql-anywhere": { @@ -460,7 +504,7 @@ "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-4.1.19.tgz", "integrity": "sha512-mQlvbECzYPBcgBC9JsdM4v+DSvNmcIP+8Vwr+ij3gktbaLSE0Iza30mztuz40Jlf7ooMs+0emBZucNjLzqz7tA==", "requires": { - "apollo-utilities": "1.0.21" + "apollo-utilities": "^1.0.21" } }, "graphql-tag": { @@ -478,8 +522,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.3.0", + "har-schema": "^2.0.0" } }, "hash-base": { @@ -487,8 +531,8 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { - "inherits": "2.0.1", - "safe-buffer": "5.1.2" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "http-signature": { @@ -496,9 +540,9 @@ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.2" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "inherits": { @@ -552,7 +596,7 @@ "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", "requires": { - "jsonparse": "1.2.0" + "jsonparse": "~1.2.0" } }, "json-schema": { @@ -580,15 +624,15 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", "requires": { - "jws": "3.2.1", - "lodash.includes": "4.3.0", - "lodash.isboolean": "3.0.3", - "lodash.isinteger": "4.0.4", - "lodash.isnumber": "3.0.3", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.once": "4.1.1", - "ms": "2.1.1" + "jws": "^3.1.5", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1" }, "dependencies": { "ms": { @@ -616,7 +660,7 @@ "requires": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.10", - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "jws": { @@ -624,8 +668,8 @@ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", "requires": { - "jwa": "1.2.0", - "safe-buffer": "5.1.2" + "jwa": "^1.2.0", + "safe-buffer": "^5.0.1" } }, "kuler": { @@ -633,7 +677,7 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", "requires": { - "colornames": "1.1.1" + "colornames": "^1.1.1" } }, "lodash": { @@ -681,11 +725,11 @@ "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", "requires": { - "colors": "1.3.3", - "fast-safe-stringify": "2.0.6", - "fecha": "2.3.3", - "ms": "2.1.1", - "triple-beam": "1.3.0" + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.2.0" }, "dependencies": { "ms": { @@ -700,8 +744,8 @@ "resolved": "http://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.1" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, "mime-db": { @@ -714,7 +758,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", "requires": { - "mime-db": "1.36.0" + "mime-db": "~1.36.0" } }, "ms": { @@ -777,12 +821,12 @@ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.1", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" } }, "request": { @@ -790,26 +834,26 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.8.0", - "caseless": "0.12.0", - "combined-stream": "1.0.7", - "extend": "3.0.2", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.1.0", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.20", - "oauth-sign": "0.9.0", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.2", - "tough-cookie": "2.4.3", - "tunnel-agent": "0.6.0", - "uuid": "3.3.2" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" } }, "retry": { @@ -837,7 +881,7 @@ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { - "is-arrayish": "0.3.2" + "is-arrayish": "^0.3.1" } }, "sshpk": { @@ -845,15 +889,15 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { - "asn1": "0.2.4", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.2", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.2", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "stack-trace": { @@ -881,8 +925,8 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { - "psl": "1.1.29", - "punycode": "1.4.1" + "psl": "^1.1.24", + "punycode": "^1.4.1" } }, "triple-beam": { @@ -890,12 +934,17 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -937,9 +986,9 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, "winston": { @@ -947,15 +996,15 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", "requires": { - "async": "2.6.1", - "diagnostics": "1.1.1", - "is-stream": "1.1.0", - "logform": "1.10.0", + "async": "^2.6.0", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^1.9.1", "one-time": "0.0.4", - "readable-stream": "2.3.6", - "stack-trace": "0.0.10", - "triple-beam": "1.3.0", - "winston-transport": "4.3.0" + "readable-stream": "^2.3.6", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.2.0" }, "dependencies": { "inherits": { @@ -973,13 +1022,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -987,7 +1036,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } } } @@ -997,8 +1046,8 @@ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", "requires": { - "readable-stream": "2.3.6", - "triple-beam": "1.3.0" + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" }, "dependencies": { "inherits": { @@ -1016,13 +1065,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -1030,7 +1079,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } } } @@ -1040,7 +1089,7 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", "requires": { - "sax": "0.5.8" + "sax": "0.5.x" } }, "xmlbuilder": { @@ -1058,7 +1107,7 @@ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz", "integrity": "sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==", "requires": { - "zen-observable": "0.8.9" + "zen-observable": "^0.8.0" } } } diff --git a/package.json b/package.json index 90a19c944..321b779f7 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "author": "Luis-Fernando-Molina", "license": "ISC", "dependencies": { + "@azure/storage-blob": "^10.3.0", "apollo-boost": "^0.1.16", "assert": "^1.4.1", "axios": "^0.18.0", From 94ef85863eacc62b97c5aecd81352bdee6bc3170 Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 22 Mar 2019 18:01:25 +0100 Subject: [PATCH 41/73] Numeric value for the timePeriod --- Root.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Root.js b/Root.js index cd1a399f4..6938a84ed 100644 --- a/Root.js +++ b/Root.js @@ -346,7 +346,7 @@ case "Cloud": { processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration if(global.EXECUTION_CONFIG.timePeriod){ - processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod + processConfig.timePeriod = Number(global.EXECUTION_CONFIG.timePeriod) } break; } From 3af01296d3a3eb7dcb450bcd631a0badae66ad6b Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 22 Mar 2019 18:33:18 +0100 Subject: [PATCH 42/73] Individual parameters --- Root.js | 4 +-- Run.js | 43 ++++++++++++++++--------------- TradingBotProcessMainLoop.js | 28 ++++++++++----------- package-lock.json | 49 ------------------------------------ package.json | 1 - 5 files changed, 37 insertions(+), 88 deletions(-) diff --git a/Root.js b/Root.js index 6938a84ed..f2c4737fb 100644 --- a/Root.js +++ b/Root.js @@ -345,8 +345,8 @@ switch (global.CURRENT_EXECUTION_AT) { case "Cloud": { processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration - if(global.EXECUTION_CONFIG.timePeriod){ - processConfig.timePeriod = Number(global.EXECUTION_CONFIG.timePeriod) + if(global.TIME_PERIOD){ + processConfig.timePeriod = global.TIME_PERIOD } break; } diff --git a/Run.js b/Run.js index 52f7889a5..0610f0498 100644 --- a/Run.js +++ b/Run.js @@ -137,30 +137,29 @@ function readExecutionConfiguration() { } function getTimePeriod(){ - if(process.env.EXECUTION_PARAMETERS !== undefined){ + if(process.env.TIME_PERIOD !== undefined){ try { - let executionParameters = JSON.parse(process.env.EXECUTION_PARAMETERS) let timePeriodMap = new Map() - timePeriodMap.set("24-hs","86400000") - timePeriodMap.set("12-hs","43200000") - timePeriodMap.set("08-hs","28800000") - timePeriodMap.set("06-hs","21600000") - timePeriodMap.set("04-hs","14400000") - timePeriodMap.set("03-hs","10800000") - timePeriodMap.set("02-hs","7200000") - timePeriodMap.set("01-hs","3600000") - timePeriodMap.set("45-min","2700000") - timePeriodMap.set("40-min","2400000") - timePeriodMap.set("30-min","1800000") - timePeriodMap.set("20-min","1200000") - timePeriodMap.set("15-min","900000") - timePeriodMap.set("10-min","600000") - timePeriodMap.set("05-min","300000") - timePeriodMap.set("04-min","240000") - timePeriodMap.set("03-min","180000") - timePeriodMap.set("02-min","120000") - timePeriodMap.set("01-min","60000") - return timePeriodMap.get(executionParameters.timePeriod) + timePeriodMap.set("24-hs", 86400000) + timePeriodMap.set("12-hs", 43200000) + timePeriodMap.set("08-hs", 28800000) + timePeriodMap.set("06-hs", 21600000) + timePeriodMap.set("04-hs", 14400000) + timePeriodMap.set("03-hs", 10800000) + timePeriodMap.set("02-hs", 7200000) + timePeriodMap.set("01-hs", 3600000) + timePeriodMap.set("45-min", 2700000) + timePeriodMap.set("40-min", 2400000) + timePeriodMap.set("30-min", 1800000) + timePeriodMap.set("20-min", 1200000) + timePeriodMap.set("15-min", 900000) + timePeriodMap.set("10-min", 600000) + timePeriodMap.set("05-min", 300000) + timePeriodMap.set("04-min", 240000) + timePeriodMap.set("03-min", 180000) + timePeriodMap.set("02-min", 120000) + timePeriodMap.set("01-min", 60000) + return timePeriodMap.get(process.env.TIME_PERIOD) } catch (error) { console.log( "[WARN] Run -> readExecutionConfiguration -> getTimePeriod -> Error: ", error); } diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 9d6e6cab5..0f5185b48 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -14,7 +14,7 @@ const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. - let nextLoopTimeoutHandle; + let nextLoopTimeoutHandle; let checkLoopHealthHandle; let thisObject = { @@ -25,7 +25,7 @@ bot["botCache"] = new Map(); let processConfig; let cloudStorage; - let UI_COMMANDS; + let UI_COMMANDS; return thisObject; @@ -58,7 +58,7 @@ } else { filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. } - + break; } case "Browser": { @@ -145,7 +145,7 @@ try { if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); } - bot.enableCheckLoopHealth = true; + bot.enableCheckLoopHealth = true; let fixedTimeLoopIntervalHandle; @@ -248,7 +248,7 @@ } else { - bot.processDatetime = new Date(bot.backtest.beginDatetime); // Set the starting time as the configured beginDatetime. + bot.processDatetime = new Date(bot.backtest.beginDatetime); // Set the starting time as the configured beginDatetime. } @@ -263,7 +263,7 @@ } else { - bot.processDatetime = new Date(bot.processDatetime.valueOf() + timePeriod); // We advance time here. + bot.processDatetime = new Date(bot.processDatetime.valueOf() + timePeriod); // We advance time here. if (UI_COMMANDS.eventHandler !== undefined) { @@ -276,11 +276,11 @@ if (UI_COMMANDS.endDatetime !== undefined) { - endDatetime = new Date(UI_COMMANDS.endDatetime.valueOf()); + endDatetime = new Date(UI_COMMANDS.endDatetime.valueOf()); } else { - endDatetime = new Date(bot.backtest.endDatetime); + endDatetime = new Date(bot.backtest.endDatetime); } @@ -381,7 +381,7 @@ + " " + bot.startMode + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8) + " bot.processDatetime = " + bot.processDatetime.toISOString()); /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ - + let exchangeAPI; let assistant; let userBot; @@ -537,7 +537,7 @@ callBackFunction(err); } } - + function initializeContext() { try { @@ -864,7 +864,7 @@ clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; + bot.enableCheckLoopHealth = false; callBackFunction(err); return; } @@ -1007,7 +1007,7 @@ nextWaitTime = 'Normal'; loopControl(nextWaitTime); - + } catch (err) { logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> err = " + err.message); logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> Execution will continue anyways. "); @@ -1167,7 +1167,7 @@ if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - /* + /* If for any reason this config file cannot be read, we are not going to abort the loop for that. Instead we are going to assume that there are no instructions to stop and we will keep the show running. */ @@ -1217,7 +1217,7 @@ } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.message); + parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); diff --git a/package-lock.json b/package-lock.json index 1180a7ec5..72604727b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,45 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@azure/ms-rest-js": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.2.3.tgz", - "integrity": "sha512-eROQ034b+9v0Hd3wETKi/EwF5pqS3VRAk1Lm8iKVPOP8v30f6Zfzsi420MRfBMsbNCx/mE2N0L65Px7tvcGfVg==", - "requires": { - "axios": "^0.18.0", - "form-data": "^2.3.2", - "tough-cookie": "^2.4.3", - "tslib": "^1.9.2", - "uuid": "^3.2.1", - "xml2js": "^0.4.19" - }, - "dependencies": { - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - } - } - }, - "@azure/storage-blob": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.3.0.tgz", - "integrity": "sha512-KZbJ3q8RpAdeIB5Em1lgXkiq7Mll9bSHHbHavOFMepkkF7HQa3Sez9FdkAVIkVVWK5YoBlshBGZ+mtiSQiS9Fw==", - "requires": { - "@azure/ms-rest-js": "1.2.3", - "events": "3.0.0", - "tslib": "^1.9.3" - } - }, "@types/async": { "version": "2.0.49", "resolved": "https://registry.npmjs.org/@types/async/-/async-2.0.49.tgz", @@ -410,11 +371,6 @@ "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" }, - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -934,11 +890,6 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", diff --git a/package.json b/package.json index 321b779f7..90a19c944 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "author": "Luis-Fernando-Molina", "license": "ISC", "dependencies": { - "@azure/storage-blob": "^10.3.0", "apollo-boost": "^0.1.16", "assert": "^1.4.1", "axios": "^0.18.0", From 29a2fb56eb2bada0a73459015adb43cb90083adc Mon Sep 17 00:00:00 2001 From: Matias Date: Fri, 22 Mar 2019 19:15:34 +0100 Subject: [PATCH 43/73] Moving to paramaters to bot config --- Root.js | 6 ++++-- Run.js | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Root.js b/Root.js index f2c4737fb..23f587d6a 100644 --- a/Root.js +++ b/Root.js @@ -345,8 +345,8 @@ switch (global.CURRENT_EXECUTION_AT) { case "Cloud": { processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration - if(global.TIME_PERIOD){ - processConfig.timePeriod = global.TIME_PERIOD + if(global.EXECUTION_CONFIG.timePeriod){ + processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod } break; } @@ -865,6 +865,8 @@ logger = DEBUG_MODULE.newDebugLog(); logger.bot = pBotConfig; + pBotConfig.timePeriodFileStorage = global.EXECUTION_CONFIG.timePeriodFileStorage + pBotConfig.dataSet = global.EXECUTION_CONFIG.dataSet if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> Entering function."); } diff --git a/Run.js b/Run.js index 0610f0498..be015b060 100644 --- a/Run.js +++ b/Run.js @@ -123,7 +123,9 @@ function readExecutionConfiguration() { global.EXECUTION_CONFIG = { executionList: executionList, startMode: startMode, - timePeriod: getTimePeriod() + timePeriod: getTimePeriod(process.env.TIME_PERIOD), + timePeriodFileStorage: process.env.TIME_PERIOD, + dataSet: process.env.DATA_SET }; readStoragePermissions(); @@ -136,8 +138,8 @@ function readExecutionConfiguration() { } } -function getTimePeriod(){ - if(process.env.TIME_PERIOD !== undefined){ +function getTimePeriod(timePeriod){ + if(timePeriod !== undefined){ try { let timePeriodMap = new Map() timePeriodMap.set("24-hs", 86400000) @@ -159,7 +161,7 @@ function getTimePeriod(){ timePeriodMap.set("03-min", 180000) timePeriodMap.set("02-min", 120000) timePeriodMap.set("01-min", 60000) - return timePeriodMap.get(process.env.TIME_PERIOD) + return timePeriodMap.get(timePeriod) } catch (error) { console.log( "[WARN] Run -> readExecutionConfiguration -> getTimePeriod -> Error: ", error); } From 052f000db948216053d1f49a917cdf07ef902612 Mon Sep 17 00:00:00 2001 From: Matias Date: Mon, 25 Mar 2019 11:09:49 +0100 Subject: [PATCH 44/73] Adding indicator error Causing the process to fail when there was an error on the initialization of the indicator. --- Root.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Root.js b/Root.js index 23f587d6a..a12f148bb 100644 --- a/Root.js +++ b/Root.js @@ -725,9 +725,10 @@ } else { logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> Bot will not be started. "); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot. "); console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message); logger.persist(); + throw new Error("Root -> start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot.") } } } From e92f9cfeb951cf5c7bbfc31161601f835831bbab Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 11:26:28 +0100 Subject: [PATCH 45/73] Update README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1604ed841..26c9cd48e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# AACloud +# Clone Executor -This repository holds the code of the bits of the AA Platform that run in the cloud. +Whithin the Superalgos project, we have the concept of Financial Beings, which are autonomous agents that have a financial life. These FBs entities have a master (imagine a class in programming) and clones (imagine an instance of a class running). The master is the one who aquires reputation after competitions. Every time we need to do a backtest, live trading or participating in a competition, a clone is extracted from the master and is put to run, either in backtest mode, live trading mode or competition mode. The clone lifespan is contrained by the purpose it was created. For instance, a clone created for a competition will live only during the period of such competition. -## About the AA Project +The software needed to execute these clones is the Clone Executor. -The AA Platform is built and maintained by Advanced Algos, the start up behind the AA Project. +## About the Superalgos Project + +Superalgos is built and maintained by the Superalgos Foundation and its Community. Our mission is to enable the fast-paced evolution of crypto trading bots within the context of trading bots competitions. From 066dc0689b5dbe2337a8f14a6b0ceda7888345d6 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 12:08:02 +0100 Subject: [PATCH 46/73] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 402b59b95..f57a84efa 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ bin/* *.cache node_modules/* exchange/Auth0.js +.env From 66e4a286dfb6040cc206ef6c989bd3efac952f35 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 12:17:32 +0100 Subject: [PATCH 47/73] Visual Studio Project Renamed --- AACloud.sln => CloneExecutor.sln | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename AACloud.sln => CloneExecutor.sln (100%) diff --git a/AACloud.sln b/CloneExecutor.sln similarity index 100% rename from AACloud.sln rename to CloneExecutor.sln From 50422852ae3f6736facab672682835b3b5e90463 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 12:31:13 +0100 Subject: [PATCH 48/73] Cloud refactored to Node --- DebugLog.js | 2 +- Exchange/ExchangeAPI.js | 2 +- ExtractionBotProcessMainLoop.js | 8 ++++---- IndicatorBotProcessMainLoop.js | 8 ++++---- Root.js | 10 +++++----- Run.js | 2 +- TradingBotProcessMainLoop.js | 14 +++++++------- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/DebugLog.js b/DebugLog.js index 70adf7be0..50b83f7f8 100644 --- a/DebugLog.js +++ b/DebugLog.js @@ -163,7 +163,7 @@ return; } - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { /* Only ERRORs go to the cloud console. */ diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index 3129473d6..6e8f68098 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -38,7 +38,7 @@ let accessToken let keyId let cloneId - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { keyId = process.env.KEY_ID cloneId = process.env.CLONE_ID diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index 81b4b90a5..b6dbe7ae5 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -49,7 +49,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Cloud": { + case "Node": { if (global.RUN_AS_TEAM) { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. } else { @@ -85,7 +85,7 @@ USER_BOT_MODULE = pMODULE; switch (global.CURRENT_EXECUTION_AT) { - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; break; } @@ -664,7 +664,7 @@ function checkLoopHealth(pLastLoop) { - if (global.CURRENT_EXECUTION_AT !== "Cloud") { + if (global.CURRENT_EXECUTION_AT !== "Node") { return; } @@ -717,7 +717,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. break; } diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 514f6d635..591aa6648 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -51,7 +51,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Cloud": { + case "Node": { if (global.RUN_AS_TEAM) { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. } else { @@ -88,7 +88,7 @@ USER_BOT_MODULE = pMODULE; switch (global.CURRENT_EXECUTION_AT) { - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; break; } @@ -898,7 +898,7 @@ function checkLoopHealth(pLastLoop) { - if (global.CURRENT_EXECUTION_AT !== "Cloud") { + if (global.CURRENT_EXECUTION_AT !== "Node") { return; } @@ -951,7 +951,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. break; } diff --git a/Root.js b/Root.js index a12f148bb..1cf6532fa 100644 --- a/Root.js +++ b/Root.js @@ -140,7 +140,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. break; } @@ -253,7 +253,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "bots" + "/" + listItem.repo; // DevTeams bots only are run at the cloud. console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> Getting Bot Config from the devTeams's Bot. "); @@ -343,7 +343,7 @@ let processConfig = botConfig.processes[i]; switch (global.CURRENT_EXECUTION_AT) { - case "Cloud": { + case "Node": { processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration if(global.EXECUTION_CONFIG.timePeriod){ processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod @@ -819,7 +819,7 @@ let clonName = botConfig.codeName + "-" + "Clon" + clonKey; clonName += ".1.0"; - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { clonName += "-" + process.env.CLONE_ID; } @@ -843,7 +843,7 @@ let genes = {}; let clonName = botConfig.codeName; - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { clonName += "-" + process.env.CLONE_ID; } diff --git a/Run.js b/Run.js index be015b060..926474a32 100644 --- a/Run.js +++ b/Run.js @@ -1,7 +1,7 @@ require('dotenv').config() global.CURRENT_ENVIRONMENT = "Develop"; -global.CURRENT_EXECUTION_AT = "Cloud"; +global.CURRENT_EXECUTION_AT = "Node"; global.SHALL_BOT_STOP = false; global.AT_BREAKPOINT = false; // This is used only when running at the browser. global.RUN_AS_TEAM = false; diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 0f5185b48..4aceb006b 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -52,7 +52,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Cloud": { + case "Node": { if (global.RUN_AS_TEAM) { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. } else { @@ -94,7 +94,7 @@ USER_BOT_MODULE = pMODULE; switch (global.CURRENT_EXECUTION_AT) { - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; break; } @@ -284,7 +284,7 @@ } - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { if (bot.processDatetime.valueOf() > endDatetime.valueOf()) { @@ -323,7 +323,7 @@ } - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { let beginDatetime = new Date(bot.competition.beginDatetime); @@ -987,7 +987,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> updateClonesModule -> Entering function."); } - if (global.CURRENT_EXECUTION_AT === "Cloud") { + if (global.CURRENT_EXECUTION_AT === "Node") { // Update clones module with latest context informations @@ -1079,7 +1079,7 @@ function checkLoopHealth(pLastLoop) { - if (global.CURRENT_EXECUTION_AT !== "Cloud") { + if (global.CURRENT_EXECUTION_AT !== "Node") { return; } @@ -1134,7 +1134,7 @@ let filePath; switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Cloud": { + case "Node": { filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. break; } From 9a277ddd720cc2ac401bc18460ab162b9c3544a8 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 14:34:35 +0100 Subject: [PATCH 49/73] Browser Execution type removed --- DebugLog.js | 19 +-------- Exchange/ExchangeAPI.js | 4 +- ExtractionBotProcessMainLoop.js | 73 ++++----------------------------- IndicatorBotProcessMainLoop.js | 70 ++++--------------------------- Root.js | 69 ++++--------------------------- TradingBotProcessMainLoop.js | 55 +++---------------------- 6 files changed, 33 insertions(+), 257 deletions(-) diff --git a/DebugLog.js b/DebugLog.js index 50b83f7f8..8f82f1c19 100644 --- a/DebugLog.js +++ b/DebugLog.js @@ -60,13 +60,6 @@ internalLoopCounter++; - if (global.CURRENT_EXECUTION_AT === "Browser") { - - //console.log("[INFO] DebugLog -> persist -> We do not persist logs while running at the Browser"); - return; - - } - let contentToPersist = accumulatedLog; accumulatedLog = "["; @@ -149,20 +142,12 @@ if (global.CURRENT_EXECUTION_AT === "IDE") { - console.log("AACloud" + spacePad(pModule, 50) + " : " + pMessage); + console.log("CloneExecutor" + spacePad(pModule, 50) + " : " + pMessage); } if (disableLogging === true) { return; } - if (global.CURRENT_EXECUTION_AT === "Browser") { - - /* Only at the browser we send the messages to the console. At the Cloud it does not make sense. */ - - console.log("AACloud" + spacePad(pModule, 50) + " : " + pMessage); - return; - } - if (global.CURRENT_EXECUTION_AT === "Node") { /* Only ERRORs go to the cloud console. */ @@ -170,7 +155,7 @@ if (pMessage.indexOf("[ERROR]") >= 0) { let now = new Date; - console.log("Loop." + pad(thisObject.bot.loopCounter, 8) + " " + now.toUTCString() + " AACloud " + spacePad(pModule, 20) + " : " + pMessage); + console.log("Loop." + pad(thisObject.bot.loopCounter, 8) + " " + now.toUTCString() + " CloneExecutor " + spacePad(pModule, 20) + " : " + pMessage); } } diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index 6e8f68098..1f29542b4 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -45,9 +45,7 @@ let auth = require('../utils/auth') let authTokenCloud = await auth.authenticate() accessToken = 'Bearer ' + authTokenCloud - } else if (global.CURRENT_EXECUTION_AT === "Browser") { - accessToken = 'Bearer ' + authToken - } + } let keyVaultAPI = createKeyVaultAPIClient(accessToken, keyId, cloneId) apiClient = api.newAPIClient(keyVaultAPI, logger); diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index b6dbe7ae5..8d1b4209c 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -47,25 +47,11 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { let filePath; - - switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Node": { - if (global.RUN_AS_TEAM) { - filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. - } else { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. - } - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. - break; - } - default: { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; } + + if (global.RUN_AS_TEAM) { + filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. + } else { + filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. } const CLOUD_REQUIRE = require(ROOT_DIR + 'CloudRequire'); @@ -84,23 +70,8 @@ USER_BOT_MODULE = pMODULE; - switch (global.CURRENT_EXECUTION_AT) { - case "Node": { - filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO; - break; - } - default: { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - + filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; + cloudRequire.downloadCommons(cloudStorage, filePath, onCommonsDownloaded); function onCommonsDownloaded(err, pMODULE) { @@ -714,34 +685,8 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - let filePath; - - switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Node": { - filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. - break; - } - case "Browser": { - if (global.SHALL_BOT_STOP === false) { - continueCallBack(); - } else { - stopCallBack(); - } - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> onInizialized -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - + let filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. + let fileName = "this.config.json"; cloudStorage.getTextFile(filePath, fileName, onFileReceived); diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 591aa6648..6de54adc5 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -50,25 +50,10 @@ let filePath; - switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Node": { - if (global.RUN_AS_TEAM) { - filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. - } else { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. - } - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. - break; - } - default: { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } + if (global.RUN_AS_TEAM) { + filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. + } else { + filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. } const CLOUD_REQUIRE = require(ROOT_DIR + 'CloudRequire'); @@ -87,22 +72,7 @@ USER_BOT_MODULE = pMODULE; - switch (global.CURRENT_EXECUTION_AT) { - case "Node": { - filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO; - break; - } - default: { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } + filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; cloudRequire.downloadCommons(cloudStorage, filePath, onCommonsDownloaded); @@ -948,34 +918,8 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - let filePath; - - switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Node": { - filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. - break; - } - case "Browser": { - if (global.SHALL_BOT_STOP === false) { - continueCallBack(); - } else { - stopCallBack(); - } - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> onInizialized -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - + let filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. + let fileName = "this.config.json"; cloudStorage.getTextFile(filePath, fileName, onFileReceived); diff --git a/Root.js b/Root.js index 1cf6532fa..240117a74 100644 --- a/Root.js +++ b/Root.js @@ -74,7 +74,7 @@ let cloudStorage; - let logDisplace = "AACloud" + " "; + let logDisplace = "CloneExecutor" + " "; let UI_COMMANDS; return thisObject; @@ -137,21 +137,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - let filePath; - - switch (global.CURRENT_EXECUTION_AT) { - case "Node": { - filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + "AACloud"; // DevTeam Members bots only are run at the browser. - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser' "); - } - } + let filePath = global.DEV_TEAM + "/" + "CloneExecutor"; // DevTeams bots only are run at the cloud. let fileName = "this.config.json"; @@ -230,7 +216,7 @@ continue; } - /* Now we will read the config of the bot from the path we obtained at the AACloud config. */ + /* Now we will read the config of the bot from the path we obtained at the CloneExecutor config. */ let botConfig; @@ -250,28 +236,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - let filePath; - - switch (global.CURRENT_EXECUTION_AT) { - case "Node": { - filePath = global.DEV_TEAM + "/" + "bots" + "/" + listItem.repo; // DevTeams bots only are run at the cloud. - - console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> Getting Bot Config from the devTeams's Bot. "); - console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> filePath = " + filePath); - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO; // DevTeam Members bots only are run at the browser. - - console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> Getting Bot Config from the endUser's Bot. "); - console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> global.USER_LOGGED_IN = " + global.USER_LOGGED_IN); - console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> filePath = " + filePath); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser' "); - } - } + let filePath = global.DEV_TEAM + "/" + "bots" + "/" + listItem.repo; // DevTeams bots only are run at the cloud. let fileName = "this.bot.config.json"; @@ -342,27 +307,11 @@ let processConfig = botConfig.processes[i]; - switch (global.CURRENT_EXECUTION_AT) { - case "Node": { - processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration - if(global.EXECUTION_CONFIG.timePeriod){ - processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod - } - break; - } - case "Browser": { - let startMode = { - live: { run: "false" }, - backtest: { run: "false", waitTime: 5000 }, - competition: { run: "false" } - } - let browserStartMode = global.CURRENT_START_MODE.toLowerCase() - startMode[browserStartMode].run = "true" - - processConfig.startMode = startMode - break; - } + processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration + if(global.EXECUTION_CONFIG.timePeriod){ + processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod } + try { /* We test each type of start Mode to get what to run and how. */ @@ -593,7 +542,7 @@ if (processFound === false) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Process listed at the configuration file of AACloud not found at the configuration file of the bot."); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Process listed at the configuration file of CloneExecutor not found at the configuration file of the bot."); console.log(logDisplace + "Root : [ERROR] start -> findProcess -> listItem.process = " + listItem.process); } diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 4aceb006b..14ad87b49 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -61,16 +61,12 @@ break; } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser. - break; - } case "IDE": { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // This works like Cloud except of a few things. break; } default: { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Node' or 'IDE'."); parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; @@ -93,23 +89,8 @@ USER_BOT_MODULE = pMODULE; - switch (global.CURRENT_EXECUTION_AT) { - case "Node": { - filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; - break; - } - case "Browser": { - filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO; - break; - } - default: { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - + filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; + cloudRequire.downloadCommons(cloudStorage, filePath, onCommonsDownloaded); function onCommonsDownloaded(err, pMODULE) { @@ -1131,34 +1112,8 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - let filePath; - - switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy. - case "Node": { - filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. - break; - } - case "Browser": { - if (global.SHALL_BOT_STOP === false) { - continueCallBack(); - } else { - stopCallBack(); - } - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> onInizialized -> CURRENT_EXECUTION_AT must be either 'Cloud' or 'Browser'."); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> onInizialized -> global.CURRENT_EXECUTION_AT = " + global.CURRENT_EXECUTION_AT); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - + let filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. + let fileName = "this.config.json"; cloudStorage.getTextFile(filePath, fileName, onFileReceived); From 0353bddef7176af96aa56b5835fc4ef9fd925a6f Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 16:25:05 +0100 Subject: [PATCH 50/73] Eliminated the Execution List from the config and the code. Only one clone can be executed at the time now. --- Root.js | 1032 ++++++++++++++++++++++------------------------ Run.js | 6 +- this.config.json | 51 --- 3 files changed, 507 insertions(+), 582 deletions(-) diff --git a/Root.js b/Root.js index 240117a74..710a8ee01 100644 --- a/Root.js +++ b/Root.js @@ -137,7 +137,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - let filePath = global.DEV_TEAM + "/" + "CloneExecutor"; // DevTeams bots only are run at the cloud. + let filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. let fileName = "this.config.json"; @@ -192,224 +192,170 @@ /* Loop through all the processes configured to be run by this Node.js Instance. */ - for (let p = 0; p < global.PLATFORM_CONFIG.executionList.length; p++) { + let cloneToExecute = global.EXECUTION_CONFIG.cloneToExecute; - let listItem; + /* Now we will read the config of the bot from the path we obtained at the CloneExecutor config. */ - /* - The local configuration allows to select the configuration to run - locally, without overwriting the server config. - Here we check that the local configuration for the execution - exist, if it doesn't exist we will take the one on the server. - */ - if (global.EXECUTION_CONFIG === undefined) { - listItem = PLATFORM_CONFIG.executionList[p]; - } else { - listItem = global.EXECUTION_CONFIG.executionList[p]; - } + let botConfig; - if (listItem === undefined || listItem.enabled !== "true") { + getBotConfig(); - console.log(logDisplace + "Root : [INFO] start -> Skipping process for being disabled."); - console.log(logDisplace + "Root : [INFO] start -> listItem.process = " + PLATFORM_CONFIG.executionList[p].process); + function getBotConfig() { - continue; - } + try { + console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> Entering function. "); - /* Now we will read the config of the bot from the path we obtained at the CloneExecutor config. */ + const BLOB_STORAGE = require(ROOT_DIR + 'BlobStorage'); + let cloudStorage = BLOB_STORAGE.newBlobStorage(cloneToExecute); - let botConfig; + cloudStorage.initialize("AAPlatform", onInizialized, true); - getBotConfig(); + function onInizialized(err) { - function getBotConfig() { + if (err.result === global.DEFAULT_OK_RESPONSE.result) { - try { - console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> Entering function. "); + let filePath = global.DEV_TEAM + "/" + "bots" + "/" + cloneToExecute.repo; // DevTeams bots only are run at the cloud. - const BLOB_STORAGE = require(ROOT_DIR + 'BlobStorage'); - let cloudStorage = BLOB_STORAGE.newBlobStorage(listItem); + let fileName = "this.bot.config.json"; - cloudStorage.initialize("AAPlatform", onInizialized, true); + cloudStorage.getTextFile(filePath, fileName, onFileReceived); - function onInizialized(err) { + function onFileReceived(err, text) { - if (err.result === global.DEFAULT_OK_RESPONSE.result) { + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> err = " + err.message); + console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> filePath = " + filePath); + console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> fileName = " + fileName); - let filePath = global.DEV_TEAM + "/" + "bots" + "/" + listItem.repo; // DevTeams bots only are run at the cloud. - - let fileName = "this.bot.config.json"; - - cloudStorage.getTextFile(filePath, fileName, onFileReceived); - - function onFileReceived(err, text) { - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> err = " + err.message); - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> filePath = " + filePath); - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> fileName = " + fileName); - - return; - } - - try { - botConfig = JSON.parse(text); - botConfig.repo = listItem.repo; - findProcess(); - } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> err = " + err.message); - return; - } + return; } - } else { - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> err = " + err.message); - return; + try { + botConfig = JSON.parse(text); + botConfig.repo = cloneToExecute.repo; + findProcess(); + } catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> err = " + err.message); + return; + } } + + } else { + console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> err = " + err.message); + return; } } - catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> err.message = " + err.message); - return; - } } + catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> err.message = " + err.message); + return; + } + } - function findProcess() { + function findProcess() { - try { - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Entering function. "); } + try { + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Entering function. "); } - botConfig.process = listItem.process; - botConfig.debug = {}; + botConfig.process = cloneToExecute.process; + botConfig.debug = {}; - /* Loop Counter */ + /* Loop Counter */ - botConfig.loopCounter = 0; + botConfig.loopCounter = 0; - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Processing item from executionList -> p = " + p); } + /* File Path Root */ - /* File Path Root */ + botConfig.filePathRoot = botConfig.devTeam + "/" + botConfig.codeName + "." + botConfig.version.major + "." + botConfig.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; - botConfig.filePathRoot = botConfig.devTeam + "/" + botConfig.codeName + "." + botConfig.version.major + "." + botConfig.version.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> cloneToExecute.process = " + cloneToExecute.process); } - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> listItem.process = " + listItem.process); } + /* Now we loop throug all the configured processes at each bots configuration until we find the one we are supposed to run at this Node.js process. */ - /* Now we loop throug all the configured processes at each bots configuration until we find the one we are supposed to run at this Node.js process. */ + let processFound = false; - let processFound = false; + for (let i = 0; i < botConfig.processes.length; i++) { - for (let i = 0; i < botConfig.processes.length; i++) { + if (botConfig.processes[i].name === cloneToExecute.process) { - if (botConfig.processes[i].name === listItem.process) { + processFound = true; + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> cloneToExecute.process = " + cloneToExecute.process); } - processFound = true; - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> listItem.process = " + listItem.process); } + let processConfig = botConfig.processes[i]; - let processConfig = botConfig.processes[i]; - - processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration - if(global.EXECUTION_CONFIG.timePeriod){ - processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod - } + processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration + if(global.EXECUTION_CONFIG.timePeriod){ + processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod + } - try { + try { - /* We test each type of start Mode to get what to run and how. */ + /* We test each type of start Mode to get what to run and how. */ - if (processConfig.startMode.allMonths !== undefined) { + if (processConfig.startMode.allMonths !== undefined) { - if (processConfig.startMode.allMonths.run === "true") { + if (processConfig.startMode.allMonths.run === "true") { - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> allMonths start mode detected. "); } + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> allMonths start mode detected. "); } - for (let year = processConfig.startMode.allMonths.maxYear; year >= processConfig.startMode.allMonths.minYear; year--) { + for (let year = processConfig.startMode.allMonths.maxYear; year >= processConfig.startMode.allMonths.minYear; year--) { - for (let month = 12; month > 0; month--) { + for (let month = 12; month > 0; month--) { - let padMonth = pad(month, 2) + let padMonth = pad(month, 2) - let newInstanceBotConfig = JSON.parse(JSON.stringify(botConfig)); + let newInstanceBotConfig = JSON.parse(JSON.stringify(botConfig)); - newInstanceBotConfig.debug = { - month: pad(month, 2), - year: pad(year, 4) - }; + newInstanceBotConfig.debug = { + month: pad(month, 2), + year: pad(year, 4) + }; - let timeDelay = Math.random() * 10 * 1000; // We introduce a short delay so as to not overload the machine. - setTimeout(startProcess, timeDelay); + let timeDelay = Math.random() * 10 * 1000; // We introduce a short delay so as to not overload the machine. + setTimeout(startProcess, timeDelay); - function startProcess() { + function startProcess() { - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); } + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); } - switch (botConfig.type) { - case 'Extraction': { - runExtractionBot(newInstanceBotConfig, processConfig, padMonth, year); - break; - } - case 'Indicator': { - runIndicatorBot(newInstanceBotConfig, processConfig, padMonth, year); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); - } + switch (botConfig.type) { + case 'Extraction': { + runExtractionBot(newInstanceBotConfig, processConfig, padMonth, year); + break; + } + case 'Indicator': { + runIndicatorBot(newInstanceBotConfig, processConfig, padMonth, year); + break; + } + default: { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); } } } } } } + } - if (processConfig.startMode.oneMonth !== undefined) { + if (processConfig.startMode.oneMonth !== undefined) { - if (processConfig.startMode.oneMonth.run === "true") { + if (processConfig.startMode.oneMonth.run === "true") { - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> oneMonth start mode detected. "); } + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> oneMonth start mode detected. "); } - startProcess(); + startProcess(); - function startProcess() { + function startProcess() { - if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); } + if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); } - let month = pad(processConfig.startMode.oneMonth.month, 2); - let year = processConfig.startMode.oneMonth.year; + let month = pad(processConfig.startMode.oneMonth.month, 2); + let year = processConfig.startMode.oneMonth.year; - botConfig.debug = { - month: pad(month, 2), - year: pad(year, 4) - }; - - switch (botConfig.type) { - case 'Extraction': { - runExtractionBot(botConfig, processConfig, month, year); - break; - } - case 'Indicator': { - runIndicatorBot(botConfig, processConfig, month, year); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); - } - } - } - } - } - - if (processConfig.startMode.noTime !== undefined) { - - if (processConfig.startMode.noTime.run === "true") { - - let month = pad((new Date()).getUTCMonth() + 1, 2); - let year = (new Date()).getUTCFullYear(); - - if (processConfig.startMode.noTime.resumeExecution === "true") { - botConfig.hasTheBotJustStarted = false; - } else { - botConfig.hasTheBotJustStarted = true; - } + botConfig.debug = { + month: pad(month, 2), + year: pad(year, 4) + }; switch (botConfig.type) { case 'Extraction': { @@ -421,464 +367,494 @@ break; } default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); } } } } + } - if (processConfig.startMode.fixedInterval !== undefined) { + if (processConfig.startMode.noTime !== undefined) { - if (processConfig.startMode.fixedInterval.run === "true") { + if (processConfig.startMode.noTime.run === "true") { - botConfig.runAtFixedInterval = true; - botConfig.fixedInterval = processConfig.startMode.fixedInterval.interval; - - let month = pad((new Date()).getUTCMonth() + 1, 2); - let year = (new Date()).getUTCFullYear(); - - switch (botConfig.type) { - case 'Extraction': { - runExtractionBot(botConfig, processConfig, month, year); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); - } - } - } - } - - if (processConfig.startMode.live !== undefined) { - - if (processConfig.startMode.live.run === "true") { - - botConfig.startMode = "Live"; - console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); - - let month = pad((new Date()).getUTCMonth() + 1, 2); - let year = (new Date()).getUTCFullYear(); - - if (processConfig.startMode.live.resumeExecution === "true") { - botConfig.hasTheBotJustStarted = false; - } else { - botConfig.hasTheBotJustStarted = true; - } - - switch (botConfig.type) { - case 'Trading': { - runTradingBot(botConfig, processConfig); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); - } - } - } - } - - if (processConfig.startMode.backtest !== undefined) { - - if (processConfig.startMode.backtest.run === "true") { - - botConfig.startMode = "Backtest"; - console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); - - botConfig.backtest = processConfig.startMode.backtest; - - /* We override these waitTimes to the one specified at the backtest configuration. */ - - processConfig.normalWaitTime = processConfig.startMode.backtest.waitTime; - processConfig.retryWaitTime = processConfig.startMode.backtest.waitTime; - - /* Backtest Mode does not support Resume Execution, so this is the only way. */ + let month = pad((new Date()).getUTCMonth() + 1, 2); + let year = (new Date()).getUTCFullYear(); + if (processConfig.startMode.noTime.resumeExecution === "true") { + botConfig.hasTheBotJustStarted = false; + } else { botConfig.hasTheBotJustStarted = true; - - switch (botConfig.type) { - case 'Trading': { - runTradingBot(botConfig, processConfig); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); - } - } - } - } - - if (processConfig.startMode.competition !== undefined) { - - if (processConfig.startMode.competition.run === "true") { - - botConfig.startMode = "Competition"; - console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); - - botConfig.competition = processConfig.startMode.competition; - - if (processConfig.startMode.competition.resumeExecution === "false") { - botConfig.hasTheBotJustStarted = true; - } else { - botConfig.hasTheBotJustStarted = false; - } - - switch (botConfig.type) { - case 'Trading': { - runTradingBot(botConfig, processConfig); - break; - } - default: { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); - } - } - } - } - - } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected exception. -> err.message = " + err.message); - } - } - } - - if (processFound === false) { - - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Process listed at the configuration file of CloneExecutor not found at the configuration file of the bot."); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> listItem.process = " + listItem.process); - - } - - function runExtractionBot(pBotConfig, pProcessConfig, pMonth, pYear) { - - try { - - const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); - let logger; - - logger = DEBUG_MODULE.newDebugLog(); - logger.bot = pBotConfig; - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> Entering function."); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> pMonth = " + pMonth); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> pYear = " + pYear); } - - let extractionBotMainLoop = EXTRACTION_BOT_MAIN_LOOP_MODULE.newExtractionBotProcessMainLoop(pBotConfig, logger); - extractionBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); - - function onInitializeReady(err) { - - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - - extractionBotMainLoop.run(pMonth, pYear, whenRunFinishes); - - function whenRunFinishes(err) { - - pBotConfig.loopCounter = 0; - - let botId; - if (pYear !== undefined) { - botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process + "." + pYear + "." + pMonth; - } else { - botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process; - } - - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - - logger.persist(); - - } else { - - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bye."); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution was aborted."); - logger.persist(); - } } - } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> Bot will not be started. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> err = " + err.message); - - logger.persist(); + switch (botConfig.type) { + case 'Extraction': { + runExtractionBot(botConfig, processConfig, month, year); + break; + } + case 'Indicator': { + runIndicatorBot(botConfig, processConfig, month, year); + break; + } + default: { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); + } + } } } - } - catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> err = " + err.message); - } - } - function runIndicatorBot(pBotConfig, pProcessConfig, pMonth, pYear) { + if (processConfig.startMode.fixedInterval !== undefined) { - try { - const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); - let logger; + if (processConfig.startMode.fixedInterval.run === "true") { - logger = DEBUG_MODULE.newDebugLog(); - logger.bot = pBotConfig; + botConfig.runAtFixedInterval = true; + botConfig.fixedInterval = processConfig.startMode.fixedInterval.interval; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> Entering function."); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> pMonth = " + pMonth); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> pYear = " + pYear); } + let month = pad((new Date()).getUTCMonth() + 1, 2); + let year = (new Date()).getUTCFullYear(); - let indicatorBotMainLoop = INDICATOR_BOT_MAIN_LOOP_MODULE.newIndicatorBotProcessMainLoop(pBotConfig, logger); - indicatorBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); - - function onInitializeReady(err) { - - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - - indicatorBotMainLoop.run(pMonth, pYear, whenRunFinishes); - - function whenRunFinishes(err) { - - pBotConfig.loopCounter = 0; - - let botId; - if (pYear !== undefined) { - botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process + "." + pYear + "." + pMonth; - } else { - botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process; + switch (botConfig.type) { + case 'Extraction': { + runExtractionBot(botConfig, processConfig, month, year); + break; } - - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - - logger.persist(); - - } else { - - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bye."); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); - logger.persist(); + default: { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); } } - - } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message); - logger.persist(); - throw new Error("Root -> start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot.") } } - } - catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> err = " + err.message); - } - } + if (processConfig.startMode.live !== undefined) { - function runTradingBot(pBotConfig, pProcessConfig) { + if (processConfig.startMode.live.run === "true") { - try { + botConfig.startMode = "Live"; + console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); - if (FULL_LOG === true) { console.log(logDisplace + "[INFO] start -> findProcess -> runTradingBot -> Entering function."); } - - if (pBotConfig.genes !== undefined) { - - /* Here, based on the gene we will create one instance for each combination of genes */ - - let valueMatrix = []; - - for (let i = 0; i < pBotConfig.genes.length; i++) { - - let gene = pBotConfig.genes[i]; - - let possibleValues = []; - - for (let j = gene.lowerLimit; j <= gene.upperLimit; j++) { - - possibleValues.push(j); + let month = pad((new Date()).getUTCMonth() + 1, 2); + let year = (new Date()).getUTCFullYear(); + if (processConfig.startMode.live.resumeExecution === "true") { + botConfig.hasTheBotJustStarted = false; + } else { + botConfig.hasTheBotJustStarted = true; } - valueMatrix.push(possibleValues); - - } - - /* - Now we have all the possible genes values in a multi-dimensional matrix. - We will go thorugh each of the elements of each dimension and get each combination possible with the other dimmensions. - */ - - let combinations = []; - let combination = []; - let dimensionIndex = 0; - - calculateCombinations(dimensionIndex, combination); - - function calculateCombinations(pDimensionIndex, pCombination) { - - let dimension = valueMatrix[pDimensionIndex]; - - for (let j = 0; j < dimension.length; j++) { - - let copy = JSON.parse(JSON.stringify(pCombination)); - - let value = dimension[j]; - copy.push(value); - - if (pDimensionIndex < valueMatrix.length - 1) { - - calculateCombinations(pDimensionIndex + 1, copy); - - } else { - - combinations.push(copy); - + switch (botConfig.type) { + case 'Trading': { + runTradingBot(botConfig, processConfig); + break; + } + default: { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); } } } + } - /* At this point we have an array with all the possible combinations, we just need to create an instance for each one and set the genes according to that. */ + if (processConfig.startMode.backtest !== undefined) { - for (let i = 0; i < combinations.length; i++) { + if (processConfig.startMode.backtest.run === "true") { - let botConfig = JSON.parse(JSON.stringify(pBotConfig)); - let combination = combinations[i]; - let genes = {}; - let clonKey = ""; + botConfig.startMode = "Backtest"; + console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); - for (let j = 0; j < botConfig.genes.length; j++) { + botConfig.backtest = processConfig.startMode.backtest; - genes[botConfig.genes[j].name] = combination[j]; - clonKey = clonKey + "." + combination[j]; + /* We override these waitTimes to the one specified at the backtest configuration. */ - } + processConfig.normalWaitTime = processConfig.startMode.backtest.waitTime; + processConfig.retryWaitTime = processConfig.startMode.backtest.waitTime; - let clonName = botConfig.codeName + "-" + "Clon" + clonKey; - clonName += ".1.0"; + /* Backtest Mode does not support Resume Execution, so this is the only way. */ - if (global.CURRENT_EXECUTION_AT === "Node") { - clonName += "-" + process.env.CLONE_ID; - } - - botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; - - botConfig.instance = clonName; - botConfig.instanceIndex = i; - - setTimeout(execute, i * Math.random() * 10 * 1000); - - function execute() { - - createBotInstance(genes, combinations.length, botConfig); + botConfig.hasTheBotJustStarted = true; + switch (botConfig.type) { + case 'Trading': { + runTradingBot(botConfig, processConfig); + break; + } + default: { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); + } } } + } + + if (processConfig.startMode.competition !== undefined) { + + if (processConfig.startMode.competition.run === "true") { + + botConfig.startMode = "Competition"; + console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode); + + botConfig.competition = processConfig.startMode.competition; + + if (processConfig.startMode.competition.resumeExecution === "false") { + botConfig.hasTheBotJustStarted = true; + } else { + botConfig.hasTheBotJustStarted = false; + } + + switch (botConfig.type) { + case 'Trading': { + runTradingBot(botConfig, processConfig); + break; + } + default: { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); + } + } + } + } + + } catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected exception. -> err.message = " + err.message); + } + } + } + + if (processFound === false) { + + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Process listed at the configuration file of CloneExecutor not found at the configuration file of the bot."); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> cloneToExecute.process = " + cloneToExecute.process); + + } + + function runExtractionBot(pBotConfig, pProcessConfig, pMonth, pYear) { + + try { + + const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); + let logger; + + logger = DEBUG_MODULE.newDebugLog(); + logger.bot = pBotConfig; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> pMonth = " + pMonth); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> pYear = " + pYear); } + + let extractionBotMainLoop = EXTRACTION_BOT_MAIN_LOOP_MODULE.newExtractionBotProcessMainLoop(pBotConfig, logger); + extractionBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); + + function onInitializeReady(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + extractionBotMainLoop.run(pMonth, pYear, whenRunFinishes); + + function whenRunFinishes(err) { + + pBotConfig.loopCounter = 0; + + let botId; + if (pYear !== undefined) { + botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process + "." + pYear + "." + pMonth; + } else { + botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process; + } + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + + logger.persist(); + + } else { + + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bye."); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution was aborted."); + logger.persist(); + } + } + } else { + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> Bot will not be started. "); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> err = " + err.message); - /* If the bot does not have any genes at all */ + logger.persist(); + } + } + } + catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> err = " + err.message); + } + } + function runIndicatorBot(pBotConfig, pProcessConfig, pMonth, pYear) { + + try { + const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); + let logger; + + logger = DEBUG_MODULE.newDebugLog(); + logger.bot = pBotConfig; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> pMonth = " + pMonth); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> pYear = " + pYear); } + + let indicatorBotMainLoop = INDICATOR_BOT_MAIN_LOOP_MODULE.newIndicatorBotProcessMainLoop(pBotConfig, logger); + indicatorBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); + + function onInitializeReady(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + indicatorBotMainLoop.run(pMonth, pYear, whenRunFinishes); + + function whenRunFinishes(err) { + + pBotConfig.loopCounter = 0; + + let botId; + if (pYear !== undefined) { + botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process + "." + pYear + "." + pMonth; + } else { + botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process; + } + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + + logger.persist(); + + } else { + + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bye."); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); + logger.persist(); + } + } + + } else { + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot. "); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message); + logger.persist(); + throw new Error("Root -> start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot.") + } + } + } + catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> err = " + err.message); + + } + } + + function runTradingBot(pBotConfig, pProcessConfig) { + + try { + + if (FULL_LOG === true) { console.log(logDisplace + "[INFO] start -> findProcess -> runTradingBot -> Entering function."); } + + if (pBotConfig.genes !== undefined) { + + /* Here, based on the gene we will create one instance for each combination of genes */ + + let valueMatrix = []; + + for (let i = 0; i < pBotConfig.genes.length; i++) { + + let gene = pBotConfig.genes[i]; + + let possibleValues = []; + + for (let j = gene.lowerLimit; j <= gene.upperLimit; j++) { + + possibleValues.push(j); + + } + + valueMatrix.push(possibleValues); + + } + + /* + Now we have all the possible genes values in a multi-dimensional matrix. + We will go thorugh each of the elements of each dimension and get each combination possible with the other dimmensions. + */ + + let combinations = []; + let combination = []; + let dimensionIndex = 0; + + calculateCombinations(dimensionIndex, combination); + + function calculateCombinations(pDimensionIndex, pCombination) { + + let dimension = valueMatrix[pDimensionIndex]; + + for (let j = 0; j < dimension.length; j++) { + + let copy = JSON.parse(JSON.stringify(pCombination)); + + let value = dimension[j]; + copy.push(value); + + if (pDimensionIndex < valueMatrix.length - 1) { + + calculateCombinations(pDimensionIndex + 1, copy); + + } else { + + combinations.push(copy); + + } + } + } + + /* At this point we have an array with all the possible combinations, we just need to create an instance for each one and set the genes according to that. */ + + for (let i = 0; i < combinations.length; i++) { + + let botConfig = JSON.parse(JSON.stringify(pBotConfig)); + let combination = combinations[i]; let genes = {}; - let clonName = botConfig.codeName; + let clonKey = ""; + + for (let j = 0; j < botConfig.genes.length; j++) { + + genes[botConfig.genes[j].name] = combination[j]; + clonKey = clonKey + "." + combination[j]; + + } + + let clonName = botConfig.codeName + "-" + "Clon" + clonKey; + clonName += ".1.0"; if (global.CURRENT_EXECUTION_AT === "Node") { clonName += "-" + process.env.CLONE_ID; } - clonName += ".1.0"; - botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; - pBotConfig.instance = clonName; - pBotConfig.instanceIndex = 0; + botConfig.instance = clonName; + botConfig.instanceIndex = i; - createBotInstance(genes, 1, pBotConfig); + setTimeout(execute, i * Math.random() * 10 * 1000); + function execute() { + + createBotInstance(genes, combinations.length, botConfig); + + } + } + } else { + + /* If the bot does not have any genes at all */ + + let genes = {}; + let clonName = botConfig.codeName; + + if (global.CURRENT_EXECUTION_AT === "Node") { + clonName += "-" + process.env.CLONE_ID; } + clonName += ".1.0"; - function createBotInstance(pGenes, pTotalInstances, pBotConfig) { + botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; - const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); - let logger; + pBotConfig.instance = clonName; + pBotConfig.instanceIndex = 0; - logger = DEBUG_MODULE.newDebugLog(); - logger.bot = pBotConfig; - pBotConfig.timePeriodFileStorage = global.EXECUTION_CONFIG.timePeriodFileStorage - pBotConfig.dataSet = global.EXECUTION_CONFIG.dataSet + createBotInstance(genes, 1, pBotConfig); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> Entering function."); } + } - let tradingBotMainLoop = TRADING_BOT_MAIN_LOOP_MODULE.newTradingBotProcessMainLoop(pBotConfig, logger); - tradingBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); - function onInitializeReady(err) { + function createBotInstance(pGenes, pTotalInstances, pBotConfig) { - if (err.result === global.DEFAULT_OK_RESPONSE.result) { + const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); + let logger; - tradingBotMainLoop.run(pGenes, pTotalInstances, whenRunFinishes); + logger = DEBUG_MODULE.newDebugLog(); + logger.bot = pBotConfig; + pBotConfig.timePeriodFileStorage = global.EXECUTION_CONFIG.timePeriodFileStorage + pBotConfig.dataSet = global.EXECUTION_CONFIG.dataSet - function whenRunFinishes(err) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> Entering function."); } - pBotConfig.loopCounter = 0; + let tradingBotMainLoop = TRADING_BOT_MAIN_LOOP_MODULE.newTradingBotProcessMainLoop(pBotConfig, logger); + tradingBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); - let botId; + function onInitializeReady(err) { - botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.instance + "." + pBotConfig.process; + if (err.result === global.DEFAULT_OK_RESPONSE.result) { - if (err.result === global.DEFAULT_OK_RESPONSE.result) { + tradingBotMainLoop.run(pGenes, pTotalInstances, whenRunFinishes); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + function whenRunFinishes(err) { - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.persist(); + pBotConfig.loopCounter = 0; - } else { + let botId; - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bye."); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); - logger.persist(); - } + botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.instance + "." + pBotConfig.process; + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.persist(); + + } else { + + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bye."); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); + logger.persist(); } - - } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> Bot will not be started. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = " + err.message); - - logger.persist(); } + + } else { + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> Bot will not be started. "); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = " + err.message); + + logger.persist(); } } } - catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> err = " + err.message); - } } + catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> err = " + err.message); + } + } - } - catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> err.message = " + err.message); - return; - } + } + catch (err) { + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> err.message = " + err.message); + return; } } + } } diff --git a/Run.js b/Run.js index 926474a32..980e7dd72 100644 --- a/Run.js +++ b/Run.js @@ -112,16 +112,16 @@ function readExecutionConfiguration() { startMode[process.env.START_MODE].run = "true" - let executionList = [{ + let cloneToExecute = { enabled: "true", devTeam: process.env.DEV_TEAM, bot: process.env.BOT, process: process.env.PROCESS, repo: global.CURRENT_BOT_REPO - }] + } global.EXECUTION_CONFIG = { - executionList: executionList, + cloneToExecute: cloneToExecute, startMode: startMode, timePeriod: getTimePeriod(process.env.TIME_PERIOD), timePeriodFileStorage: process.env.TIME_PERIOD, diff --git a/this.config.json b/this.config.json index 9f33a2962..46ab69018 100644 --- a/this.config.json +++ b/this.config.json @@ -5,57 +5,6 @@ "minor": 1, "patch": 0 }, - "executionList": [ - { - "enabled": "false", - "devTeam": "AAMasters", - "bot": "AAMariam", - "process": "Trading-Process", - "repo": "AAMariam-Trading-Bot" - }, - { - "enabled": "false", - "devTeam": "AAMasters", - "bot": "AACharly", - "process": "Poloniex-Live-Trades", - "repo": "AACharly-Extraction-Bot" - }, - { - "enabled": "false", - "devTeam": "AAMasters", - "bot": "AACharly", - "process": "Poloniex-Hole-Fixing", - "repo": "AACharly-Extraction-Bot" - }, - { - "enabled": "false", - "devTeam": "AAMasters", - "bot": "AABruce", - "process": "One-Min-Daily-Candles-Volumes", - "repo": "AABruce-Indicator-Bot" - }, - { - "enabled": "false", - "devTeam": "AAMasters", - "bot": "AAOlivia", - "process": "Multi-Period-Daily", - "repo": "AAOlivia-Indicator-Bot" - }, - { - "enabled": "false", - "devTeam": "AAMasters", - "bot": "AAOlivia", - "process": "Multi-Period-Market", - "repo": "AAOlivia-Indicator-Bot" - }, - { - "enabled": "true", - "devTeam": "AAMasters", - "bot": "AAChris", - "process": "Multi-Period-Market", - "repo": "AAOlivia-Indicator-Bot" - } - ], "stopGracefully": false, "marketRateProvider": { "devTeam": "AAMasters", From dc7aae78672cb5e5317cb20cd0624e682e120d40 Mon Sep 17 00:00:00 2001 From: Matias Date: Mon, 25 Mar 2019 17:02:48 +0100 Subject: [PATCH 51/73] Adding Begin Time to indicator --- Run.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Run.js b/Run.js index 980e7dd72..d47d89476 100644 --- a/Run.js +++ b/Run.js @@ -16,13 +16,13 @@ global.MARKET = { process.on('uncaughtException', function (err) { console.log('[INFO] Run -> uncaughtException -> err.message = ' + err.message); console.log('[INFO] Run -> uncaughtException -> err.stack = ', err.stack); - return; + throw new Error() }); process.on('unhandledRejection', (reason, p) => { console.log('[INFO] Run -> unhandledRejection -> reason = ' + reason); console.log('[INFO] Run -> unhandledRejection -> p = ' + JSON.stringify(p)); - return; + throw new Error() }); process.on('exit', function (code) { @@ -92,7 +92,8 @@ function readExecutionConfiguration() { month: process.env.MONTH } let noTime = { - run: "false" + run: "false", + beginDatetime: process.env.BEGIN_DATE_TIME } let fixedInterval = { run: "false", From 676d0d34e5378ec6f1cd4478c17f961d01120ef1 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 17:46:10 +0100 Subject: [PATCH 52/73] Begint Time arriving to MultiPeriodDaily market --- MultiPeriodDaily.js | 1 - Root.js | 5 +++++ Run.js | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 508590812..562cd2f3f 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -247,7 +247,6 @@ */ contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); - //contextVariables.lastFile = new Date(contextVariables.lastFile.valueOf() + ONE_DAY_IN_MILISECONDS); if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile === undefined"); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> contextVariables.lastFile = " + contextVariables.lastFile); } diff --git a/Root.js b/Root.js index 710a8ee01..0b125f7c0 100644 --- a/Root.js +++ b/Root.js @@ -287,6 +287,11 @@ if(global.EXECUTION_CONFIG.timePeriod){ processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod } + + if (processConfig.framework.name === "Multi-Period-Daily") { + processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; + processConfig.framework.startDate.resumeExecution = processConfig.startMode.noTime.resumeExecution; + } try { diff --git a/Run.js b/Run.js index d47d89476..97f972dfe 100644 --- a/Run.js +++ b/Run.js @@ -93,7 +93,8 @@ function readExecutionConfiguration() { } let noTime = { run: "false", - beginDatetime: process.env.BEGIN_DATE_TIME + beginDatetime: process.env.BEGIN_DATE_TIME, + resumeExecution: process.env.RESUME_EXECUTION } let fixedInterval = { run: "false", From 2e82e7e22821ded3317395e81d2dd39a7c47e37b Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 25 Mar 2019 18:11:29 +0100 Subject: [PATCH 53/73] Supports Begin Date and Resume Execution on Multi Period Daily Framework --- MultiPeriodDaily.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 562cd2f3f..5d54bc0b6 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -233,8 +233,13 @@ if (thisReport.lastFile !== undefined) { - contextVariables.lastFile = new Date(thisReport.lastFile); + if (bot.hasTheBotJustStarted === true && processConfig.framework.startDate.resumeExecution === "false") { + + startFromBegining(); + return; + } + contextVariables.lastFile = new Date(thisReport.lastFile); interExecutionMemoryArray = thisReport.interExecutionMemoryArray; processTimePeriods(); @@ -246,10 +251,16 @@ In the case when there is no status report, we assume like the last processed file is the one on the date of Begining of Market. */ + startFromBegining(); + return; + } + + function startFromBegining() { + contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> thisReport.lastFile === undefined"); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> contextVariables.lastFile = " + contextVariables.lastFile); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> startFromBegining -> thisReport.lastFile === undefined"); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> startFromBegining -> contextVariables.lastFile = " + contextVariables.lastFile); } /* The first time the process is running is the right time to create the data structure that is going to be shared across different executions. @@ -258,14 +269,13 @@ interExecutionMemoryArray = []; - for (let i = 0; i < global.dailyFilePeriods.length; i++) - { + for (let i = 0; i < global.dailyFilePeriods.length; i++) { let emptyObject = {}; interExecutionMemoryArray.push(emptyObject); } processTimePeriods(); - return; + } } catch (err) { @@ -734,6 +744,7 @@ thisReport.file.interExecutionMemoryArray = interExecutionMemoryArray; thisReport.save(callBack); + bot.hasTheBotJustStarted = false; } catch (err) { logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.message); From ada66e41c837d6335d4a0cf6aa7879320056d9e5 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 26 Mar 2019 13:35:20 +0100 Subject: [PATCH 54/73] BUG corrected. Framework is not required on every bot --- Root.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Root.js b/Root.js index 0b125f7c0..158a8ac82 100644 --- a/Root.js +++ b/Root.js @@ -288,11 +288,13 @@ processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod } - if (processConfig.framework.name === "Multi-Period-Daily") { - processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; - processConfig.framework.startDate.resumeExecution = processConfig.startMode.noTime.resumeExecution; + if (processConfig.framework !== undefined) { + if (processConfig.framework.name === "Multi-Period-Daily") { + processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; + processConfig.framework.startDate.resumeExecution = processConfig.startMode.noTime.resumeExecution; + } } - + try { /* We test each type of start Mode to get what to run and how. */ From 1a1301af87687e505335f2ebf6f82dfb2840b8ad Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 26 Mar 2019 17:12:20 +0100 Subject: [PATCH 55/73] Extradata on execution history --- Assistant.js | 8 +++++++- Context.js | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Assistant.js b/Assistant.js index d4fbb4346..28f5c0065 100644 --- a/Assistant.js +++ b/Assistant.js @@ -30,7 +30,8 @@ rememberThis: rememberThis, remindMeOf: remindMeOf, truncDecimals: truncDecimals, - sendEmail: sendEmail + sendEmail: sendEmail, + addExtraData: addExtraData }; let utilities = UTILITIES.newCloudUtilities(bot, logger); @@ -1363,6 +1364,11 @@ return; } + function addExtraData(pExtraDataArray) { + + context.extraData = pExtraDataArray; + } + function truncDecimals(pFloatValue, pDecimals) { if (!pDecimals) pDecimals = 8; // Default value diff --git a/Context.js b/Context.js index df5cd196f..1d272378a 100644 --- a/Context.js +++ b/Context.js @@ -45,7 +45,8 @@ messageBody: "" }, initialize: initialize, - saveThemAll: saveThemAll + saveThemAll: saveThemAll, + extraData: [] }; /* @@ -492,7 +493,9 @@ thisObject.newHistoryRecord.messageBody ]; - thisObject.executionHistory.push(newRecord); + let recordWithExtraData = newRecord.concat(thisObject.extraData); + + thisObject.executionHistory.push(recordWithExtraData); let fileContent = JSON.stringify(thisObject.executionHistory); From cc49dd3f179b4cd1a306f43ed4d133f7cc1875cf Mon Sep 17 00:00:00 2001 From: Matias Date: Tue, 26 Mar 2019 18:50:22 +0100 Subject: [PATCH 56/73] Throwing error to allow kubernetes restart --- Run.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Run.js b/Run.js index 97f972dfe..e3d194ece 100644 --- a/Run.js +++ b/Run.js @@ -28,7 +28,7 @@ process.on('unhandledRejection', (reason, p) => { process.on('exit', function (code) { try { console.log('[INFO] Run -> process.on.exit -> About to exit -> code = ' + code); - return; + throw new Error() } catch (err) { console.log("[ERROR] Run -> process.on.exit -> Error Logging Error Code."); From 04f046890338c76783aaaf238a0b8663a24e031b Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 27 Mar 2019 09:11:37 +0100 Subject: [PATCH 57/73] Multi Period Market also accepting .ENV initial Date for simulation --- Root.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Root.js b/Root.js index 158a8ac82..86f99e4c1 100644 --- a/Root.js +++ b/Root.js @@ -289,8 +289,10 @@ } if (processConfig.framework !== undefined) { - if (processConfig.framework.name === "Multi-Period-Daily") { - processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; + if (processConfig.framework.name === "Multi-Period-Daily" || processConfig.framework.name === "Multi-Period-Market") { + if (processConfig.startMode.noTime.beginDatetime !== undefined) { + processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime; + } processConfig.framework.startDate.resumeExecution = processConfig.startMode.noTime.resumeExecution; } } From 1b82fb8206edbd99b3ef2e63fe2837e03995db28 Mon Sep 17 00:00:00 2001 From: Matias Date: Wed, 27 Mar 2019 14:49:48 +0100 Subject: [PATCH 58/73] Normal exit process --- Run.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Run.js b/Run.js index e3d194ece..a9c441bb8 100644 --- a/Run.js +++ b/Run.js @@ -26,15 +26,7 @@ process.on('unhandledRejection', (reason, p) => { }); process.on('exit', function (code) { - try { - console.log('[INFO] Run -> process.on.exit -> About to exit -> code = ' + code); - throw new Error() - } - catch (err) { - console.log("[ERROR] Run -> process.on.exit -> Error Logging Error Code."); - console.log("[ERROR] Run -> process.on.exit -> err.message = " + err.message); - return; - } + console.log('[INFO] Run -> process.on.exit -> About to exit -> code = ' + code); }); readExecutionConfiguration(); From c01d5beed0834eea091c070336d229ea2b3a408d Mon Sep 17 00:00:00 2001 From: Matias Date: Wed, 27 Mar 2019 20:16:16 +0100 Subject: [PATCH 59/73] Exiting Process change --- Run.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Run.js b/Run.js index a9c441bb8..59cefc5fa 100644 --- a/Run.js +++ b/Run.js @@ -16,13 +16,13 @@ global.MARKET = { process.on('uncaughtException', function (err) { console.log('[INFO] Run -> uncaughtException -> err.message = ' + err.message); console.log('[INFO] Run -> uncaughtException -> err.stack = ', err.stack); - throw new Error() + process.exit(1) }); process.on('unhandledRejection', (reason, p) => { - console.log('[INFO] Run -> unhandledRejection -> reason = ' + reason); + console.log('[INFO] Run -> unhandledRejection -> reason = ' + JSON.stringify(reason)); console.log('[INFO] Run -> unhandledRejection -> p = ' + JSON.stringify(p)); - throw new Error() + process.exit(1) }); process.on('exit', function (code) { From 3b9edf74c788c2bea04abcd8576930cc8f456672 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 27 Mar 2019 20:34:26 +0100 Subject: [PATCH 60/73] Improved logging, added bot.processDatetime at Indicators and extractors Loop Log and Internal Loop --- DebugLog.js | 2 +- ExtractionBotProcessMainLoop.js | 4 ++-- IndicatorBotProcessMainLoop.js | 4 ++-- MultiPeriodDaily.js | 21 ++++++++++----------- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/DebugLog.js b/DebugLog.js index 8f82f1c19..d4b23743f 100644 --- a/DebugLog.js +++ b/DebugLog.js @@ -42,7 +42,7 @@ function newInternalLoop(pBot, pProcess) { - console.log(new Date().toISOString() + " " + strPad(pBot, 20) + " " + strPad(pProcess, 30) + " Entered into Internal Loop # " + strPad(internalLoopCounter + 1, 4)); + console.log(new Date().toISOString() + " " + strPad(pBot, 20) + " " + strPad(pProcess, 30) + " Entered into Internal Loop # " + strPad(internalLoopCounter + 1, 4) + " bot.processDatetime = " + thisObject.bot.processDatetime.toISOString()); persist(); diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index 8d1b4209c..914d95a27 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -153,8 +153,8 @@ /* High level log entry */ - console.log(bot.processDatetime.toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4) - + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8)); + console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4) + + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8) + " bot.processDatetime = " + bot.processDatetime.toISOString()); /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 6de54adc5..f9c58dd20 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -156,8 +156,8 @@ /* High level log entry */ - console.log(bot.processDatetime.toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4) - + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8)); + console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4) + + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8) + " bot.processDatetime = " + bot.processDatetime.toISOString()); /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 5d54bc0b6..6fe54df00 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -96,7 +96,6 @@ }; let previousDay; // Holds the date of the previous day relative to the processing date. - let currentDay; // Holds the processing date. let interExecutionMemoryArray; @@ -297,7 +296,7 @@ let n; let botNeverRan = true; - currentDay = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop. + bot.processDatetime = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop. advanceTime(); @@ -309,15 +308,15 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> Entering function."); } - currentDay = new Date(currentDay.valueOf() + ONE_DAY_IN_MILISECONDS); - previousDay = new Date(currentDay.valueOf() - ONE_DAY_IN_MILISECONDS); + bot.processDatetime = new Date(bot.processDatetime.valueOf() + ONE_DAY_IN_MILISECONDS); + previousDay = new Date(bot.processDatetime.valueOf() - ONE_DAY_IN_MILISECONDS); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> currentDay = " + currentDay); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> bot.processDatetime = " + bot.processDatetime); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> previousDay = " + previousDay); } /* Validation that we are not going past the head of the market. */ - if (currentDay.valueOf() > contextVariables.dateEndOfMarket.valueOf()) { + if (bot.processDatetime.valueOf() > contextVariables.dateEndOfMarket.valueOf()) { const logText = "Head of the market found @ " + previousDay.getUTCFullYear() + "/" + (previousDay.getUTCMonth() + 1) + "/" + previousDay.getUTCDate() + "."; if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> " + logText); } @@ -384,7 +383,7 @@ let previousFile; let currentFile; - if (currentDay.valueOf() > contextVariables.dateBeginOfMarket.valueOf()) { + if (bot.processDatetime.valueOf() > contextVariables.dateBeginOfMarket.valueOf()) { getPreviousFile(); } else { previousFile = []; @@ -466,7 +465,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> Entering function."); } - let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let dateForPath = bot.processDatetime.getUTCFullYear() + '/' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.processDatetime.getUTCDate(), 2); let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; let fileName = market.assetA + '_' + market.assetB + ".json"; @@ -560,7 +559,7 @@ dataFiles, timePeriod, outputPeriodLabel, - currentDay, + bot.processDatetime, contextVariables.dateBeginOfMarket, contextVariables.dateEndOfMarket, interExecutionMemoryArray[n], @@ -629,7 +628,7 @@ return; } - writeStatusReport(currentDay, advanceTime); + writeStatusReport(bot.processDatetime, advanceTime); } catch (err) { logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = " + err.message); @@ -664,7 +663,7 @@ let folderName = bot.products[productIndex].codeName; - writeDataRange(contextVariables.dateBeginOfMarket, currentDay, folderName, controlLoop); + writeDataRange(contextVariables.dateBeginOfMarket, bot.processDatetime, folderName, controlLoop); } function controlLoop() { From e28f4abab8e7cd4081b0cfa87b51bfbddaaecf8e Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 29 Mar 2019 10:03:30 +0100 Subject: [PATCH 61/73] correction on logging of process datetime --- MultiPeriodDaily.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 6fe54df00..7807f7126 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -304,13 +304,13 @@ try { - logger.newInternalLoop(bot.codeName, bot.process); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> Entering function."); } bot.processDatetime = new Date(bot.processDatetime.valueOf() + ONE_DAY_IN_MILISECONDS); previousDay = new Date(bot.processDatetime.valueOf() - ONE_DAY_IN_MILISECONDS); + logger.newInternalLoop(bot.codeName, bot.process); + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> bot.processDatetime = " + bot.processDatetime); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> advanceTime -> previousDay = " + previousDay); } From a8da9b4e46a504113918bf54ead9cfebd2f55815 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 29 Mar 2019 21:59:56 +0100 Subject: [PATCH 62/73] Using MQService Library --- package-lock.json | 335 +++++++++++++++++++++++----------------------- package.json | 1 + 2 files changed, 171 insertions(+), 165 deletions(-) diff --git a/package-lock.json b/package-lock.json index 72604727b..7ba6dd109 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@superalgos/mqservice": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@superalgos/mqservice/-/mqservice-0.0.3.tgz", + "integrity": "sha512-7beJRbcylkzND1MnWdEIrmtrqOyFvRsS131JKk6Xap5fFpS8kPpXKHEY50K97qwBnbTJZSJyNvSjafJPRUNjqQ==" + }, "@types/async": { "version": "2.0.49", "resolved": "https://registry.npmjs.org/@types/async/-/async-2.0.49.tgz", @@ -20,10 +25,10 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "apollo-boost": { @@ -31,14 +36,14 @@ "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.1.16.tgz", "integrity": "sha512-ppnQr90n2cn0ZMveEbqxW6NxmskIpThiLziLlRpRLy4keoAICg1NZecxJQmeaBLMtyhf5UholAjpS2SLmEJeHg==", "requires": { - "apollo-cache": "^1.1.17", - "apollo-cache-inmemory": "^1.2.10", - "apollo-client": "^2.4.2", - "apollo-link": "^1.0.6", - "apollo-link-error": "^1.0.3", - "apollo-link-http": "^1.3.1", - "apollo-link-state": "^0.4.0", - "graphql-tag": "^2.4.2" + "apollo-cache": "1.1.17", + "apollo-cache-inmemory": "1.2.10", + "apollo-client": "2.4.2", + "apollo-link": "1.2.3", + "apollo-link-error": "1.1.1", + "apollo-link-http": "1.5.5", + "apollo-link-state": "0.4.2", + "graphql-tag": "2.10.0" } }, "apollo-cache": { @@ -46,7 +51,7 @@ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.17.tgz", "integrity": "sha512-7sp24n2HZO4vXgTaKNomLyIfGxG4gDdDkBB0jkRzRi7HhnKmfwhiF/RCiKNbgLdrPX151INdls0KwIVliD0dHQ==", "requires": { - "apollo-utilities": "^1.0.21" + "apollo-utilities": "1.0.21" } }, "apollo-cache-inmemory": { @@ -54,9 +59,9 @@ "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.2.10.tgz", "integrity": "sha512-eBusPFVtYIuo+PIfJdAwUCQ4cs7AJ4mB7sTdXxNQCXToYw8mzE6EfHnV37kdVfBXSaa82BzE2rb/YUq/duuamw==", "requires": { - "apollo-cache": "^1.1.17", - "apollo-utilities": "^1.0.21", - "graphql-anywhere": "^4.1.19" + "apollo-cache": "1.1.17", + "apollo-utilities": "1.0.21", + "graphql-anywhere": "4.1.19" } }, "apollo-client": { @@ -65,13 +70,13 @@ "integrity": "sha512-g1z23umaVSoKLj9xNl0aAnk2KBF4JeBi7MeKFc9CGTixH7TkqeQUQtxcjrC7j2h4KmDbuhOAHOFUGf8YshN+ag==", "requires": { "@types/async": "2.0.49", - "@types/zen-observable": "^0.8.0", + "@types/zen-observable": "0.8.0", "apollo-cache": "1.1.17", - "apollo-link": "^1.0.0", - "apollo-link-dedup": "^1.0.0", + "apollo-link": "1.2.3", + "apollo-link-dedup": "1.0.10", "apollo-utilities": "1.0.21", - "symbol-observable": "^1.0.2", - "zen-observable": "^0.8.0" + "symbol-observable": "1.2.0", + "zen-observable": "0.8.9" } }, "apollo-link": { @@ -79,8 +84,8 @@ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.3.tgz", "integrity": "sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==", "requires": { - "apollo-utilities": "^1.0.0", - "zen-observable-ts": "^0.8.10" + "apollo-utilities": "1.0.21", + "zen-observable-ts": "0.8.10" } }, "apollo-link-dedup": { @@ -88,7 +93,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz", "integrity": "sha512-tpUI9lMZsidxdNygSY1FxflXEkUZnvKRkMUsXXuQUNoSLeNtEvUX7QtKRAl4k9ubLl8JKKc9X3L3onAFeGTK8w==", "requires": { - "apollo-link": "^1.2.3" + "apollo-link": "1.2.3" } }, "apollo-link-error": { @@ -96,7 +101,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-error/-/apollo-link-error-1.1.1.tgz", "integrity": "sha512-/yPcaQWcBdB94vpJ4FsiCJt1dAGGRm+6Tsj3wKwP+72taBH+UsGRQQZk7U/1cpZwl1yqhHZn+ZNhVOebpPcIlA==", "requires": { - "apollo-link": "^1.2.3" + "apollo-link": "1.2.3" } }, "apollo-link-http": { @@ -104,8 +109,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.5.tgz", "integrity": "sha512-C5N6N/mRwmepvtzO27dgMEU3MMtRKSqcljBkYNZmWwH11BxkUQ5imBLPM3V4QJXNE7NFuAQAB5PeUd4ligivTQ==", "requires": { - "apollo-link": "^1.2.3", - "apollo-link-http-common": "^0.2.5" + "apollo-link": "1.2.3", + "apollo-link-http-common": "0.2.5" } }, "apollo-link-http-common": { @@ -113,7 +118,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.5.tgz", "integrity": "sha512-6FV1wr5AqAyJ64Em1dq5hhGgiyxZE383VJQmhIoDVc3MyNcFL92TkhxREOs4rnH2a9X2iJMko7nodHSGLC6d8w==", "requires": { - "apollo-link": "^1.2.3" + "apollo-link": "1.2.3" } }, "apollo-link-state": { @@ -121,8 +126,8 @@ "resolved": "https://registry.npmjs.org/apollo-link-state/-/apollo-link-state-0.4.2.tgz", "integrity": "sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw==", "requires": { - "apollo-utilities": "^1.0.8", - "graphql-anywhere": "^4.1.0-alpha.0" + "apollo-utilities": "1.0.21", + "graphql-anywhere": "4.1.19" } }, "apollo-utilities": { @@ -130,8 +135,8 @@ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.21.tgz", "integrity": "sha512-ZcxELlEl+sDCYBgEMdNXJAsZtRVm8wk4HIA58bMsqYfd1DSAJQEtZ93F0GZgYNAGy3QyaoBeZtbb0/01++G8JQ==", "requires": { - "fast-json-stable-stringify": "^2.0.0", - "fclone": "^1.0.11" + "fast-json-stable-stringify": "2.0.0", + "fclone": "1.0.11" } }, "asn1": { @@ -139,7 +144,7 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert": { @@ -160,7 +165,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { - "lodash": "^4.17.10" + "lodash": "4.17.11" } }, "asynckit": { @@ -183,8 +188,8 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { - "follow-redirects": "^1.3.0", - "is-buffer": "^1.1.5" + "follow-redirects": "1.6.1", + "is-buffer": "1.1.6" } }, "azure-storage": { @@ -192,17 +197,17 @@ "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.2.tgz", "integrity": "sha512-pOyGPya9+NDpAfm5YcFfklo57HfjDbYLXxs4lomPwvRxmb0Di/A+a+RkUmEFzaQ8S13CqxK40bRRB0sjj2ZQxA==", "requires": { - "browserify-mime": "~1.2.9", - "extend": "^3.0.2", + "browserify-mime": "1.2.9", + "extend": "3.0.2", "json-edm-parser": "0.1.2", "md5.js": "1.3.4", - "readable-stream": "~2.0.0", - "request": "^2.86.0", - "underscore": "~1.8.3", - "uuid": "^3.0.0", - "validator": "~9.4.1", + "readable-stream": "2.0.6", + "request": "2.88.0", + "underscore": "1.8.3", + "uuid": "3.3.2", + "validator": "9.4.1", "xml2js": "0.2.8", - "xmlbuilder": "^9.0.7" + "xmlbuilder": "9.0.7" }, "dependencies": { "underscore": { @@ -218,7 +223,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "browserify-mime": { @@ -246,8 +251,8 @@ "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-convert": "1.9.3", + "color-string": "1.5.3" } }, "color-convert": { @@ -268,8 +273,8 @@ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" } }, "colornames": { @@ -287,8 +292,8 @@ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" + "color": "3.0.0", + "text-hex": "1.0.0" } }, "combined-stream": { @@ -296,7 +301,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "core-util-is": { @@ -309,7 +314,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "debug": { @@ -330,9 +335,9 @@ "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" + "colorspace": "1.1.1", + "enabled": "1.0.2", + "kuler": "1.0.1" } }, "dotenv": { @@ -346,8 +351,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "ecdsa-sig-formatter": { @@ -355,7 +360,7 @@ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "enabled": { @@ -363,7 +368,7 @@ "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", "requires": { - "env-variable": "0.0.x" + "env-variable": "0.0.5" } }, "env-variable": { @@ -411,7 +416,7 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "requires": { - "debug": "=3.1.0" + "debug": "3.1.0" } }, "forever-agent": { @@ -424,9 +429,9 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "^0.4.0", + "asynckit": "0.4.0", "combined-stream": "1.0.6", - "mime-types": "^2.1.12" + "mime-types": "2.1.20" }, "dependencies": { "combined-stream": { @@ -434,7 +439,7 @@ "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } } } @@ -444,7 +449,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "graphql": { @@ -452,7 +457,7 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", "requires": { - "iterall": "^1.2.2" + "iterall": "1.2.2" } }, "graphql-anywhere": { @@ -460,7 +465,7 @@ "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-4.1.19.tgz", "integrity": "sha512-mQlvbECzYPBcgBC9JsdM4v+DSvNmcIP+8Vwr+ij3gktbaLSE0Iza30mztuz40Jlf7ooMs+0emBZucNjLzqz7tA==", "requires": { - "apollo-utilities": "^1.0.21" + "apollo-utilities": "1.0.21" } }, "graphql-tag": { @@ -478,8 +483,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "hash-base": { @@ -487,8 +492,8 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "2.0.1", + "safe-buffer": "5.1.2" } }, "http-signature": { @@ -496,9 +501,9 @@ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" } }, "inherits": { @@ -552,7 +557,7 @@ "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", "requires": { - "jsonparse": "~1.2.0" + "jsonparse": "1.2.0" } }, "json-schema": { @@ -580,15 +585,15 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", "requires": { - "jws": "^3.1.5", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1" + "jws": "3.2.1", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.1.1" }, "dependencies": { "ms": { @@ -616,7 +621,7 @@ "requires": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.10", - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "jws": { @@ -624,8 +629,8 @@ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", "requires": { - "jwa": "^1.2.0", - "safe-buffer": "^5.0.1" + "jwa": "1.2.0", + "safe-buffer": "5.1.2" } }, "kuler": { @@ -633,7 +638,7 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", "requires": { - "colornames": "^1.1.1" + "colornames": "1.1.1" } }, "lodash": { @@ -681,11 +686,11 @@ "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.2.0" + "colors": "1.3.3", + "fast-safe-stringify": "2.0.6", + "fecha": "2.3.3", + "ms": "2.1.1", + "triple-beam": "1.3.0" }, "dependencies": { "ms": { @@ -700,8 +705,8 @@ "resolved": "http://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "3.0.4", + "inherits": "2.0.1" } }, "mime-db": { @@ -714,7 +719,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", "requires": { - "mime-db": "~1.36.0" + "mime-db": "1.36.0" } }, "ms": { @@ -777,12 +782,12 @@ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" } }, "request": { @@ -790,26 +795,26 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" } }, "retry": { @@ -837,7 +842,7 @@ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { - "is-arrayish": "^0.3.1" + "is-arrayish": "0.3.2" } }, "sshpk": { @@ -845,15 +850,15 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "stack-trace": { @@ -881,8 +886,8 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "1.1.29", + "punycode": "1.4.1" } }, "triple-beam": { @@ -895,7 +900,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -937,9 +942,9 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "winston": { @@ -947,15 +952,15 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", "requires": { - "async": "^2.6.0", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^1.9.1", + "async": "2.6.1", + "diagnostics": "1.1.1", + "is-stream": "1.1.0", + "logform": "1.10.0", "one-time": "0.0.4", - "readable-stream": "^2.3.6", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.2.0" + "readable-stream": "2.3.6", + "stack-trace": "0.0.10", + "triple-beam": "1.3.0", + "winston-transport": "4.3.0" }, "dependencies": { "inherits": { @@ -973,13 +978,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -987,7 +992,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -997,8 +1002,8 @@ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", "requires": { - "readable-stream": "^2.3.6", - "triple-beam": "^1.2.0" + "readable-stream": "2.3.6", + "triple-beam": "1.3.0" }, "dependencies": { "inherits": { @@ -1016,13 +1021,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -1030,7 +1035,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } } } @@ -1040,7 +1045,7 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", "requires": { - "sax": "0.5.x" + "sax": "0.5.8" } }, "xmlbuilder": { @@ -1058,7 +1063,7 @@ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz", "integrity": "sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==", "requires": { - "zen-observable": "^0.8.0" + "zen-observable": "0.8.9" } } } diff --git a/package.json b/package.json index 90a19c944..df4c6f8ad 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "author": "Luis-Fernando-Molina", "license": "ISC", "dependencies": { + "@superalgos/mqservice": "0.0.3", "apollo-boost": "^0.1.16", "assert": "^1.4.1", "axios": "^0.18.0", From add75b5341603809892b72920a5ce71796e7bf5b Mon Sep 17 00:00:00 2001 From: Matias Date: Sat, 30 Mar 2019 11:16:45 +0100 Subject: [PATCH 63/73] New version mqservice --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df4c6f8ad..4e4e3afd8 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "author": "Luis-Fernando-Molina", "license": "ISC", "dependencies": { - "@superalgos/mqservice": "0.0.3", + "@superalgos/mqservice": "0.0.9", "apollo-boost": "^0.1.16", "assert": "^1.4.1", "axios": "^0.18.0", From 92a9479ce9f9660defa4e743404d4ab548112023 Mon Sep 17 00:00:00 2001 From: Matias Date: Sun, 31 Mar 2019 23:04:10 +0200 Subject: [PATCH 64/73] Adding basic coss exchange integration --- Exchange/ExchangeAPI.js | 14 +- Exchange/wrappers/coss.js | 340 ++++++++++++++++++++++++++ Exchange/wrappers/cossClient.js | 178 ++++++++++++++ Exchange/wrappers/cossProperties.json | 23 ++ ExtractionBotProcessMainLoop.js | 18 +- TradingBotProcessMainLoop.js | 6 +- 6 files changed, 563 insertions(+), 16 deletions(-) create mode 100644 Exchange/wrappers/coss.js create mode 100644 Exchange/wrappers/cossClient.js create mode 100644 Exchange/wrappers/cossProperties.json diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js index 1f29542b4..d95e8c2a1 100644 --- a/Exchange/ExchangeAPI.js +++ b/Exchange/ExchangeAPI.js @@ -1,4 +1,4 @@ -exports.newExchangeAPI = function newExchangeAPI(logger, authToken) { +exports.newExchangeAPI = function newExchangeAPI(logger, exchangeName) { /* @@ -31,7 +31,13 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - let botExchange = 'Poloniex'; + let botExchange + if (exchangeName === undefined) { + botExchange = 'Poloniex'; // Default Value + } else { + botExchange = exchangeName; + } + let exchange = botExchange.toLowerCase() + 'Client.js'; let api = require('./wrappers/' + exchange); @@ -45,7 +51,7 @@ let auth = require('../utils/auth') let authTokenCloud = await auth.authenticate() accessToken = 'Bearer ' + authTokenCloud - } + } let keyVaultAPI = createKeyVaultAPIClient(accessToken, keyId, cloneId) apiClient = api.newAPIClient(keyVaultAPI, logger); @@ -60,7 +66,7 @@ function createKeyVaultAPIClient(accessToken, keyId, cloneId) { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Entering function."); } - + const keyVaultAPI = {} keyVaultAPI.signTransaction = function (transaction, next) { axios({ diff --git a/Exchange/wrappers/coss.js b/Exchange/wrappers/coss.js new file mode 100644 index 000000000..346655af5 --- /dev/null +++ b/Exchange/wrappers/coss.js @@ -0,0 +1,340 @@ +// Source: https://github.com/coss-exchange/trading-api-wrapper-node-js/blob/master/index.js +// Documentation: https://api.coss.io/v1/spec + +const request = require('superagent'); +const querystring = require('querystring'); +const HttpMethod = { POST: 1, GET: 2, DELETE: 3 }; +const util = require('util'); + +const HOST_URL = "https://trade.coss.io/c/api/v1"; +const HOST_URL2 = "https://engine.coss.io/api/v1"; +const EXCHANGE_HOST = "https://exchange.coss.io/api"; + + +//WRAPPER STARTS HERE (Commenting out stuff that coss wrote which should be part of bot.js (the actual trading bot) rather than index.js (the wrapper core functionality)) +let Coss = (keyVaultAPI) => { + + //HTTPS Private Request + async function transmit_encrypted_request(method, url, payload) { + var payload_json_str = method == HttpMethod.GET ? querystring.stringify(payload) : JSON.stringify(payload) + var sign = await transmit_payload_signature_get(payload_json_str) + var req_headers = transmit_signed_header_get(sign) + + console.log(`sending ${payload_json_str} to ${url}`) + + if (method == HttpMethod.POST) { + let response = await request.post(url).set(req_headers).send(payload_json_str) + return (response.body); + + } else if (method == HttpMethod.DELETE) { + let response = await request.delete(url).set(req_headers).send(payload_json_str) + return (response.body); + + } else if (method == HttpMethod.GET) { + let response = await request.get(url).set(req_headers).query(payload_json_str) + return (response.body); + } + + } + + function transmit_signed_header_get(sign) { + var req_headers = { + 'Content-Type': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Authorization': sign.Key, + 'Signature': sign.Sign, + } + return req_headers + } + + //AUTHBUILDER + async function transmit_payload_signature_get(payload_json_str) { + const signTransaction = util.promisify(keyVaultAPI.signTransaction) + return await signTransaction(payload_json_str) + } + + //HTTPS Public Request + async function publicRequest(url) { + let response = await request.get(url) + return response.body; + } + + + return { + //PLACE LIMIT ORDER + placeLimitOrder: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("placeLimitOrder(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("placeLimitOrder(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } else if (!params.Side) { + return Promise.reject("placeLimitOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); + } else if (params.Side && params.Side !== 'Buy' && params.Side !== 'Sell') { + return Promise.reject("placeLimitOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); + } else if (!params.Price || !params.Amount) { + return Promise.reject("placeLimitOrder(), You must supply a valid Price and Amount, e.g. Price: '0.00000034' or Amount: '123.00000000'!"); + //} else if (typeof params.Price !== 'number' || typeof params.Amount !== 'number') { + //return Promise.reject("placeLimitOrder(), You must supply a valid Price and Amount as a number, e.g. Price: '0.00000034' or Amount: '123.00000000'!"); + } + var now = new Date().getTime() + var query_params = { + 'order_symbol': params.Symbol, + 'order_price': params.Price.toString(), + 'order_side': params.Side, + 'order_size': params.Amount.toString(), + 'type': 'limit', + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/add"; + return transmit_encrypted_request(HttpMethod.POST, url, query_params) + }, + + //PLACE MARKET ORDER + placeMarketOrder: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("placeMarketOrder(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("placeMarketOrder(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } else if (!params.Side) { + return Promise.reject("placeMarketOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); + } else if (params.Side && params.Side !== 'Buy' && params.Side !== 'Sell') { + return Promise.reject("placeMarketOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); + } else if (!params.Amount) { + return Promise.reject("placeMarketOrder(), You must supply a valid Amount, e.g. Amount: '123.00000000'!"); + } else if (typeof params.Amount !== 'number') { + return Promise.reject("placeMarketOrder(), You must supply a valid Amount as a number, e.g. Amount: '123.00000000'!"); + } + var now = new Date().getTime() + var query_params = { + 'order_symbol': params.Symbol, + 'order_side': params.Side, + 'order_size': params.Amount.toString(), + 'type': 'market', + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/add"; + return transmit_encrypted_request(HttpMethod.POST, url, query_params) + }, + + //Get Account Balances + getAccountBalances: async (params = {}) => { + var now = new Date().getTime() + var query_params = { + 'recvWindow': 5000, + 'timestamp': now + } + let url = HOST_URL + "/account/balances"; + return transmit_encrypted_request(HttpMethod.GET, url, query_params) + }, + + //Get Account Details + getAccountDetails: async (params = {}) => { + var now = new Date().getTime() + var query_params = { + 'recvWindow': 5000, + 'timestamp': now + } + let url = HOST_URL + "/account/details"; + return transmit_encrypted_request(HttpMethod.GET, url, query_params) + }, + + //CANCEL ORDER BY ID # + cancelOrder: async (params = {}) => { + if (!params.ID) { + return Promise.reject("cancelOrder(), You must supply a valid order_ID to cancel, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); + } else if (params.ID && typeof params.ID !== 'string') { + return Promise.reject("cancelOrder(), You must supply a valid order_ID to cancel as a string, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); + } else if (!params.Symbol) { + return Promise.reject("cancelOrder(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("cancelOrder(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + + var now = new Date().getTime() + var query_params = { + 'order_id': params.ID, + 'order_symbol': params.Symbol, + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/cancel"; + return transmit_encrypted_request(HttpMethod.DELETE, url, query_params) + }, + + //GET ORDER DETAILS + getOrderDetails: async (params = {}) => { + if (!params.ID) { + return Promise.reject("getOrderDetails(), You must supply a valid order_ID to cancel, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); + } else if (params.ID && typeof params.ID !== 'string') { + return Promise.reject("getOrderDetails(), You must supply a valid order_ID to cancel as a string, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); + } + + var now = new Date().getTime() + var query_params = { + 'order_id': params.ID, + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/details"; + return transmit_encrypted_request(HttpMethod.POST, url, query_params) + }, + + //GET OPEN ORDERS + getOpenOrders: async (params = {}) => { + if (!params.Limit) { + return Promise.reject("getOpenOrders(), You must supply a valid Limit for your open orders, e.g. '10'!"); + } else if (params.Limit && typeof params.Limit !== 'number') { + return Promise.reject("getOpenOrders(), You must supply a valid Limit as a number for your open orders, e.g. '10'!"); + } else if (!params.Symbol) { + return Promise.reject("getOpenOrders(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getOpenOrders(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + + var now = new Date().getTime() + var query_params = { + 'limit': params.Limit.toString(), + 'page': 0, + 'symbol': params.Symbol, + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/list/open"; + return transmit_encrypted_request(HttpMethod.POST, url, query_params) + }, + + //GET COMPLETED ORDERS + getCompletedOrders: async (params = {}) => { + if (!params.Limit) { + return Promise.reject("getCompletedOrders(), You must supply a valid Limit for your open orders, e.g. '10'!"); + } else if (params.Limit && typeof params.Limit !== 'number') { + return Promise.reject("getCompletedOrders(), You must supply a valid Limit as a number for your open orders, e.g. '10'!"); + } else if (!params.Symbol) { + return Promise.reject("getCompletedOrders(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getCompletedOrders(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + + var now = new Date().getTime() + var query_params = { + 'limit': params.Limit.toString(), + 'page': 0, + 'symbol': params.Symbol, + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/list/completed"; + return transmit_encrypted_request(HttpMethod.POST, url, query_params) + }, + + //GET ALL USER ORDERS + getAllOrders: async (params = {}) => { + if (!params.Limit) { + return Promise.reject("getAllOrders(), You must supply a valid Limit for your open orders, e.g. '10'!"); + } else if (params.Limit && typeof params.Limit !== 'number') { + return Promise.reject("getAllOrders(), You must supply a valid Limit as a number for your open orders, e.g. '10'!"); + } else if (!params.Symbol) { + return Promise.reject("getAllOrders(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getAllOrders(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } else if (!params.ID) { + return Promise.reject("getAllOrders(), You must supply a valid account ID"); + } else if (params.ID && typeof params.ID !== 'string') { + return Promise.reject("getAllOrders(), You must supply a valid account ID as a string"); + } + + var now = new Date().getTime() + var query_params = { + 'symbol': params.Symbol, + 'from_id': params.ACCT_ID, + 'limit': params.Limit, + 'timestamp': now, + 'recvWindow': 5000 + } + let url = HOST_URL + "/order/list/all"; + return transmit_encrypted_request(HttpMethod.POST, url, query_params) + }, + + + //Public API Calls (don't need to be signed) + //get Market Price + getMarketPrice: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("getMarketPrice(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getMarketPrice(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + + let url = HOST_URL + "/market-price/" + '?symbol=' + params.Symbol; + + + return publicRequest(url); + }, + + //get Market Price + getPairDepth: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("getPairDepth(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getPairDepth(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + console.log(HOST_URL2 + "/dp" + '?symbol=' + params.Symbol); + let url = HOST_URL2 + "/dp" + '?symbol=' + params.Symbol; + + + return publicRequest(url); + }, + + //get Market Price + getMarketSides: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("getMarketSides(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getMarketSides(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + console.log(HOST_URL2 + "/dp" + '?symbol=' + params.Symbol); + let url = HOST_URL2 + "/dp" + '?symbol=' + params.Symbol; + + let pairDepth = await publicRequest(url); + let marketSides = [[pairDepth.bids[0][0], pairDepth.bids[0][1]], [pairDepth.asks[0][0], pairDepth.asks[0][1]]]; + + return (marketSides) + }, + + //get Exchange Info + getExchangeInfo: async () => { + console.log(HOST_URL + "/exchange-info"); + let url = HOST_URL + "/exchange-info"; + + return publicRequest(url); + }, + + //get Market Summary (NOT WORKING ATM) + getMarketSummary: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("getMarketSummary(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getMarketSummary(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + console.log(EXCHANGE_HOST + "/getmarketsummaries/" + '?symbol=' + params.Symbol); + let url = EXCHANGE_HOST + "/getmarketsummaries/" + '?symbol=' + params.Symbol; + + return publicRequest(url); + }, + + getTradeHistory: async (params = {}) => { + if (!params.Symbol) { + return Promise.reject("getTradeHistory(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); + } else if (params.Symbol && typeof params.Symbol !== 'string') { + return Promise.reject("getTradeHistory(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); + } + console.log(HOST_URL2 + "/ht" + '?symbol=' + params.Symbol); + let url = HOST_URL2 + "/ht" + '?symbol=' + params.Symbol; + + return publicRequest(url); + } + } +}; +module.exports = exports = Coss; diff --git a/Exchange/wrappers/cossClient.js b/Exchange/wrappers/cossClient.js new file mode 100644 index 000000000..3845232a6 --- /dev/null +++ b/Exchange/wrappers/cossClient.js @@ -0,0 +1,178 @@ +exports.newAPIClient = function newAPIClient(keyVaultAPI, logger) { + const Coss = require("./coss"); + const exchangeProperties = require('./cossProperties.json'); + let API = Coss(keyVaultAPI); + + let thisObject = { + getTicker: getTicker, + getOpenPositions: getOpenPositions, + getExecutedTrades: getExecutedTrades, + buy: buy, + sell: sell, + movePosition: movePosition, + getPublicTradeHistory: getPublicTradeHistory, + getExchangeProperties: getExchangeProperties, + isValidLot: isValidLot + }; + + return thisObject; + + function joinCurrencies(currencyA, currencyB) { + // If only one arg, then return the first + if (typeof currencyB !== 'string') { + return currencyA; + } + + return currencyA + '_' + currencyB; + } + + + /* + * Returns the properties for this exchange + */ + function getExchangeProperties() { + return exchangeProperties; + } + + /* + * Returns the price for a given pair of assets. + * The object returned is an array of trades: + * ticker = { + * bid, Number + * ask, Number + * last Number + * }; + */ + async function getTicker(pMarket, callBack) { + + let params = {} + params.Symbol = joinCurrencies(pMarket.assetB, pMarket.assetA) + try { + var response = await API.getPairDepth(params) + let ticker = { + bid: Number(response.bids[0][0]), + ask: Number(response.asks[0][0]), + last: Number((response.bids[0][0] + response.asks[0][0]) / 2) // TODO Pending review + }; + + callBack(global.DEFAULT_OK_RESPONSE.result, ticker) + } catch (error) { + callBack(global.DEFAULT_FAIL_RESPONSE.result) + } + } + + /* + * Returns the open positions ath the exchange for a given market and user account. + * The object returned is an array of positions: + * position = { + * id, + * type, + * rate, Number + * amountA, Number + * amountB, Number + * fee, (not required) Number + * datetime + * }; + */ + function getOpenPositions(pMarket, callBack) { + // Not implemented yet + callBack(global.DEFAULT_OK_RESPONSE) + } + + /* + * Returns the trades for a given order number. + * The object returned is an array of positions: + * position = { + * id, + * type, + * rate, Number + * amountA, Number + * amountB, Number + * fee, Number + * datetime + * }; + */ + function getExecutedTrades(pPositionId, callBack) { + // Not implemented yet + callBack(global.DEFAULT_OK_RESPONSE) + } + + /* + * Creates a new buy order. + * The orderNumber is returned. String + */ + function buy(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { + // Not implemented yet + callBack(global.DEFAULT_OK_RESPONSE) + } + + /* + * Creates a new sell order. + * The orderNumber is returned. String + */ + function sell(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { + // Not implemented yet + callBack(global.DEFAULT_OK_RESPONSE) + } + + /* + * Move an existing position to the new rate. + * The orderNumber is returned. String + */ + function movePosition(pPosition, pNewRate, pNewAmountB, callBack) { + // Not implemented yet + callBack(global.DEFAULT_OK_RESPONSE) + } + + /* + * Returns all the trade history from the Exchange since startTime to endTime orderd by tradeId. + * It's possible that the exchange doesn't support this method. + * The object returned is an array of trades: + * trade = { + * tradeID, String + * globalTradeID, String + * type, String + * rate, Number + * amountA, Number + * amountB, Number + * date Date + * }; + */ + async function getPublicTradeHistory(assetA, assetB, startTime, endTime, callBack) { + + let params = {} + params.Symbol = joinCurrencies(assetB, assetA) + try { + let trades = [] + var response = await API.getTradeHistory(params); + for (let i = 0; i < response.history.length; i++) { + let record = response.history[i] + let type + if (record.isBuyerMaker) { + type = "sell" + } else { + type = "buy" + } + + let trade = { + tradeID: record.id, + globalTradeID: record.id, + type: type, + rate: Number(record.price), + amount: Number(record.qty), + total: Number(record.price) * Number(record.qty), + date: new Date(record.time) + } + trades.push(trade); + } + + callBack(global.DEFAULT_OK_RESPONSE.result, trades); + } catch (error) { + callBack(global.DEFAULT_FAIL_RESPONSE.result); + } + } + + function isValidLot(price, amount) { + return amount * price >= 0.0001; + } +} diff --git a/Exchange/wrappers/cossProperties.json b/Exchange/wrappers/cossProperties.json new file mode 100644 index 000000000..310e7b119 --- /dev/null +++ b/Exchange/wrappers/cossProperties.json @@ -0,0 +1,23 @@ +{ + "currencies": [ + "BTC", + "USDT" + ], + "assets": [ + "BTC", + "USDT" + ], + "markets": [ + { + "pair": [ + "BTC", + "USDT" + ], + "maxDecimals": 5, + "minimalOrder": { + "amount": 0.0001, + "unit": "asset" + } + } + ] +} diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index 914d95a27..db8f5b7c7 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -13,7 +13,7 @@ const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. - let nextLoopTimeoutHandle; + let nextLoopTimeoutHandle; let checkLoopHealthHandle; let thisObject = { @@ -22,7 +22,7 @@ }; let processConfig; - let UI_COMMANDS; + let UI_COMMANDS; return thisObject; @@ -47,7 +47,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { let filePath; - + if (global.RUN_AS_TEAM) { filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud. } else { @@ -71,7 +71,7 @@ USER_BOT_MODULE = pMODULE; filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; - + cloudRequire.downloadCommons(cloudStorage, filePath, onCommonsDownloaded); function onCommonsDownloaded(err, pMODULE) { @@ -105,7 +105,7 @@ try { if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); } - bot.enableCheckLoopHealth = true; + bot.enableCheckLoopHealth = true; let fixedTimeLoopIntervalHandle; @@ -246,7 +246,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } - exchangeAPI = EXCHANGE_API.newExchangeAPI(logger); + exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, process.env.EXCHANGE_NAME); exchangeAPI.initialize(onInizialized); @@ -591,7 +591,7 @@ logger.persist(); return; } else { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.normalWaitTime / 1000) + " seconds."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.normalWaitTime / 1000) + " seconds."); } checkLoopHealthHandle = setTimeout(checkLoopHealth, processConfig.normalWaitTime * 5, bot.loopCounter); nextLoopTimeoutHandle = setTimeout(loop, processConfig.normalWaitTime); logger.persist(); @@ -686,7 +686,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { let filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. - + let fileName = "this.config.json"; cloudStorage.getTextFile(filePath, fileName, onFileReceived); @@ -695,7 +695,7 @@ if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - /* + /* If for any reason this config file cannot be read, we are not going to abort the loop for that. Instead we are going to assume that there are no instructions to stop and we will keep the show running. */ diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 14ad87b49..ac051348f 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -90,7 +90,7 @@ USER_BOT_MODULE = pMODULE; filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; - + cloudRequire.downloadCommons(cloudStorage, filePath, onCommonsDownloaded); function onCommonsDownloaded(err, pMODULE) { @@ -598,7 +598,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } - exchangeAPI = EXCHANGE_API.newExchangeAPI(logger); + exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, process.env.EXCHANGE_NAME); exchangeAPI.initialize(onInizialized); @@ -1113,7 +1113,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { let filePath = global.DEV_TEAM + "/" + "AACloud"; // DevTeams bots only are run at the cloud. - + let fileName = "this.config.json"; cloudStorage.getTextFile(filePath, fileName, onFileReceived); From 317a8fc44f1d5c91d3ebfbf22ebef80ed1e6e62e Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 1 Apr 2019 09:10:12 +0200 Subject: [PATCH 65/73] Standarizing Exchange Name from global variable filled from .env --- Exchange/wrappers/binanceClient.js | 2 +- ExtractionBotProcessMainLoop.js | 2 +- MultiPeriodDaily.js | 1 - MultiPeriodMarket.js | 3 - Project.njsproj | 1 + Run.js | 2 +- TradingBotProcessMainLoop.js | 2 +- package-lock.json | 108 +++++++++++++++++++++++++++-- package.json | 3 +- 9 files changed, 111 insertions(+), 13 deletions(-) diff --git a/Exchange/wrappers/binanceClient.js b/Exchange/wrappers/binanceClient.js index a46ca7d24..e9208e283 100644 --- a/Exchange/wrappers/binanceClient.js +++ b/Exchange/wrappers/binanceClient.js @@ -309,7 +309,7 @@ return (exchangeErr, exchangeResponse) => { let error; - /* This function analizes the different situations we might encounter trying to access Poloniex and returns appropiate standard errors. */ + /* This function analizes the different situations we might encounter trying to access Binance and returns appropiate standard errors. */ let stringExchangeErr = JSON.stringify(exchangeErr); let stringExchangeResponse = JSON.stringify(exchangeResponse); diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index db8f5b7c7..5aae506f1 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -246,7 +246,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } - exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, process.env.EXCHANGE_NAME); + exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, global.EXCHANGE_NAME); exchangeAPI.initialize(onInizialized); diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 7807f7126..4127b0c15 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -3,7 +3,6 @@ const FULL_LOG = true; const LOG_FILE_CONTENT = false; const MODULE_NAME = "Multi Period Daily"; - const EXCHANGE_NAME = "Poloniex"; const commons = COMMONS.newCommons(bot, logger, UTILITIES); const GMT_SECONDS = ':00.000 GMT+0000'; const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000; diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 20ade8176..9f8d7853f 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -2,11 +2,8 @@ const FULL_LOG = true; const LOG_FILE_CONTENT = false; - const MODULE_NAME = "Multi Period Market"; - const EXCHANGE_NAME = "Poloniex"; - const commons = COMMONS.newCommons(bot, logger, UTILITIES); thisObject = { diff --git a/Project.njsproj b/Project.njsproj index c9cb27126..c3667ef7d 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -33,6 +33,7 @@ Code + Code diff --git a/Run.js b/Run.js index 59cefc5fa..c83f6690e 100644 --- a/Run.js +++ b/Run.js @@ -7,7 +7,7 @@ global.AT_BREAKPOINT = false; // This is used only when running at the browser. global.RUN_AS_TEAM = false; /* Default parameters can be changed by the execution configuration */ -global.EXCHANGE_NAME = "Poloniex"; +global.EXCHANGE_NAME = process.env.EXCHANGE_NAME; global.MARKET = { assetA: "USDT", assetB: "BTC" diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index ac051348f..610635efb 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -598,7 +598,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } - exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, process.env.EXCHANGE_NAME); + exchangeAPI = EXCHANGE_API.newExchangeAPI(logger, global.EXCHANGE_NAME); exchangeAPI.initialize(onInizialized); diff --git a/package-lock.json b/package-lock.json index 7ba6dd109..e8e2796f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "AACloud", + "name": "CloneExecutor", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@superalgos/mqservice": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@superalgos/mqservice/-/mqservice-0.0.3.tgz", - "integrity": "sha512-7beJRbcylkzND1MnWdEIrmtrqOyFvRsS131JKk6Xap5fFpS8kPpXKHEY50K97qwBnbTJZSJyNvSjafJPRUNjqQ==" + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@superalgos/mqservice/-/mqservice-0.0.9.tgz", + "integrity": "sha512-YH4BrDAE1+WmxBLu2JeVXzp/QiZwaKLLe6M+bh6ErliNGvGSOoB36/P5Vgmw6MDU81y6OU+hn5LqoRzESBW/CQ==" }, "@types/async": { "version": "2.0.49", @@ -304,6 +304,16 @@ "delayed-stream": "1.0.0" } }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -444,6 +454,11 @@ } } }, + "formidable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -709,6 +724,16 @@ "inherits": "2.0.1" } }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==" + }, "mime-db": { "version": "1.36.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", @@ -837,6 +862,11 @@ "resolved": "http://registry.npmjs.org/sax/-/sax-0.5.8.tgz", "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" }, + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==" + }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -871,6 +901,76 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "superagent": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.0.2.tgz", + "integrity": "sha512-CqeqvwByDJuLwhcO6NOSuPatyQOIZX/TlvD5GJnXg5tzBTth2xQGZGdAZdo/kX+BtzvwJFX2IGGczTZgEIT7Wg==", + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.2", + "debug": "4.1.1", + "form-data": "2.3.3", + "formidable": "1.2.1", + "methods": "1.1.2", + "mime": "2.4.0", + "qs": "6.7.0", + "readable-stream": "3.2.0", + "semver": "6.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "2.1.1" + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.20" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "requires": { + "inherits": "2.0.3", + "string_decoder": "1.2.0", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", diff --git a/package.json b/package.json index 4e4e3afd8..16b2e2cd9 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "AACloud", + "name": "CloneExecutor", "version": "1.0.0", "description": "", "main": "Run.js", @@ -22,6 +22,7 @@ "nonce": "^1.0.4", "querystring": "^0.2.0", "retry": "^0.12.0", + "superagent": "^5.0.2", "underscore": "^1.9.1", "winston": "^3.1.0" } From 1fff3e009536576589882ebedc8b8c2c666ae1b8 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 1 Apr 2019 09:46:48 +0200 Subject: [PATCH 66/73] Extraction for Sensor --- ExtractionBotProcessMainLoop.js | 4 ++-- Root.js | 8 ++++---- Run.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js index 5aae506f1..3b9b5b346 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/ExtractionBotProcessMainLoop.js @@ -2,7 +2,7 @@ const ROOT_DIR = './'; - const MODULE_NAME = "Extraction Bot Process Main Loop"; + const MODULE_NAME = "Sensor Bot Process Main Loop"; const FULL_LOG = true; let USER_BOT_MODULE; @@ -581,7 +581,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onContinue -> Entering function."); } - /* Extraction bots are going to be executed after a configured period of time after the last execution ended. This is to avoid overlapping executions. */ + /* Sensor bots are going to be executed after a configured period of time after the last execution ended. This is to avoid overlapping executions. */ switch (nextWaitTime) { case 'Normal': { diff --git a/Root.js b/Root.js index 86f99e4c1..9bc24e9b0 100644 --- a/Root.js +++ b/Root.js @@ -328,7 +328,7 @@ if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); } switch (botConfig.type) { - case 'Extraction': { + case 'Sensor': { runExtractionBot(newInstanceBotConfig, processConfig, padMonth, year); break; } @@ -367,7 +367,7 @@ }; switch (botConfig.type) { - case 'Extraction': { + case 'Sensor': { runExtractionBot(botConfig, processConfig, month, year); break; } @@ -397,7 +397,7 @@ } switch (botConfig.type) { - case 'Extraction': { + case 'Sensor': { runExtractionBot(botConfig, processConfig, month, year); break; } @@ -423,7 +423,7 @@ let year = (new Date()).getUTCFullYear(); switch (botConfig.type) { - case 'Extraction': { + case 'Sensor': { runExtractionBot(botConfig, processConfig, month, year); break; } diff --git a/Run.js b/Run.js index c83f6690e..8231644e9 100644 --- a/Run.js +++ b/Run.js @@ -72,7 +72,7 @@ function readExecutionConfiguration() { backtest: backtest, competition: competition } - } else if (process.env.TYPE === 'Indicator' || process.env.TYPE === 'Extraction') { + } else if (process.env.TYPE === 'Indicator' || process.env.TYPE === 'Sensor') { let allMonths = { run: "false", minYear: process.env.MIN_YEAR, From 4f22b92b27e8b219ee82f811d47ba2b17f1e85aa Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 1 Apr 2019 09:48:49 +0200 Subject: [PATCH 67/73] Extraction for Sensor part II --- Project.njsproj | 2 +- Root.js | 48 +++++++++---------- ...MainLoop.js => SensorBotProcessMainLoop.js | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) rename ExtractionBotProcessMainLoop.js => SensorBotProcessMainLoop.js (99%) diff --git a/Project.njsproj b/Project.njsproj index c3667ef7d..79b200eb5 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -67,7 +67,7 @@ Code - + Code diff --git a/Root.js b/Root.js index 9bc24e9b0..1d8ebc007 100644 --- a/Root.js +++ b/Root.js @@ -188,7 +188,7 @@ const TRADING_BOT_MAIN_LOOP_MODULE = require('./TradingBotProcessMainLoop'); const INDICATOR_BOT_MAIN_LOOP_MODULE = require('./IndicatorBotProcessMainLoop'); - const EXTRACTION_BOT_MAIN_LOOP_MODULE = require('./ExtractionBotProcessMainLoop'); + const EXTRACTION_BOT_MAIN_LOOP_MODULE = require('./SensorBotProcessMainLoop'); /* Loop through all the processes configured to be run by this Node.js Instance. */ @@ -329,7 +329,7 @@ switch (botConfig.type) { case 'Sensor': { - runExtractionBot(newInstanceBotConfig, processConfig, padMonth, year); + runSensorBot(newInstanceBotConfig, processConfig, padMonth, year); break; } case 'Indicator': { @@ -368,7 +368,7 @@ switch (botConfig.type) { case 'Sensor': { - runExtractionBot(botConfig, processConfig, month, year); + runSensorBot(botConfig, processConfig, month, year); break; } case 'Indicator': { @@ -398,7 +398,7 @@ switch (botConfig.type) { case 'Sensor': { - runExtractionBot(botConfig, processConfig, month, year); + runSensorBot(botConfig, processConfig, month, year); break; } case 'Indicator': { @@ -424,7 +424,7 @@ switch (botConfig.type) { case 'Sensor': { - runExtractionBot(botConfig, processConfig, month, year); + runSensorBot(botConfig, processConfig, month, year); break; } default: { @@ -532,7 +532,7 @@ } - function runExtractionBot(pBotConfig, pProcessConfig, pMonth, pYear) { + function runSensorBot(pBotConfig, pProcessConfig, pMonth, pYear) { try { @@ -542,11 +542,11 @@ logger = DEBUG_MODULE.newDebugLog(); logger.bot = pBotConfig; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> Entering function."); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> pMonth = " + pMonth); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> pYear = " + pYear); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> pMonth = " + pMonth); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> pYear = " + pYear); } - let extractionBotMainLoop = EXTRACTION_BOT_MAIN_LOOP_MODULE.newExtractionBotProcessMainLoop(pBotConfig, logger); + let extractionBotMainLoop = EXTRACTION_BOT_MAIN_LOOP_MODULE.newSensorBotProcessMainLoop(pBotConfig, logger); extractionBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); function onInitializeReady(err) { @@ -568,38 +568,38 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); logger.persist(); } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bye."); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bye."); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> whenStartFinishes -> Bot execution was aborted."); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution was aborted."); logger.persist(); } } } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> Bot will not be started. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> onInitializeReady -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> Bot will not be started. "); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = " + err.message); logger.persist(); } } } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runExtractionBot -> err = " + err.message); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> err = " + err.message); } } diff --git a/ExtractionBotProcessMainLoop.js b/SensorBotProcessMainLoop.js similarity index 99% rename from ExtractionBotProcessMainLoop.js rename to SensorBotProcessMainLoop.js index 3b9b5b346..7ce23337c 100644 --- a/ExtractionBotProcessMainLoop.js +++ b/SensorBotProcessMainLoop.js @@ -1,4 +1,4 @@ -exports.newExtractionBotProcessMainLoop = function newExtractionBotProcessMainLoop(bot, parentLogger) { +exports.newSensorBotProcessMainLoop = function newSensorBotProcessMainLoop(bot, parentLogger) { const ROOT_DIR = './'; From 16dace553632534d3bfd899b304b3d41caac6c1b Mon Sep 17 00:00:00 2001 From: Matias Date: Mon, 1 Apr 2019 10:29:42 +0200 Subject: [PATCH 68/73] Renaming to Clone Executor --- .gitignore | 2 ++ Exchange/wrappers/binanceClient.js | 15 +++++---------- Exchange/wrappers/poloniexClient.js | 5 ----- README.md | 2 +- package.json | 2 +- this.config.json | 4 ++-- 6 files changed, 11 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index f57a84efa..6f7be3c13 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ bin/* node_modules/* exchange/Auth0.js .env + +\.vscode/ diff --git a/Exchange/wrappers/binanceClient.js b/Exchange/wrappers/binanceClient.js index e9208e283..3b00f3469 100644 --- a/Exchange/wrappers/binanceClient.js +++ b/Exchange/wrappers/binanceClient.js @@ -1,10 +1,5 @@ exports.newAPIClient = function newAPIClient(pKey, pSecret, logger) { - /* - /* ATENTION: This Library is used both a the cloud (AACloud) and also at the AAWeb on the server side without any modifications. - /* There is a second version, stripped of all the inner functionality that runs at AAWeb browser side, which channels the requests to the server side one. - */ - const FULL_LOG = true; const LOG_FILE_CONTENT = true; const MODULE_NAME = "binanceClient"; @@ -100,7 +95,7 @@ }; const fetch = next => API.ticker24hr(market, analizeResponse(next)); - + retry(null, fetch, handle); } @@ -310,7 +305,7 @@ let error; /* This function analizes the different situations we might encounter trying to access Binance and returns appropiate standard errors. */ - + let stringExchangeErr = JSON.stringify(exchangeErr); let stringExchangeResponse = JSON.stringify(exchangeResponse); @@ -347,14 +342,14 @@ error.notFatal = true; } } - + return callBack(error, exchangeResponse); - + } catch (err) { logger.write(MODULE_NAME, "[ERROR] analizeResponse -> err.message = " + err.message); return callBack(global.DEFAULT_FAIL_RESPONSE, exchangeResponse); } } } - + } diff --git a/Exchange/wrappers/poloniexClient.js b/Exchange/wrappers/poloniexClient.js index 368ce01cc..34bc7a00f 100644 --- a/Exchange/wrappers/poloniexClient.js +++ b/Exchange/wrappers/poloniexClient.js @@ -1,10 +1,5 @@ exports.newAPIClient = function newAPIClient(keyVaultAPI, logger) { - /* - /* ATENTION: This Library is used both a the cloud (AACloud) and also at the AAWeb on the server side without any modifications. - /* There is a second version, stripped of all the inner functionality that runs at AAWeb browser side, which channels the requests to the server side one. - */ - const FULL_LOG = true; const LOG_FILE_CONTENT = false; const MODULE_NAME = "poloniexClient"; diff --git a/README.md b/README.md index 26c9cd48e..20138c17f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ If you are interested in coding your own crypto trading bots and eventually part ## Copyright and License Notice -© Copyright 2018 Advanced Algos. Please see the [AACloud License](/LICENSE) for information on how you can use this software. +© Copyright 2018 Advanced Algos. Please see the [Clone Executor License](/LICENSE) for information on how you can use this software. ## Disclaimer diff --git a/package.json b/package.json index 16b2e2cd9..2495394c9 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "CloneExecutor", + "name": "@superalgos/clone-executor", "version": "1.0.0", "description": "", "main": "Run.js", diff --git a/this.config.json b/this.config.json index 46ab69018..fa18a5c76 100644 --- a/this.config.json +++ b/this.config.json @@ -1,5 +1,5 @@ { - "codeName": "AACloud", + "codeName": "clone-executor", "version": { "major": 1, "minor": 1, @@ -17,4 +17,4 @@ "dataSet": "One-Min", "dataSetVersion": "dataSet.V1" } -} \ No newline at end of file +} From 3028a898a1d3a587581e88cfdf0e592b6c448e40 Mon Sep 17 00:00:00 2001 From: Matias Date: Mon, 1 Apr 2019 11:07:43 +0200 Subject: [PATCH 69/73] Sorting by trade ID desc --- Exchange/wrappers/cossClient.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Exchange/wrappers/cossClient.js b/Exchange/wrappers/cossClient.js index 3845232a6..012da975c 100644 --- a/Exchange/wrappers/cossClient.js +++ b/Exchange/wrappers/cossClient.js @@ -165,7 +165,7 @@ } trades.push(trade); } - + trades.sort((a, b) => b.tradeID - a.tradeID); callBack(global.DEFAULT_OK_RESPONSE.result, trades); } catch (error) { callBack(global.DEFAULT_FAIL_RESPONSE.result); From ecd38c1de88ea404c8b95a00c477f61a3a9328ac Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 3 Apr 2019 17:08:17 +0200 Subject: [PATCH 70/73] Err response didnt need the .result --- Exchange/wrappers/cossClient.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Exchange/wrappers/cossClient.js b/Exchange/wrappers/cossClient.js index 012da975c..36a068946 100644 --- a/Exchange/wrappers/cossClient.js +++ b/Exchange/wrappers/cossClient.js @@ -166,9 +166,9 @@ trades.push(trade); } trades.sort((a, b) => b.tradeID - a.tradeID); - callBack(global.DEFAULT_OK_RESPONSE.result, trades); + callBack(global.DEFAULT_OK_RESPONSE, trades); } catch (error) { - callBack(global.DEFAULT_FAIL_RESPONSE.result); + callBack(global.DEFAULT_FAIL_RESPONSE); } } From 8ae3ce59a5df42936993aab36823411806750b54 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 3 Apr 2019 18:37:57 +0200 Subject: [PATCH 71/73] Exchange API moved to ExchangeGateway.js repo --- Exchange/ExchangeAPI.js | 314 -- Exchange/exchangeUtils.js | 100 - Exchange/wrappers/beautifier.js | 183 - Exchange/wrappers/binance.js | 368 -- Exchange/wrappers/binanceClient.js | 355 -- Exchange/wrappers/binanceProperties.json | 4594 --------------------- Exchange/wrappers/coss.js | 340 -- Exchange/wrappers/cossClient.js | 178 - Exchange/wrappers/cossProperties.json | 23 - Exchange/wrappers/poloniex.js | 440 -- Exchange/wrappers/poloniexClient.js | 348 -- Exchange/wrappers/poloniexProperties.json | 3513 ---------------- Project.njsproj | 1 - SensorBotProcessMainLoop.js | 2 +- TradingBotProcessMainLoop.js | 2 +- package-lock.json | 1858 ++++++++- package.json | 3 +- 17 files changed, 1858 insertions(+), 10764 deletions(-) delete mode 100644 Exchange/ExchangeAPI.js delete mode 100644 Exchange/exchangeUtils.js delete mode 100644 Exchange/wrappers/beautifier.js delete mode 100644 Exchange/wrappers/binance.js delete mode 100644 Exchange/wrappers/binanceClient.js delete mode 100644 Exchange/wrappers/binanceProperties.json delete mode 100644 Exchange/wrappers/coss.js delete mode 100644 Exchange/wrappers/cossClient.js delete mode 100644 Exchange/wrappers/cossProperties.json delete mode 100644 Exchange/wrappers/poloniex.js delete mode 100644 Exchange/wrappers/poloniexClient.js delete mode 100644 Exchange/wrappers/poloniexProperties.json diff --git a/Exchange/ExchangeAPI.js b/Exchange/ExchangeAPI.js deleted file mode 100644 index d95e8c2a1..000000000 --- a/Exchange/ExchangeAPI.js +++ /dev/null @@ -1,314 +0,0 @@ -exports.newExchangeAPI = function newExchangeAPI(logger, exchangeName) { - - /* - - This module allows trading bots to connect to the exchange and do trading operations on it. So far it can only work with Poloniex. - - */ - const _ = require('lodash') - const isValidOrder = require('./exchangeUtils').isValidOrder - const axios = require('axios') - let MODULE_NAME = "Exchange API"; - - let thisObject = { - initialize: initialize, - getTicker: getTicker, - getOpenPositions: getOpenPositions, - getExecutedTrades: getExecutedTrades, - putPosition: putPosition, - movePosition: movePosition, - getPublicTradeHistory: getPublicTradeHistory, - getExchangeProperties: getExchangeProperties, - getMaxDecimalPositions: getMaxDecimalPositions - }; - - let apiClient; - - return thisObject; - - async function initialize(callBackFunction) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - - let botExchange - if (exchangeName === undefined) { - botExchange = 'Poloniex'; // Default Value - } else { - botExchange = exchangeName; - } - - let exchange = botExchange.toLowerCase() + 'Client.js'; - let api = require('./wrappers/' + exchange); - - let accessToken - let keyId - let cloneId - if (global.CURRENT_EXECUTION_AT === "Node") { - keyId = process.env.KEY_ID - cloneId = process.env.CLONE_ID - - let auth = require('../utils/auth') - let authTokenCloud = await auth.authenticate() - accessToken = 'Bearer ' + authTokenCloud - } - - let keyVaultAPI = createKeyVaultAPIClient(accessToken, keyId, cloneId) - apiClient = api.newAPIClient(keyVaultAPI, logger); - - callBackFunction(global.DEFAULT_OK_RESPONSE); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function createKeyVaultAPIClient(accessToken, keyId, cloneId) { - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Entering function."); } - - const keyVaultAPI = {} - keyVaultAPI.signTransaction = function (transaction, next) { - axios({ - url: global.GATEWAY_ENDPOINT, - method: 'post', - data: { - query: ` - mutation keyVault_SignTransaction($transaction: String!, $keyId: String, $cloneId: String){ - keyVault_SignTransaction(transaction: $transaction, keyId: $keyId, cloneId: $cloneId){ - key, - signature, - date - } - } - `, - variables: { - transaction: transaction, - keyId: keyId, - cloneId: cloneId - } - }, - headers: { - authorization: accessToken - } - - }).then(res => { - if (res.errors) { - next(undefined, 'Error from graphql: ' + res.errors); - } else { - let signature = { - Key: res.data.data.keyVault_SignTransaction.key, - Sign: res.data.data.keyVault_SignTransaction.signature - } - next(signature) - } - }).catch(error => { - next(undefined, 'Error signing the message on the key vault: ' + error.message); - }); - } - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Returning graphql client."); } - - return keyVaultAPI; - } - - /* - * Position Object = { - * id, String - * type, String - * rate, Number - * amountA, Number - * amountB, Number - * fee, Number - * datetime Date - * }; - */ - function truncDecimals(pFloatValue) { - let decimals = getMaxDecimalPositions(); - return parseFloat(parseFloat(pFloatValue).toFixed(decimals)); - } - - /* - * Return number of decimals for the current market - */ - function getMaxDecimalPositions() { - return getMarketConfig().maxDecimals; - } - - /* - * Return number of decimals for the current market - */ - function getMarketConfig() { - return _.find(getExchangeProperties().markets, (p) => { - return _.first(p.pair) === global.MARKET.assetA.toUpperCase() && - _.last(p.pair) === global.MARKET.assetB.toUpperCase(); - }); - } - - /* - * Return number of decimals for the current market - */ - function getExchangeProperties() { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getExchangeProperties -> Entering function."); } - - return apiClient.getExchangeProperties(); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] getExchangeProperties -> err = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - /* - * Returns the price for a given pair of assets. - * The object returned is an array of trades: - * ticker = { - * bid, Number - * ask, Number - * last Number - * }; - */ - function getTicker(pMarket, callBack) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getTicker -> Entering function."); } - - apiClient.getTicker(pMarket, callBack); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] getTicker -> err = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - /* - * Returns the open positions ath the exchange for a given market and user account. - * The object returned is an array of positions - * - */ - function getOpenPositions(pMarket, callBack) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getOpenPositions -> Entering function."); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getOpenPositions -> pMarket = " + JSON.stringify(pMarket)); } - - apiClient.getOpenPositions(pMarket, callBack); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] getOpenPositions -> Error = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - /* - * Returns the trades for a given order number. - * The object returned is an array of positions - */ - function getExecutedTrades(pPositionId, callBack) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getExecutedTrades -> Entering function."); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getExecutedTrades -> pPositionId = " + pPositionId); } - - apiClient.getExecutedTrades(pPositionId, callBack); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] getExecutedTrades -> Error = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - /* - * Creates a new buy or sell order. - * The orderNumber is returned. String - */ - function putPosition(pMarket, pType, pRate, pAmountA, pAmountB, callBack) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> Entering function."); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pMarket = " + JSON.stringify(pMarket)); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pType = " + pType); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pRate = " + truncDecimals(pRate)); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountA = " + truncDecimals(pAmountA)); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountB = " + truncDecimals(pAmountB)); } - - let check = isValidOrder({ - market: getMarketConfig(), - api: apiClient, - amount: truncDecimals(pAmountB), - price: truncDecimals(pRate) - }); - - if (check.valid) { - if (pType === "buy") { - apiClient.buy(pMarket.assetA, pMarket.assetB, truncDecimals(pRate), truncDecimals(pAmountB), callBack); - return; - } - - if (pType === "sell") { - apiClient.sell(pMarket.assetA, pMarket.assetB, truncDecimals(pRate), truncDecimals(pAmountB), callBack); - return; - } - - logger.write(MODULE_NAME, "[ERROR] putPosition -> pType must be either 'buy' or 'sell'."); - callBack(global.DEFAULT_FAIL_RESPONSE); - - } else { - logger.write(MODULE_NAME, "[ERROR] putPosition -> The order is invalid: " + check.reason); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] putPosition -> err = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - /* - * Move an existing position to the new rate. - * The new orderNumber is returned. - */ - function movePosition(pPosition, pNewRate, pNewAmountB, callBack) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> Entering function."); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> pPosition = " + JSON.stringify(pPosition)); } - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] movePosition -> pNewRate = " + truncDecimals(pNewRate)); } - - apiClient.movePosition(pPosition, truncDecimals(pNewRate), truncDecimals(pNewAmountB), callBack); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] movePosition -> err = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - /* - * Returns all the trade history from the Exchange since startTime to endTime orderd by tradeId. - * It's possible that the exchange doesn't support this method. - * The object returned is an array of trades: - * trade = { - * tradeID, String - * globalTradeID, String - * type, String - * rate, Number - * amountA, Number - * amountB, Number - * date Date - * }; - */ - function getPublicTradeHistory(assetA, assetB, startTime, endTime, callBack) { - try { - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getTradeHistory -> Entering function."); } - - apiClient.getPublicTradeHistory(assetA, assetB, startTime, endTime, callBack); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] getTradeHistory -> err = " + err.message); - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } -}; diff --git a/Exchange/exchangeUtils.js b/Exchange/exchangeUtils.js deleted file mode 100644 index 853d6d825..000000000 --- a/Exchange/exchangeUtils.js +++ /dev/null @@ -1,100 +0,0 @@ -// generic low level reusuable utils for interacting with exchanges. - -const retry = require('retry'); -const _ = require('lodash'); - -const retryInstance = (options, checkFn, callback) => { - if(!options) { - options = { - retries: 100, - factor: 1.2, - minTimeout: 1 * 1000, - maxTimeout: 4 * 1000 - }; - } - - let attempt = 0; - - const operation = retry.operation(options); - operation.attempt(function(currentAttempt) { - checkFn((err, result) => { - if (!err) { - return callback(global.DEFAULT_OK_RESPONSE, result); - } else { - if (err.result === global.CUSTOM_OK_RESPONSE.result) { - return callback(err, result); - } - } - - let maxAttempts = err.retry; - if(maxAttempts === true) - maxAttempts = 10; - - if(err.retry && attempt++ < maxAttempts) { - return operation.retry(err); - } - - if(err.notFatal) { - if(err.backoffDelay) { - return setTimeout(() => operation.retry(err), err.backoffDelay); - } - - return operation.retry(err); - } - - callback(err, result); - }); - }); -} - -const isValidOrder = ({api, market, amount, price}) => { - let reason = false; - - // Check amount - if(amount < market.minimalOrder.amount) { - reason = 'Amount is too small'; - } - - // Some exchanges have restrictions on prices - if( - _.isFunction(api.isValidPrice) && - !api.isValidPrice(price) - ) { - reason = 'Price is not valid'; - } - - if( - _.isFunction(api.isValidLot) && - !api.isValidLot(price, amount) - ) { - reason = 'Lot size is too small'; - } - - return { - reason, - valid: !reason - } -} - -const includes = function(str, list) { - if (!_.isString(str)) - return false; - - return _.some(list, item => str.includes(item)); -} - - -const getMarketConfig = function(exchangeProperties) { - return _.find(exchangeProperties.markets, (p) => { - return _.first(p.pair) === global.MARKET.assetA.toUpperCase() && - _.last(p.pair) === global.MARKET.assetB.toUpperCase(); - }); -} - -module.exports = { - retry: retryInstance, - includes: includes, - isValidOrder, - getMarketConfig - -} \ No newline at end of file diff --git a/Exchange/wrappers/beautifier.js b/Exchange/wrappers/beautifier.js deleted file mode 100644 index 5e5e6a051..000000000 --- a/Exchange/wrappers/beautifier.js +++ /dev/null @@ -1,183 +0,0 @@ -const _ = require('underscore'); - -class Beautifier { - - constructor() { - this._beautifications = { - aggTrades: { - a: 'aggTradeId', - p: 'price', - q: 'quantity', - f: 'firstTradeId', - l: 'lastTradeId', - T: 'timestamp', - m: 'maker', - M: 'bestPriceMatch' - }, - klines: { - 0: 'openTime', - 1: 'open', - 2: 'high', - 3: 'low', - 4: 'close', - 5: 'volume', - 6: 'closeTime', - 7: 'quoteAssetVolume', - 8: 'trades', - 9: 'takerBaseAssetVolume', - 10: 'takerQuoteAssetVolume', - 11: 'ignored' - }, - bids: [ - { - 0: 'price', - 1: 'quantity', - 2: 'ignored' - } - ], - asks: [ - { - 0: 'price', - 1: 'quantity', - 2: 'ignored' - } - ], - depthUpdateEvent: { - e: 'eventType', - E: 'eventTime', - s: 'symbol', - u: 'updateId', - b: 'bidDepthDelta', - a: 'askDepthDelta' - }, - bidDepthDelta: [ - { - 0: 'price', - 1: 'quantity', - 2: 'ignored' - } - ], - askDepthDelta: [ - { - 0: 'price', - 1: 'quantity', - 2: 'ignored' - } - ], - klineEvent: { - e: 'eventType', - E: 'eventTime', - s: 'symbol', - k: 'kline' - }, - kline: { - t: 'startTime', - T: 'endTime', - s: 'symbol', - i: 'interval', - f: 'firstTradeId', - L: 'lastTradeId', - o: 'open', - c: 'close', - h: 'high', - l: 'low', - v: 'volume', - n: 'trades', - x: 'final', - q: 'quoteVolume', - V: 'volumeActive', - Q: 'quoteVolumeActive', - B: 'ignored' - }, - aggTradeEvent: { - e: 'eventType', - E: 'eventTime', - s: 'symbol', - a: 'tradeId', - p: 'price', - q: 'quantity', - f: 'firstTradeId', - l: 'lastTradeId', - T: 'time', - m: 'maker', - M: 'ignored' - }, - outboundAccountInfoEvent: { - e: 'eventType', - E: 'eventTime', - m: 'makerCommission', - t: 'takerCommission', - b: 'buyerCommission', - s: 'sellerCommission', - T: 'canTrade', - W: 'canWithdraw', - D: 'canDeposit', - B: 'balances' - }, - balances: [ - { - a: 'asset', - f: 'availableBalance', - l: 'onOrderBalance' - } - ], - executionReportEvent: { - e: 'eventType', - E: 'eventTime', - s: 'symbol', - c: 'newClientOrderId', - S: 'side', - o: 'orderType', - f: 'cancelType', // GTC 'Good till Cancel', IOC: 'Immediate or Cancel' - q: 'quantity', - p: 'price', - x: 'executionType', - X: 'orderStatus', - r: 'rejectReason', - i: 'orderId', - l: 'lastTradeQuantity', - z: 'accumulatedQuantity', - L: 'lastTradePrice', - n: 'commission', - N: 'commissionAsset', - m: 'maker', - T: 'tradeTime', - t: 'tradeId' - } - } - } - - beautify(object, type) { - const beautifications = _.isObject(type) ? type : this._beautifications[type]; - if (!beautifications) { - return object; - } - let newItem = {}; - _.each(object, (value, key) => { - if (_.isArray(value)) { - const newArray = []; - if (_.isArray(this._beautifications[beautifications[key]])) { - _.each(value, arrayValue => { - newArray.push(this.beautify(arrayValue, this._beautifications[beautifications[key]][0])); - }); - } else { - _.each(value, (value, key) => { - newItem.push(this.beautify(value, beautifications[key])) - }); - } - const newKey = beautifications[key] || key; - newItem[newKey] = newArray; - } else if (_.isObject(value)) { - const newKey = beautifications[key] || key; - newItem[newKey] = this.beautify(value, beautifications[key]); - } else { - const newKey = beautifications[key] || key; - newItem[newKey] = value; - } - }); - return newItem; - } - -} - -module.exports = Beautifier; \ No newline at end of file diff --git a/Exchange/wrappers/binance.js b/Exchange/wrappers/binance.js deleted file mode 100644 index 624c0fc06..000000000 --- a/Exchange/wrappers/binance.js +++ /dev/null @@ -1,368 +0,0 @@ -// Source: https://github.com/zoeyg/binance/blob/master/lib/rest.js - -const request = require('request'); -const qs = require('querystring'); -const _ = require('underscore'); -const crypto = require('crypto'); -const Beautifier = require('./beautifier.js'); -const assert = require('assert'); - -class BinanceRest { - - constructor({ - key, - secret, - recvWindow = false, - timeout = 15000, - disableBeautification = false, - handleDrift = false - }) { - this.key = key; - this.secret = secret; - this.recvWindow = recvWindow; - this.timeout = timeout; - this.disableBeautification = disableBeautification; - this.handleDrift = handleDrift; - - this._beautifier = new Beautifier(); - this._baseUrl = 'https://api.binance.com/'; - this._drift = 0; - this._syncInterval = 0; - } - - _makeRequest(query, callback, route, security, method, attempt = 0) { - assert(_.isUndefined(callback) || _.isFunction(callback), 'callback must be a function or undefined'); - assert(_.isObject(query), 'query must be an object'); - - let queryString; - const type = _.last(route.split('/')), - options = { - url: `${this._baseUrl}${route}`, - timeout: this.timeout - }; - - if (security === 'SIGNED') { - if (this.recvWindow) { - query.recvWindow = this.recvWindow; - } - queryString = qs.stringify(query); - options.url += '?' + queryString; - if (options.url.substr(options.url.length - 1) !== '?') { - options.url += '&'; - } - options.url += `signature=${this._sign(queryString)}`; - } else { - queryString = qs.stringify(query); - if (queryString) { - options.url += '?' + queryString; - } - } - if (security === 'API-KEY' || security === 'SIGNED') { - options.headers = { 'X-MBX-APIKEY': this.key }; - } - if (method) { - options.method = method; - } - - const action = cb => { - request(options, (err, response, body) => { - let payload; - try { - payload = JSON.parse(body); - } catch (e) { - payload = body; - } - if (err) { - cb(err, payload); - } else if (response.statusCode < 200 || response.statusCode > 299) { - /* - * If we get a response that the timestamp is ahead of the server, - * calculate the drift and then attempt the request again - */ - if (response.statusCode === 400 && payload.code === -1021 && - this.handleDrift && attempt === 0) { - - this.calculateDrift() - .then(() => { - query.timestamp = this._getTime() + this._drift; - return this._makeRequest(query, cb, route, security, method, - ++attempt); - }); - } else { - cb(new Error(`Response code ${response.statusCode}`), payload); - } - } else { - if (_.isArray(payload)) { - payload = _.map(payload, (item) => { - return this._doBeautifications(item, type); - }); - } else { - payload = this._doBeautifications(payload); - } - cb(err, payload); - } - }); - }; - if (callback) { - action(callback); - } else { - return new Promise((resolve, reject) => action((err, payload) => { - if (err) { - if (payload === undefined) { - reject(err); - } else { - reject(payload); - } - } else { - resolve(payload); - } - })); - } - } - - _doBeautifications(response, route) { - if (this.disableBeautification) { - return response; - } - return this._beautifier.beautify(response, route); - } - - _sign(queryString) { - return crypto.createHmac('sha256', this.secret) - .update(queryString) - .digest('hex'); - } - - _setTimestamp(query) { - if (!query.timestamp) { - query.timestamp = this._getTime() + this._drift; - } - } - - _getTime() { - return new Date().getTime(); - } - - calculateDrift() { - const systemTime = this._getTime(); - return this.time() - .then((response) => { - // Calculate the approximate trip time from here to binance - const transitTime = parseInt((this._getTime() - systemTime) / 2); - this._drift = response.serverTime - (systemTime + transitTime); - }); - } - - startTimeSync(interval = 300000, onRecalculateDriftCb) { - return new Promise((resolve, reject) => { - // If there's already an interval running, clear it and reset values - if (this._syncInterval !== 0) { - this.endTimeSync(); - return resolve(); - } - - // Calculate initial drift value and setup interval to periodically update it - this.calculateDrift() - .then(resolve) - .catch(reject); - - this._syncInterval = setInterval(() => { - const promise = this.calculateDrift(); - - if (_.isFunction(onRecalculateDriftCb)) { - onRecalculateDriftCb(promise); - } - }, interval); - }); - } - - endTimeSync() { - clearInterval(this._syncInterval); - this._drift = 0; - this._syncInterval = 0; - } - - // Public APIs - ping(callback) { - return this._makeRequest({}, callback, 'api/v1/ping'); - } - - time(callback) { - return this._makeRequest({}, callback, 'api/v1/time'); - } - - depth(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v1/depth'); - } - - trades(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v1/trades'); - } - - historicalTrades(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v1/historicalTrades', 'API-KEY'); - } - - aggTrades(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v1/aggTrades'); - } - - exchangeInfo(callback) { - return this._makeRequest({}, callback, 'api/v1/exchangeInfo'); - } - - klines(query = {}, callback) { - return this._makeRequest(query, callback, 'api/v1/klines'); - } - - ticker24hr(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v1/ticker/24hr'); - } - - tickerPrice(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v3/ticker/price'); - } - - bookTicker(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - - return this._makeRequest(query, callback, 'api/v3/ticker/bookTicker'); - } - - allBookTickers(callback) { - return this._makeRequest({}, callback, 'api/v1/ticker/allBookTickers'); - } - - allPrices(callback) { - return this._makeRequest({}, callback, 'api/v1/ticker/allPrices'); - } - - // Private APIs - newOrder(query = {}, callback) { - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/order', 'SIGNED', 'POST'); - } - - testOrder(query = {}, callback) { - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/order/test', 'SIGNED', 'POST'); - } - - queryOrder(query = {}, callback) { - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/order', 'SIGNED'); - } - - cancelOrder(query = {}, callback) { - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/order', 'SIGNED', 'DELETE'); - } - - openOrders(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/openOrders', 'SIGNED'); - } - - allOrders(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/allOrders', 'SIGNED'); - } - - account(query = {}, callback) { - if (_.isFunction(query)) { - callback = query; - query = {}; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/account', 'SIGNED'); - } - - myTrades(query = {}, callback) { - if (_.isString(query)) { - query = { symbol: query }; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'api/v3/myTrades', 'SIGNED'); - } - - withdraw(query = {}, callback) { - this._setTimestamp(query); - return this._makeRequest(query, callback, 'wapi/v3/withdraw.html', 'SIGNED', 'POST'); - } - - depositHistory(query = {}, callback) { - if (_.isString(query)) { - query = { asset: query }; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'wapi/v3/depositHistory.html', 'SIGNED'); - } - - withdrawHistory(query = {}, callback) { - if (_.isString(query)) { - query = { asset: query }; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'wapi/v3/withdrawHistory.html', 'SIGNED'); - } - - depositAddress(query = {}, callback) { - if (_.isString(query)) { - query = { asset: query }; - } - this._setTimestamp(query); - return this._makeRequest(query, callback, 'wapi/v3/depositAddress.html', 'SIGNED'); - } - - accountStatus(callback) { - const query = {}; - this._setTimestamp(query); - return this._makeRequest(query, callback, 'wapi/v3/accountStatus.html', 'SIGNED'); - } - - startUserDataStream(callback) { - return this._makeRequest({}, callback, 'api/v1/userDataStream', 'API-KEY', 'POST'); - } - - keepAliveUserDataStream(query = {}, callback) { - return this._makeRequest(query, callback, 'api/v1/userDataStream', 'API-KEY', 'PUT'); - } - - closeUserDataStream(query = {}, callback) { - return this._makeRequest(query, callback, 'api/v1/userDataStream', 'API-KEY', 'DELETE'); - } -} - -module.exports = BinanceRest; \ No newline at end of file diff --git a/Exchange/wrappers/binanceClient.js b/Exchange/wrappers/binanceClient.js deleted file mode 100644 index 3b00f3469..000000000 --- a/Exchange/wrappers/binanceClient.js +++ /dev/null @@ -1,355 +0,0 @@ -exports.newAPIClient = function newAPIClient(pKey, pSecret, logger) { - - const FULL_LOG = true; - const LOG_FILE_CONTENT = true; - const MODULE_NAME = "binanceClient"; - - const retry = require('../exchangeUtils').retry; - const includes = require('../exchangeUtils').includes; - const _ = require('lodash'); - const Binance = require("./binance"); - const exchangeProperties = require('./poloniexProperties.json'); - - const recoverableErrors = [ - 'SOCKETTIMEDOUT', - 'TIMEDOUT', - 'CONNRESET', - 'CONNREFUSED', - 'NOTFOUND', - 'Error -1021', - 'Response code 429', - 'Response code 5', - 'ETIMEDOUT' - ]; - - let API = new Binance({ - key: pKey, - secret: pSecret, - timeout: 15000, - recvWindow: 60000, - disableBeautification: false, - handleDrift: true, - }); - - let thisObject = { - getTicker: getTicker, - getOpenPositions: getOpenPositions, - getExecutedTrades: getExecutedTrades, - buy: buy, - sell: sell, - movePosition: movePosition, - getPublicTradeHistory: getPublicTradeHistory, - getExchangeProperties: getExchangeProperties, - isValidPrice: isValidPrice, - isValidLot: isValidLot - }; - - return thisObject; - - function joinCurrencies(currencyA, currencyB) { - // If only one arg, then return the first - if (typeof currencyB !== 'string') { - return currencyA; - } - - return currencyB + '' + currencyA; - } - - /* - * Returns the properties for this exchange - */ - function getExchangeProperties() { - return exchangeProperties; - } - - function truncDecimals(pFloatValue) { - - let decimals = 6; - - return parseFloat(parseFloat(pFloatValue).toFixed(decimals)); - - } - - /* - * Returns the price for a given pair of assets. - * The object returned is an array of trades: - * ticker = { - * bid, Number - * ask, Number - * last Number - * }; - */ - function getTicker(pMarket, callBack) { - - let market = joinCurrencies(pMarket.assetA, pMarket.assetB); - const handle = (err, response) => { - let ticker; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - ticker = { - bid: Number(response.bidPrice), - ask: Number(response.askPrice), - last: Number(response.lastPrice) - }; - } - callBack(err, ticker); - }; - - const fetch = next => API.ticker24hr(market, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Returns the open positions ath the exchange for a given market and user account. - * The object returned is an array of positions: - * position = { - * id, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * fee, (not required) Number - * datetime - * }; - */ - function getOpenPositions(pMarket, callBack) { - - let market = joinCurrencies(pMarket.assetA, pMarket.assetB); - const handle = (err, response) => { - let exchangePositions = []; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - for (let i = 0; i < response.length; i++) { - let openPosition = { - id: response[i].orderId, - type: response[i].side.toLowerCase(), - rate: Number(response[i].price), - amountA: truncDecimals(response[i].origQty * response[i].price), - amountB: Number(response[i].origQty), - date: (new Date(response[i].time)).valueOf() - }; - exchangePositions.push(openPosition); - } - } - callBack(err, exchangePositions); - }; - - const fetch = next => API.openOrders(market, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Returns the trades for a given order number. - * The object returned is an array of positions: - * position = { - * id, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * fee, Number - * datetime - * }; - */ - function getExecutedTrades(pPositionId, callBack) { - - let market = joinCurrencies(global.MARKET.assetA, global.MARKET.assetB); - const handle = (err, response) => { - let exchangeTrades = []; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - for (let i = 0; i < response.length; i++) { - if (response[i].orderId === pPositionId) { - let type = "sell" - if (response[i].isBuyer === true) { - type = "buy"; - } - let trade = { - id: response[i].orderId, - type: type, - rate: Number(response[i].price), - amountA: truncDecimals(response[i].qty * response[i].price), - amountB: Number(response[i].qty), - fee: Number(response[i].commission), - date: (new Date(response[i].time)).valueOf() - }; - exchangeTrades.push(trade); - break; - } - } - } - callBack(err, exchangeTrades); - }; - - const fetch = next => API.myTrades(market, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Creates a new buy order. - * The orderNumber is returned. - */ - function buy(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { - - var parameters = { - symbol: joinCurrencies(pCurrencyA, pCurrencyB), - side: 'BUY', - type: 'LIMIT', - quantity: pAmount, - price: pRate, - timeInForce: 'GTC' - }; - const handle = (err, response) => { - let orderNumber; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - orderNumber = response.orderId; - } - callBack(err, orderNumber); - }; - - const fetch = next => API.newOrder(parameters, analizeResponse(next)); - - retry(null, fetch, handle); - - } - - /* - * Creates a new sell order. - * The orderNumber is returned. String - */ - function sell(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { - - var parameters = { - symbol: joinCurrencies(pCurrencyA, pCurrencyB), - side: 'SELL', - type: 'LIMIT', - quantity: pAmount, - price: pRate, - timeInForce: 'GTC' - }; - const handle = (err, response) => { - let orderNumber; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - orderNumber = response.orderId; - } - callBack(err, orderNumber); - }; - - const fetch = next => API.newOrder(parameters, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* //TODO Complete partial orders - * Move an existing position to the new rate. - * The new orderNumber is returned. String - */ - function movePosition(pPosition, pNewRate, pNewAmountB, callBack) { - - var parameters = { - symbol: joinCurrencies(global.MARKET.assetA, global.MARKET.assetB), - orderId: pPosition.id - }; - - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] moveOrder -> Step1 - Cancelling Position: " + JSON.stringify(pPosition)); } - - const handle = (err, response) => { - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] moveOrder -> Step1 Complete - Position Cancelled. Proceeding to put the new position."); } - - if (position.type === "buy") - thisObject.buy(global.MARKET.assetA, global.MARKET.assetB, pNewRate, pNewAmountB, callBack); - else - thisObject.sell(global.MARKET.assetA, global.MARKET.assetB, pNewRate, pNewAmountB, callBack); - } else { - callBack(err); - } - }; - - const fetch = next => API.cancelOrder(parameters, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* //TODO Pending Review - * Returns all the trade history from the Exchange since startTime to endTime orderd by tradeId. - * It's possible that the exchange doesn't support this method. - * The object returned is an array of trades: - * trade = { - * tradeIdAtExchange, - * marketIdAtExchange, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * datetime - * }; - */ - function getPublicTradeHistory(assetA, assetB, startTime, endTime, callBack) { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] getPublicTradeHistory -> Not implemented yet."); } - callBack(global.DEFAULT_FAIL_RESPONSE); - } - - function isValidPrice(price) { - return price >= market.minimalOrder.price; - } - - function isValidLot(price, amount) { - return amount * price >= market.minimalOrder.order; - } - - function analizeResponse(callBack) { - - return (exchangeErr, exchangeResponse) => { - let error; - - /* This function analizes the different situations we might encounter trying to access Binance and returns appropiate standard errors. */ - - let stringExchangeErr = JSON.stringify(exchangeErr); - let stringExchangeResponse = JSON.stringify(exchangeResponse); - - try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeErr = " + stringExchangeErr); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeResponse = " + stringExchangeResponse); } - - if (exchangeErr) { - error = global.DEFAULT_FAIL_RESPONSE; - } else if (!exchangeResponse) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: 'Empty response' - }; - } else if (includes(exchangeResponse.error, [''])) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: exchangeResponse - }; - } else if (includes(exchangeResponse.error, ['Order does not exist.'])) { - error = { - result: global.CUSTOM_OK_RESPONSE.result, - message: exchangeResponse.error - }; - } else if (exchangeResponse.error) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: exchangeResponse.error - }; - } - - if (error) { - if (includes(error.message, recoverableErrors)) { - error.notFatal = true; - } - } - - return callBack(error, exchangeResponse); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] analizeResponse -> err.message = " + err.message); - return callBack(global.DEFAULT_FAIL_RESPONSE, exchangeResponse); - } - } - } - -} diff --git a/Exchange/wrappers/binanceProperties.json b/Exchange/wrappers/binanceProperties.json deleted file mode 100644 index ad4438de0..000000000 --- a/Exchange/wrappers/binanceProperties.json +++ /dev/null @@ -1,4594 +0,0 @@ -{ - "assets": [ - "NULS", - "VEN", - "BNB", - "NEO", - "LINK", - "SALT", - "IOTA", - "ETC", - "AST", - "KNC", - "WTC", - "SNGLS", - "EOS", - "SNT", - "MCO", - "BTC", - "OAX", - "OMG", - "GAS", - "BQX", - "QTUM", - "BNT", - "DNT", - "ICN", - "SNM", - "STRAT", - "ZRX", - "FUN", - "LTC", - "ETH", - "XVG", - "BCC", - "ADA", - "ADX", - "AE", - "AGI", - "AION", - "AMB", - "APPC", - "ARK", - "ARN", - "BAT", - "BCD", - "BCN", - "BCPT", - "BLZ", - "BRD", - "BTG", - "BTS", - "CDT", - "CHAT", - "CLOAK", - "CMT", - "CND", - "CVC", - "DASH", - "DATA", - "DENT", - "DGD", - "DLT", - "EDO", - "ELF", - "ENG", - "ENJ", - "EVX", - "FUEL", - "GNT", - "GRS", - "GTO", - "GVT", - "GXS", - "HSR", - "ICX", - "INS", - "IOST", - "IOTX", - "KEY", - "KMD", - "LEND", - "LOOM", - "LRC", - "LSK", - "LUN", - "MANA", - "MDA", - "MFT", - "MOD", - "MTH", - "MTL", - "NANO", - "NAS", - "NAV", - "NCASH", - "NEBL", - "NPXS", - "NXS", - "ONT", - "OST", - "PIVX", - "POA", - "POE", - "POWR", - "PPT", - "QKC", - "QLC", - "QSP", - "RCN", - "RDN", - "REP", - "REQ", - "RLC", - "RPX", - "SC", - "SKY", - "STEEM", - "STORJ", - "STORM", - "SUB", - "SYS", - "THETA", - "TNB", - "TNT", - "TRIG", - "TRX", - "TUSD", - "VIA", - "VIB", - "VIBE", - "WABI", - "WAN", - "WAVES", - "WINGS", - "WPR", - "XEM", - "XLM", - "XMR", - "XRP", - "XZC", - "YOYO", - "ZEC", - "ZEN", - "ZIL" - ], - "currencies": [ - "BNB", - "BTC", - "ETH", - "USDT" - ], - "markets": [ - { - "pair": [ - "BNB", - "NULS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BNB", - "VEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BNB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "NULS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "NEO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NULS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "LINK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "SALT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "IOTA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "ETC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "AST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "KNC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "WTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "SNGLS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "EOS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "SNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "MCO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "BTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.000001, - "price": 0.01, - "order": 10 - } - }, - { - "pair": [ - "ETH", - "OAX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "OMG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "GAS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BQX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "WTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "QTUM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "BNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "DNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "ICN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "SNM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "SNM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "SNGLS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "BQX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NEO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "KNC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "STRAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "ZRX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "QTUM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "FUN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "LTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "LINK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ETH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "XVG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "STRAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "ZRX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "IOTA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "BCC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "OMG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "MCO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "SALT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "ADA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ADA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ADA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "ADA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.1, - "price": 0.00001, - "order": 10 - } - }, - { - "pair": [ - "BNB", - "ADX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ADX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ADX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "AE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "AE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "AE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "AGI" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "AGI" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "AGI" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "AION" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "AION" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "AION" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "AMB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "AMB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "AMB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "APPC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "APPC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "APPC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ARK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ARK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ARN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ARN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "AST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "BAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "BCC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.00001, - "price": 0.01, - "order": 1 - } - }, - { - "pair": [ - "ETH", - "BCC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "BCC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.00001, - "price": 0.01, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "BCD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BCD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "BCN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BCN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BCN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "BCPT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BCPT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BCPT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "BLZ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BLZ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BLZ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "BNB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "BNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "BRD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BRD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BRD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "BTG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BTG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "BTS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "BTS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "BTS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "CDT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "CDT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "CHAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "CHAT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "CLOAK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "CLOAK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "CMT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "CMT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "CMT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "CND" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "CND" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "CND" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "CVC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "CVC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "CVC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "DASH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "DASH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "DATA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "DATA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "DENT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "DENT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "DGD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "DGD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "DLT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "DLT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "DLT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "DNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "EDO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "EDO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ELF" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ELF" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ENG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ENG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "ENJ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ENJ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ENJ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "EOS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "EOS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "USDT", - "EOS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "BNB", - "ETC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "ETH", - "ETC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "ETC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "EVX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "EVX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "FUEL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "FUEL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "FUN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "GNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "GNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "GNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "GRS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "GRS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "GTO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "GTO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "GTO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "GVT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "GVT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "GXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "GXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "HSR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "HSR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ICN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "ICX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ICX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ICX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "ICX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "INS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "INS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "IOST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "IOST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "IOTA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "USDT", - "IOTA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "IOTX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "IOTX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "KEY" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "KEY" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "KMD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "KMD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "LEND" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "LEND" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "LOOM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "LOOM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "LOOM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "LRC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "LRC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "LSK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "LSK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "LSK" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "LTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.00001, - "price": 0.01, - "order": 1 - } - }, - { - "pair": [ - "ETH", - "LTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "LTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.00001, - "price": 0.01, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "LUN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "LUN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "MANA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "MANA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "MCO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "MDA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "MDA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "MFT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "MFT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "MFT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "MOD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "MOD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "MTH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "MTH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "MTL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "MTL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NANO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "NANO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NANO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NAS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "NAS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NAS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NAV" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "NAV" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NAV" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NCASH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "NCASH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NCASH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NEBL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "NEBL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NEBL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NEO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 1 - } - }, - { - "pair": [ - "USDT", - "NEO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "NPXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NPXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "NXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "NXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "NXS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "OAX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "ONT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ONT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ONT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "ONT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 10 - } - }, - { - "pair": [ - "BNB", - "OST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "OST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "OST" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "PIVX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "PIVX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "PIVX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "POA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "POA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "POA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "POE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "POE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "POWR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "POWR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "POWR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "PPT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "PPT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "QKC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "QKC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "QLC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "QLC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "QLC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "QSP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "QSP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "QSP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "QTUM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "USDT", - "QTUM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 10 - } - }, - { - "pair": [ - "BNB", - "RCN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "RCN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "RCN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "RDN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "RDN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "RDN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "REP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "REP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "REP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "REQ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "REQ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "RLC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "RLC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "RLC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "RPX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "RPX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "RPX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "SC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "SC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "SC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "SKY" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "SKY" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "SKY" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "SNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "STEEM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "STEEM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "STEEM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "STORJ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "STORJ" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "STORM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "STORM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "STORM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "SUB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "SUB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "SYS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "SYS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "SYS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "THETA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "THETA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "THETA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "TNB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "TNB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "TNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "TNT" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "TRIG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "TRIG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "TRIG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "TRX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "TRX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "TRX" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.1, - "price": 0.00001, - "order": 10 - } - }, - { - "pair": [ - "BNB", - "TUSD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "TUSD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "TUSD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "TUSD" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "VEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "VEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "VEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "BNB", - "VIA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "VIA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "VIA" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "VIB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BTC", - "VIBE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "VIBE" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "ETH", - "VIB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "WABI" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "WABI" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "WABI" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "WAN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "WAN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "WAN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "WAVES" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "WAVES" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 1e-7, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "WAVES" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "WINGS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "WINGS" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-7, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "WPR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "WPR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "WTC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 1 - } - }, - { - "pair": [ - "BNB", - "XEM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "XEM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "XEM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "XLM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "XLM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "XLM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "XLM" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "XMR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "XMR" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "XRP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.00001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "XRP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "XRP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "XRP" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.1, - "price": 0.00001, - "order": 10 - } - }, - { - "pair": [ - "BTC", - "XVG" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "BNB", - "XZC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "XZC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "XZC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.000001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "YOYO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "YOYO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "YOYO" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "BTC", - "ZEC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ZEC" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "ZEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ZEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.000001, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ZEN" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.001, - "price": 0.00001, - "order": 0.01 - } - }, - { - "pair": [ - "BNB", - "ZIL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 0.000001, - "order": 1 - } - }, - { - "pair": [ - "BTC", - "ZIL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.001 - } - }, - { - "pair": [ - "ETH", - "ZIL" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 1, - "price": 1e-8, - "order": 0.01 - } - }, - { - "pair": [ - "USDT", - "BNB" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.01, - "price": 0.0001, - "order": 10 - } - }, - { - "pair": [ - "USDT", - "ETH" - ], - "maxDecimals": 6, - "minimalOrder": { - "amount": 0.00001, - "price": 0.01, - "order": 10 - } - } - ] -} \ No newline at end of file diff --git a/Exchange/wrappers/coss.js b/Exchange/wrappers/coss.js deleted file mode 100644 index 346655af5..000000000 --- a/Exchange/wrappers/coss.js +++ /dev/null @@ -1,340 +0,0 @@ -// Source: https://github.com/coss-exchange/trading-api-wrapper-node-js/blob/master/index.js -// Documentation: https://api.coss.io/v1/spec - -const request = require('superagent'); -const querystring = require('querystring'); -const HttpMethod = { POST: 1, GET: 2, DELETE: 3 }; -const util = require('util'); - -const HOST_URL = "https://trade.coss.io/c/api/v1"; -const HOST_URL2 = "https://engine.coss.io/api/v1"; -const EXCHANGE_HOST = "https://exchange.coss.io/api"; - - -//WRAPPER STARTS HERE (Commenting out stuff that coss wrote which should be part of bot.js (the actual trading bot) rather than index.js (the wrapper core functionality)) -let Coss = (keyVaultAPI) => { - - //HTTPS Private Request - async function transmit_encrypted_request(method, url, payload) { - var payload_json_str = method == HttpMethod.GET ? querystring.stringify(payload) : JSON.stringify(payload) - var sign = await transmit_payload_signature_get(payload_json_str) - var req_headers = transmit_signed_header_get(sign) - - console.log(`sending ${payload_json_str} to ${url}`) - - if (method == HttpMethod.POST) { - let response = await request.post(url).set(req_headers).send(payload_json_str) - return (response.body); - - } else if (method == HttpMethod.DELETE) { - let response = await request.delete(url).set(req_headers).send(payload_json_str) - return (response.body); - - } else if (method == HttpMethod.GET) { - let response = await request.get(url).set(req_headers).query(payload_json_str) - return (response.body); - } - - } - - function transmit_signed_header_get(sign) { - var req_headers = { - 'Content-Type': 'application/json', - 'X-Requested-With': 'XMLHttpRequest', - 'Authorization': sign.Key, - 'Signature': sign.Sign, - } - return req_headers - } - - //AUTHBUILDER - async function transmit_payload_signature_get(payload_json_str) { - const signTransaction = util.promisify(keyVaultAPI.signTransaction) - return await signTransaction(payload_json_str) - } - - //HTTPS Public Request - async function publicRequest(url) { - let response = await request.get(url) - return response.body; - } - - - return { - //PLACE LIMIT ORDER - placeLimitOrder: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("placeLimitOrder(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("placeLimitOrder(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } else if (!params.Side) { - return Promise.reject("placeLimitOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); - } else if (params.Side && params.Side !== 'Buy' && params.Side !== 'Sell') { - return Promise.reject("placeLimitOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); - } else if (!params.Price || !params.Amount) { - return Promise.reject("placeLimitOrder(), You must supply a valid Price and Amount, e.g. Price: '0.00000034' or Amount: '123.00000000'!"); - //} else if (typeof params.Price !== 'number' || typeof params.Amount !== 'number') { - //return Promise.reject("placeLimitOrder(), You must supply a valid Price and Amount as a number, e.g. Price: '0.00000034' or Amount: '123.00000000'!"); - } - var now = new Date().getTime() - var query_params = { - 'order_symbol': params.Symbol, - 'order_price': params.Price.toString(), - 'order_side': params.Side, - 'order_size': params.Amount.toString(), - 'type': 'limit', - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/add"; - return transmit_encrypted_request(HttpMethod.POST, url, query_params) - }, - - //PLACE MARKET ORDER - placeMarketOrder: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("placeMarketOrder(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("placeMarketOrder(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } else if (!params.Side) { - return Promise.reject("placeMarketOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); - } else if (params.Side && params.Side !== 'Buy' && params.Side !== 'Sell') { - return Promise.reject("placeMarketOrder(), You must supply a valid Side, e.g. 'BUY' or 'SELL'!"); - } else if (!params.Amount) { - return Promise.reject("placeMarketOrder(), You must supply a valid Amount, e.g. Amount: '123.00000000'!"); - } else if (typeof params.Amount !== 'number') { - return Promise.reject("placeMarketOrder(), You must supply a valid Amount as a number, e.g. Amount: '123.00000000'!"); - } - var now = new Date().getTime() - var query_params = { - 'order_symbol': params.Symbol, - 'order_side': params.Side, - 'order_size': params.Amount.toString(), - 'type': 'market', - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/add"; - return transmit_encrypted_request(HttpMethod.POST, url, query_params) - }, - - //Get Account Balances - getAccountBalances: async (params = {}) => { - var now = new Date().getTime() - var query_params = { - 'recvWindow': 5000, - 'timestamp': now - } - let url = HOST_URL + "/account/balances"; - return transmit_encrypted_request(HttpMethod.GET, url, query_params) - }, - - //Get Account Details - getAccountDetails: async (params = {}) => { - var now = new Date().getTime() - var query_params = { - 'recvWindow': 5000, - 'timestamp': now - } - let url = HOST_URL + "/account/details"; - return transmit_encrypted_request(HttpMethod.GET, url, query_params) - }, - - //CANCEL ORDER BY ID # - cancelOrder: async (params = {}) => { - if (!params.ID) { - return Promise.reject("cancelOrder(), You must supply a valid order_ID to cancel, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); - } else if (params.ID && typeof params.ID !== 'string') { - return Promise.reject("cancelOrder(), You must supply a valid order_ID to cancel as a string, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); - } else if (!params.Symbol) { - return Promise.reject("cancelOrder(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("cancelOrder(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - - var now = new Date().getTime() - var query_params = { - 'order_id': params.ID, - 'order_symbol': params.Symbol, - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/cancel"; - return transmit_encrypted_request(HttpMethod.DELETE, url, query_params) - }, - - //GET ORDER DETAILS - getOrderDetails: async (params = {}) => { - if (!params.ID) { - return Promise.reject("getOrderDetails(), You must supply a valid order_ID to cancel, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); - } else if (params.ID && typeof params.ID !== 'string') { - return Promise.reject("getOrderDetails(), You must supply a valid order_ID to cancel as a string, e.g. '9e5ae4dd-3369-401d-81f5-dff985e1c4e7'!"); - } - - var now = new Date().getTime() - var query_params = { - 'order_id': params.ID, - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/details"; - return transmit_encrypted_request(HttpMethod.POST, url, query_params) - }, - - //GET OPEN ORDERS - getOpenOrders: async (params = {}) => { - if (!params.Limit) { - return Promise.reject("getOpenOrders(), You must supply a valid Limit for your open orders, e.g. '10'!"); - } else if (params.Limit && typeof params.Limit !== 'number') { - return Promise.reject("getOpenOrders(), You must supply a valid Limit as a number for your open orders, e.g. '10'!"); - } else if (!params.Symbol) { - return Promise.reject("getOpenOrders(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getOpenOrders(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - - var now = new Date().getTime() - var query_params = { - 'limit': params.Limit.toString(), - 'page': 0, - 'symbol': params.Symbol, - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/list/open"; - return transmit_encrypted_request(HttpMethod.POST, url, query_params) - }, - - //GET COMPLETED ORDERS - getCompletedOrders: async (params = {}) => { - if (!params.Limit) { - return Promise.reject("getCompletedOrders(), You must supply a valid Limit for your open orders, e.g. '10'!"); - } else if (params.Limit && typeof params.Limit !== 'number') { - return Promise.reject("getCompletedOrders(), You must supply a valid Limit as a number for your open orders, e.g. '10'!"); - } else if (!params.Symbol) { - return Promise.reject("getCompletedOrders(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getCompletedOrders(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - - var now = new Date().getTime() - var query_params = { - 'limit': params.Limit.toString(), - 'page': 0, - 'symbol': params.Symbol, - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/list/completed"; - return transmit_encrypted_request(HttpMethod.POST, url, query_params) - }, - - //GET ALL USER ORDERS - getAllOrders: async (params = {}) => { - if (!params.Limit) { - return Promise.reject("getAllOrders(), You must supply a valid Limit for your open orders, e.g. '10'!"); - } else if (params.Limit && typeof params.Limit !== 'number') { - return Promise.reject("getAllOrders(), You must supply a valid Limit as a number for your open orders, e.g. '10'!"); - } else if (!params.Symbol) { - return Promise.reject("getAllOrders(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getAllOrders(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } else if (!params.ID) { - return Promise.reject("getAllOrders(), You must supply a valid account ID"); - } else if (params.ID && typeof params.ID !== 'string') { - return Promise.reject("getAllOrders(), You must supply a valid account ID as a string"); - } - - var now = new Date().getTime() - var query_params = { - 'symbol': params.Symbol, - 'from_id': params.ACCT_ID, - 'limit': params.Limit, - 'timestamp': now, - 'recvWindow': 5000 - } - let url = HOST_URL + "/order/list/all"; - return transmit_encrypted_request(HttpMethod.POST, url, query_params) - }, - - - //Public API Calls (don't need to be signed) - //get Market Price - getMarketPrice: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("getMarketPrice(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getMarketPrice(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - - let url = HOST_URL + "/market-price/" + '?symbol=' + params.Symbol; - - - return publicRequest(url); - }, - - //get Market Price - getPairDepth: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("getPairDepth(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getPairDepth(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - console.log(HOST_URL2 + "/dp" + '?symbol=' + params.Symbol); - let url = HOST_URL2 + "/dp" + '?symbol=' + params.Symbol; - - - return publicRequest(url); - }, - - //get Market Price - getMarketSides: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("getMarketSides(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getMarketSides(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - console.log(HOST_URL2 + "/dp" + '?symbol=' + params.Symbol); - let url = HOST_URL2 + "/dp" + '?symbol=' + params.Symbol; - - let pairDepth = await publicRequest(url); - let marketSides = [[pairDepth.bids[0][0], pairDepth.bids[0][1]], [pairDepth.asks[0][0], pairDepth.asks[0][1]]]; - - return (marketSides) - }, - - //get Exchange Info - getExchangeInfo: async () => { - console.log(HOST_URL + "/exchange-info"); - let url = HOST_URL + "/exchange-info"; - - return publicRequest(url); - }, - - //get Market Summary (NOT WORKING ATM) - getMarketSummary: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("getMarketSummary(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getMarketSummary(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - console.log(EXCHANGE_HOST + "/getmarketsummaries/" + '?symbol=' + params.Symbol); - let url = EXCHANGE_HOST + "/getmarketsummaries/" + '?symbol=' + params.Symbol; - - return publicRequest(url); - }, - - getTradeHistory: async (params = {}) => { - if (!params.Symbol) { - return Promise.reject("getTradeHistory(), You must supply a valid trading pair Symbol, e.g. 'COSS_ETH'!"); - } else if (params.Symbol && typeof params.Symbol !== 'string') { - return Promise.reject("getTradeHistory(), You must supply a valid trading pair Symbol as a string, e.g. 'COSS_ETH'!"); - } - console.log(HOST_URL2 + "/ht" + '?symbol=' + params.Symbol); - let url = HOST_URL2 + "/ht" + '?symbol=' + params.Symbol; - - return publicRequest(url); - } - } -}; -module.exports = exports = Coss; diff --git a/Exchange/wrappers/cossClient.js b/Exchange/wrappers/cossClient.js deleted file mode 100644 index 36a068946..000000000 --- a/Exchange/wrappers/cossClient.js +++ /dev/null @@ -1,178 +0,0 @@ -exports.newAPIClient = function newAPIClient(keyVaultAPI, logger) { - const Coss = require("./coss"); - const exchangeProperties = require('./cossProperties.json'); - let API = Coss(keyVaultAPI); - - let thisObject = { - getTicker: getTicker, - getOpenPositions: getOpenPositions, - getExecutedTrades: getExecutedTrades, - buy: buy, - sell: sell, - movePosition: movePosition, - getPublicTradeHistory: getPublicTradeHistory, - getExchangeProperties: getExchangeProperties, - isValidLot: isValidLot - }; - - return thisObject; - - function joinCurrencies(currencyA, currencyB) { - // If only one arg, then return the first - if (typeof currencyB !== 'string') { - return currencyA; - } - - return currencyA + '_' + currencyB; - } - - - /* - * Returns the properties for this exchange - */ - function getExchangeProperties() { - return exchangeProperties; - } - - /* - * Returns the price for a given pair of assets. - * The object returned is an array of trades: - * ticker = { - * bid, Number - * ask, Number - * last Number - * }; - */ - async function getTicker(pMarket, callBack) { - - let params = {} - params.Symbol = joinCurrencies(pMarket.assetB, pMarket.assetA) - try { - var response = await API.getPairDepth(params) - let ticker = { - bid: Number(response.bids[0][0]), - ask: Number(response.asks[0][0]), - last: Number((response.bids[0][0] + response.asks[0][0]) / 2) // TODO Pending review - }; - - callBack(global.DEFAULT_OK_RESPONSE.result, ticker) - } catch (error) { - callBack(global.DEFAULT_FAIL_RESPONSE.result) - } - } - - /* - * Returns the open positions ath the exchange for a given market and user account. - * The object returned is an array of positions: - * position = { - * id, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * fee, (not required) Number - * datetime - * }; - */ - function getOpenPositions(pMarket, callBack) { - // Not implemented yet - callBack(global.DEFAULT_OK_RESPONSE) - } - - /* - * Returns the trades for a given order number. - * The object returned is an array of positions: - * position = { - * id, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * fee, Number - * datetime - * }; - */ - function getExecutedTrades(pPositionId, callBack) { - // Not implemented yet - callBack(global.DEFAULT_OK_RESPONSE) - } - - /* - * Creates a new buy order. - * The orderNumber is returned. String - */ - function buy(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { - // Not implemented yet - callBack(global.DEFAULT_OK_RESPONSE) - } - - /* - * Creates a new sell order. - * The orderNumber is returned. String - */ - function sell(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { - // Not implemented yet - callBack(global.DEFAULT_OK_RESPONSE) - } - - /* - * Move an existing position to the new rate. - * The orderNumber is returned. String - */ - function movePosition(pPosition, pNewRate, pNewAmountB, callBack) { - // Not implemented yet - callBack(global.DEFAULT_OK_RESPONSE) - } - - /* - * Returns all the trade history from the Exchange since startTime to endTime orderd by tradeId. - * It's possible that the exchange doesn't support this method. - * The object returned is an array of trades: - * trade = { - * tradeID, String - * globalTradeID, String - * type, String - * rate, Number - * amountA, Number - * amountB, Number - * date Date - * }; - */ - async function getPublicTradeHistory(assetA, assetB, startTime, endTime, callBack) { - - let params = {} - params.Symbol = joinCurrencies(assetB, assetA) - try { - let trades = [] - var response = await API.getTradeHistory(params); - for (let i = 0; i < response.history.length; i++) { - let record = response.history[i] - let type - if (record.isBuyerMaker) { - type = "sell" - } else { - type = "buy" - } - - let trade = { - tradeID: record.id, - globalTradeID: record.id, - type: type, - rate: Number(record.price), - amount: Number(record.qty), - total: Number(record.price) * Number(record.qty), - date: new Date(record.time) - } - trades.push(trade); - } - trades.sort((a, b) => b.tradeID - a.tradeID); - callBack(global.DEFAULT_OK_RESPONSE, trades); - } catch (error) { - callBack(global.DEFAULT_FAIL_RESPONSE); - } - } - - function isValidLot(price, amount) { - return amount * price >= 0.0001; - } -} diff --git a/Exchange/wrappers/cossProperties.json b/Exchange/wrappers/cossProperties.json deleted file mode 100644 index 310e7b119..000000000 --- a/Exchange/wrappers/cossProperties.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "currencies": [ - "BTC", - "USDT" - ], - "assets": [ - "BTC", - "USDT" - ], - "markets": [ - { - "pair": [ - "BTC", - "USDT" - ], - "maxDecimals": 5, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - } - ] -} diff --git a/Exchange/wrappers/poloniex.js b/Exchange/wrappers/poloniex.js deleted file mode 100644 index 9a1a32b41..000000000 --- a/Exchange/wrappers/poloniex.js +++ /dev/null @@ -1,440 +0,0 @@ -// Source: https://github.com/premasagar/poloniex.js -// Documentation: https://poloniex.com/support/api/ - -module.exports = (function () { - 'use strict'; - - // Module dependencies - var request = require('request'), - nonce = require('nonce')(); - - // Constants - var version = '0.0.9', - PUBLIC_API_URL = 'https://poloniex.com/public', - PRIVATE_API_URL = 'https://poloniex.com/tradingApi', - USER_AGENT = 'poloniex.js ' + version; - //USER_AGENT = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0' - - // Helper methods - function joinCurrencies(currencyA, currencyB) { - // If only one arg, then return the first - if (typeof currencyB !== 'string') { - return currencyA; - } - - return currencyA + '_' + currencyB; - } - - // Constructor - function Poloniex(keyVaultAPI) { - // Generate headers signed by this user's key and secret. - // The secret is encapsulated and never exposed - this._getPrivateHeaders = function (parameters, next) { - var paramString, signature; - - // Convert to `arg1=foo&arg2=bar` - paramString = Object.keys(parameters).map(function (param) { - return encodeURIComponent(param) + '=' + encodeURIComponent(parameters[param]); - }).join('&'); - - keyVaultAPI.signTransaction(paramString, next); - }; - } - - // Currently, this fails with `Error: CERT_UNTRUSTED` - // Poloniex.STRICT_SSL can be set to `false` to avoid this. Use with caution. - // Will be removed in future, once this is resolved. - Poloniex.STRICT_SSL = true; - - // Customisable user agent string - Poloniex.USER_AGENT = USER_AGENT; - - // Prototype - Poloniex.prototype = { - constructor: Poloniex, - - // Make an API request - _request: function (options, callback) { - if (!('headers' in options)) { - options.headers = {}; - } - - options.json = true; - options.headers['User-Agent'] = Poloniex.USER_AGENT; - options.strictSSL = Poloniex.STRICT_SSL; - options.timeout = 60 * 1000; - - request(options, function (err, response, body) { - // Empty response - if (!err && (typeof body === 'undefined' || body === null)) { - err = 'Empty response'; - } - - callback(err, body); - }); - - return this; - }, - - // Make a public API request - _public: function (command, parameters, callback) { - var options; - - if (typeof parameters === 'function') { - callback = parameters; - parameters = {}; - } - - parameters || (parameters = {}); - parameters.command = command; - options = { - method: 'GET', - url: PUBLIC_API_URL, - qs: parameters - }; - - options.qs.command = command; - return this._request(options, callback); - }, - - // Make a private API request - _private: function (command, parameters, callback) { - var options; - - if (typeof parameters === 'function') { - callback = parameters; - parameters = {}; - } - - parameters || (parameters = {}); - parameters.command = command; - parameters.nonce = nonce(); - - options = { - method: 'POST', - url: PRIVATE_API_URL, - form: parameters - }; - - let headers = this._getPrivateHeaders(parameters, next) - - let thisObject = this - - function next(pHeaders, error) { - if (!error) { - options.headers = pHeaders; - return thisObject._request(options, callback); - } else { - callback(error); - } - - } - }, - - ///// - // PUBLIC METHODS - - returnTicker: function (callback) { - return this._public('returnTicker', callback); - }, - - return24hVolume: function (callback) { - return this._public('return24hVolume', callback); - }, - - returnOrderBook: function (currencyA, currencyB, callback) { - var currencyPair; - - if (typeof currencyB === 'function') { - currencyPair = currencyA; - callback = currencyB; - currencyB = null; - } - - else { - currencyPair = joinCurrencies(currencyA, currencyB); - } - - var parameters = { - currencyPair: currencyPair - }; - - return this._public('returnOrderBook', parameters, callback); - }, - - returnChartData: function (currencyA, currencyB, period, start, end, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - period: period, - start: start, - end: end - }; - - return this._public('returnChartData', parameters, callback); - }, - - returnCurrencies: function (callback) { - return this._public('returnCurrencies', callback); - }, - - returnLoanOrders: function (currency, callback) { - return this._public('returnLoanOrders', { currency: currency }, callback); - }, - - returnTradeHistory: function (currencyA, currencyB, start, end, callback) { - if (arguments.length < 5) { - callback = start; - start = Date.now() / 1000 - 60 * 60; - end = Date.now() / 1000 + 60 * 60; // Some buffer in case of client/server time out of sync. - } - - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - start: start, - end: end - }; - - return this._public('returnTradeHistory', parameters, callback); - }, - - ///// - // PRIVATE METHODS - - returnBalances: function (callback) { - return this._private('returnBalances', {}, callback); - }, - - returnCompleteBalances: function (account, callback) { - var parameters = {}; - - if (typeof account === 'function') { - callback = account; - } - - else if (typeof account === 'string' && !!account) { - parameters.account = account; - } - - return this._private('returnCompleteBalances', parameters, callback); - }, - - returnDepositAddresses: function (callback) { - return this._private('returnDepositAddresses', {}, callback); - }, - - generateNewAddress: function (currency, callback) { - return this._private('generateNewAddress', { currency: currency }, callback); - }, - - returnDepositsWithdrawals: function (start, end, callback) { - return this._private('returnDepositsWithdrawals', { start: start, end: end }, callback); - }, - - // can be called with `returnOpenOrders('all', callback)` - returnOpenOrders: function (currencyA, currencyB, callback) { - var currencyPair; - - if (typeof currencyB === 'function') { - currencyPair = currencyA; - callback = currencyB; - currencyB = null; - } - - else { - currencyPair = joinCurrencies(currencyA, currencyB); - } - - var parameters = { - currencyPair: currencyPair - }; - - return this._private('returnOpenOrders', parameters, callback); - }, - - returnOrderTrades: function (orderNumber, callback) { - var parameters = { - orderNumber: orderNumber - }; - - return this._private('returnOrderTrades', parameters, callback); - }, - - buy: function (currencyA, currencyB, rate, amount, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - rate: rate, - amount: amount - }; - - return this._private('buy', parameters, callback); - }, - - sell: function (currencyA, currencyB, rate, amount, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - rate: rate, - amount: amount - }; - - return this._private('sell', parameters, callback); - }, - - cancelOrder: function (currencyA, currencyB, orderNumber, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - orderNumber: orderNumber - }; - - return this._private('cancelOrder', parameters, callback); - }, - - moveOrder: function (orderNumber, rate, amount, callback) { - var parameters = { - orderNumber: orderNumber, - rate: rate, - amount: amount ? amount : null - }; - - return this._private('moveOrder', parameters, callback); - }, - - withdraw: function (currency, amount, address, callback) { - var parameters = { - currency: currency, - amount: amount, - address: address - }; - - return this._private('withdraw', parameters, callback); - }, - - returnFeeInfo: function (callback) { - return this._private('returnFeeInfo', {}, callback); - }, - - returnAvailableAccountBalances: function (account, callback) { - var parameters = {}; - - if (typeof account === 'function') { - callback = account; - } - - else if (typeof account === 'string' && !!account) { - parameters.account = account; - } - - return this._private('returnAvailableAccountBalances', parameters, callback); - }, - - returnTradableBalances: function (callback) { - return this._private('returnTradableBalances', {}, callback); - }, - - transferBalance: function (currency, amount, fromAccount, toAccount, callback) { - var parameters = { - currency: currency, - amount: amount, - fromAccount: fromAccount, - toAccount: toAccount - }; - - return this._private('transferBalance', parameters, callback); - }, - - returnMarginAccountSummary: function (callback) { - return this._private('returnMarginAccountSummary', {}, callback); - }, - - marginBuy: function (currencyA, currencyB, rate, amount, lendingRate, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - rate: rate, - amount: amount, - lendingRate: lendingRate ? lendingRate : null - }; - - return this._private('marginBuy', parameters, callback); - }, - - marginSell: function (currencyA, currencyB, rate, amount, lendingRate, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB), - rate: rate, - amount: amount, - lendingRate: lendingRate ? lendingRate : null - }; - - return this._private('marginSell', parameters, callback); - }, - - getMarginPosition: function (currencyA, currencyB, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB) - }; - - return this._private('getMarginPosition', parameters, callback); - }, - - closeMarginPosition: function (currencyA, currencyB, callback) { - var parameters = { - currencyPair: joinCurrencies(currencyA, currencyB) - }; - - return this._private('closeMarginPosition', parameters, callback); - }, - - createLoanOffer: function (currency, amount, duration, autoRenew, lendingRate, callback) { - var parameters = { - currency: currency, - amount: amount, - duration: duration, - autoRenew: autoRenew, - lendingRate: lendingRate - }; - - return this._private('createLoanOffer', parameters, callback); - }, - - cancelLoanOffer: function (orderNumber, callback) { - var parameters = { - orderNumber: orderNumber - }; - - return this._private('cancelLoanOffer', parameters, callback); - }, - - returnOpenLoanOffers: function (callback) { - return this._private('returnOpenLoanOffers', {}, callback); - }, - - returnActiveLoans: function (callback) { - return this._private('returnActiveLoans', {}, callback); - }, - - returnLendingHistory: function (start, end, limit, callback) { - var parameters = { - start: start, - end: end, - limit: limit - }; - - return this._private('returnLendingHistory', parameters, callback); - }, - - toggleAutoRenew: function (orderNumber, callback) { - return this._private('toggleAutoRenew', { orderNumber: orderNumber }, callback); - } - - }; - - // Backwards Compatibility - Poloniex.prototype.getTicker = Poloniex.prototype.returnTicker; - Poloniex.prototype.get24hVolume = Poloniex.prototype.return24hVolume; - Poloniex.prototype.getOrderBook = Poloniex.prototype.returnOrderBook; - Poloniex.prototype.getTradeHistory = Poloniex.prototype.returnChartData; - Poloniex.prototype.myBalances = Poloniex.prototype.returnBalances; - Poloniex.prototype.myOpenOrders = Poloniex.prototype.returnOpenOrders; - Poloniex.prototype.myTradeHistory = Poloniex.prototype.returnTradeHistory; - - return Poloniex; -})(); diff --git a/Exchange/wrappers/poloniexClient.js b/Exchange/wrappers/poloniexClient.js deleted file mode 100644 index 34bc7a00f..000000000 --- a/Exchange/wrappers/poloniexClient.js +++ /dev/null @@ -1,348 +0,0 @@ -exports.newAPIClient = function newAPIClient(keyVaultAPI, logger) { - - const FULL_LOG = true; - const LOG_FILE_CONTENT = false; - const MODULE_NAME = "poloniexClient"; - - const retry = require('../exchangeUtils').retry; - const includes = require('../exchangeUtils').includes; - const _ = require('lodash'); - const Poloniex = require("./poloniex"); - const exchangeProperties = require('./poloniexProperties.json'); - - const recoverableErrors = [ - 'SOCKETTIMEDOUT', - 'TIMEDOUT', - 'CONNRESET', - 'CONNREFUSED', - 'NOTFOUND', - '429', - '522', - '504', - '503', - '500', - '502', - 'Empty response', - 'Please try again in a few minutes.', - 'Nonce must be greater than', - 'Internal error. Please try again.', - 'Connection timed out. Please try again.', - 'ENOTFOUND', - 'ECONNREFUSED', - 'CONNREFUSED', - 'NOTFOUND', - 'ESOCKETTIMEDOUT', - 'ECONNRESET', - 'Connection timed out', - 'Connection Error', - 'Order not found, or you are not the person who placed it.', - 'ETIMEDOUT' - ]; - - let API = new Poloniex(keyVaultAPI); - - let thisObject = { - getTicker: getTicker, - getOpenPositions: getOpenPositions, - getExecutedTrades: getExecutedTrades, - buy: buy, - sell: sell, - movePosition: movePosition, - getPublicTradeHistory: getPublicTradeHistory, - getExchangeProperties: getExchangeProperties, - isValidLot: isValidLot - }; - - return thisObject; - - function joinCurrencies(currencyA, currencyB) { - // If only one arg, then return the first - if (typeof currencyB !== 'string') { - return currencyA; - } - - return currencyA + '_' + currencyB; - } - - - /* - * Returns the properties for this exchange - */ - function getExchangeProperties() { - return exchangeProperties; - } - - /* - * Returns the price for a given pair of assets. - * The object returned is an array of trades: - * ticker = { - * bid, Number - * ask, Number - * last Number - * }; - */ - function getTicker(pMarket, callBack) { - - const handle = (err, response) => { - let ticker; - let market = joinCurrencies(pMarket.assetA, pMarket.assetB); - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - ticker = { - bid: Number(response[market].highestBid), - ask: Number(response[market].lowestAsk), - last: Number(response[market].last) - }; - } - callBack(err, ticker); - }; - - const fetch = next => API.getTicker(analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Returns the open positions ath the exchange for a given market and user account. - * The object returned is an array of positions: - * position = { - * id, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * fee, (not required) Number - * datetime - * }; - */ - function getOpenPositions(pMarket, callBack) { - - const handle = (err, response) => { - let exchangePositions = []; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - for (let i = 0; i < response.length; i++) { - let openPosition = { - id: response[i].orderNumber, - type: response[i].type, - rate: Number(response[i].rate), - amountA: Number(response[i].total), - amountB: Number(response[i].amount), - date: (new Date(response[i].time)).valueOf() - }; - exchangePositions.push(openPosition); - } - } - callBack(err, exchangePositions); - }; - - const fetch = next => API.returnOpenOrders(pMarket.assetA, pMarket.assetB, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Returns the trades for a given order number. - * The object returned is an array of positions: - * position = { - * id, - * type, - * rate, Number - * amountA, Number - * amountB, Number - * fee, Number - * datetime - * }; - */ - function getExecutedTrades(pPositionId, callBack) { - - const handle = (err, response) => { - let trades = []; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - for (let i = 0; i < response.length; i++) { - let trade = { - id: response[i].tradeID, - type: response[i].type, - rate: Number(response[i].rate), - amountA: Number(response[i].total), - amountB: Number(response[i].amount), - fee: Number(response[i].fee), - date: (new Date(response[i].date)).valueOf() - } - trades.push(trade); - } - } else if (err.result === global.CUSTOM_OK_RESPONSE.result) { - // No trades found at the exchange for the position, but returning empy trades object. - err = global.DEFAULT_OK_RESPONSE; - } - callBack(err, trades); - }; - - const fetch = next => API.returnOrderTrades(pPositionId, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Creates a new buy order. - * The orderNumber is returned. String - */ - function buy(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { - - const handle = (err, response) => { - let orderNumber; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - orderNumber = response.orderNumber; - } - callBack(err, orderNumber); - }; - - const fetch = next => API.buy(pCurrencyA, pCurrencyB, pRate, pAmount, analizeResponse(next)); - - retry(null, fetch, handle); - - } - - /* - * Creates a new sell order. - * The orderNumber is returned. String - */ - function sell(pCurrencyA, pCurrencyB, pRate, pAmount, callBack) { - - const handle = (err, response) => { - let orderNumber; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - orderNumber = response.orderNumber; - } - callBack(err, orderNumber); - }; - - const fetch = next => API.sell(pCurrencyA, pCurrencyB, pRate, pAmount, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Move an existing position to the new rate. - * The orderNumber is returned. String - */ - function movePosition(pPosition, pNewRate, pNewAmountB, callBack) { - - const handle = (err, response) => { - let orderNumber; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - orderNumber = response.orderNumber; - } - callBack(err, orderNumber); - }; - - const fetch = next => API.moveOrder(pPosition.id, pNewRate, pNewAmountB, analizeResponse(next)); - - retry(null, fetch, handle); - } - - /* - * Returns all the trade history from the Exchange since startTime to endTime orderd by tradeId. - * It's possible that the exchange doesn't support this method. - * The object returned is an array of trades: - * trade = { - * tradeID, String - * globalTradeID, String - * type, String - * rate, Number - * amountA, Number - * amountB, Number - * date Date - * }; - */ - function getPublicTradeHistory(assetA, assetB, startTime, endTime, callBack) { - - const handle = (err, response) => { - let trades = []; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - for (let i = 0; i < response.length; i++) { - let trade = { - tradeID: response[i].tradeID, - globalTradeID: response[i].globalTradeID, - type: response[i].type, - rate: Number(response[i].rate), - total: Number(response[i].total), - amount: Number(response[i].amount), - date: new Date(response[i].date) - } - trades.push(trade); - } - } - callBack(err, trades); - }; - - const fetch = next => API.returnTradeHistory(assetA, assetB, startTime, endTime, analizeResponse(next)); - - retry(null, fetch, handle); - } - - function isValidLot(price, amount) { - return amount * price >= 0.0001; - } - - function analizeResponse(callBack) { - - return (exchangeErr, exchangeResponse) => { - let error; - - /* This function analizes the different situations we might encounter trying to access Poloniex and returns appropiate standard errors. */ - - let stringExchangeErr = JSON.stringify(exchangeErr); - let stringExchangeResponse = JSON.stringify(exchangeResponse); - - try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeErr = " + stringExchangeErr); } - if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeResponse = " + stringExchangeResponse); } - - if (exchangeErr) { - error = global.DEFAULT_FAIL_RESPONSE; - - if (includes(exchangeErr.code, recoverableErrors)) { - error.notFatal = true; - } - } else if (!exchangeResponse || exchangeResponse === undefined) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: 'Empty response', - notFatal: true - }; - } else if (includes(exchangeResponse.error, ['Please complete the security check to proceed.'])) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: 'The IP has been flagged by CloudFlare.' - }; - } else if (includes(exchangeResponse.error, [''])) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: exchangeResponse - }; - } else if (includes(exchangeResponse.error, ['Not enough'])) { - error = { - result: global.DEFAULT_RETRY_RESPONSE.result, - message: exchangeResponse.error - }; - } else if (includes(exchangeResponse.error, ['Order not found, or you are not the person who placed it.'])) { - error = { - result: global.CUSTOM_OK_RESPONSE.result, - message: exchangeResponse.error - }; - } else if (exchangeResponse.error) { - error = { - result: global.DEFAULT_FAIL_RESPONSE.result, - message: exchangeResponse.error - }; - } - - return callBack(error, exchangeResponse); - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] analizeResponse -> err.message = " + err.message); - return callBack(global.DEFAULT_FAIL_RESPONSE, exchangeResponse); - } - } - } - -} diff --git a/Exchange/wrappers/poloniexProperties.json b/Exchange/wrappers/poloniexProperties.json deleted file mode 100644 index a5716ba3b..000000000 --- a/Exchange/wrappers/poloniexProperties.json +++ /dev/null @@ -1,3513 +0,0 @@ -{ - "currencies": ["BTC", "ETH", "XMR", "USDT"], - "assets": [ - "1CR", "ABY", "AC", "ACH", "ADN", "AEON", "AERO", "AIR", "AMP", "APH", - "ARCH", "AUR", "AXIS", "BALLS", "BANK", "BBL", "BBR", "BCC", "BCH", "BCN", - "BCY", "BDC", "BDG", "BELA", "BITCNY", "BITS", "BITUSD", "BLK", "BLOCK", - "BLU", "BNS", "BONES", "BOST", "BTC", "BTCD", "BTCS", "BTM", "BTS", - "BURN", "BURST", "C2", "CACH", "CAI", "CC", "CCN", "CGA", "CHA", "CINNI", - "CLAM", "CNL", "CNMT", "CNOTE", "COMM", "CON", "CORG", "CRYPT", "CURE", - "CVC", "CYC", "DAO", "DASH", "DCR", "DGB", "DICE", "DIEM", "DIME", "DIS", "DNS", - "DOGE", "DRKC", "DRM", "DSH", "DVK", "EAC", "EBT", "ECC", "EFL", "EMC2", - "EMO", "ENC", "ETC", "ETH", "eTOK", "EXE", "EXP", "FAC", "FCN", "FCT", - "FIBRE", "FLAP", "FLDC", "FLO", "FLT", "FOX", "FRAC", "FRK", "FRQ", "GNO", - "FVZ", "FZ", "FZN", "GAME", "GAP", "GAS", "GDN", "GEMZ", "GEO", "GIAR", "GLB", - "GML", "GNS", "GNT", "GOLD", "GPC", "GPUC", "GRC", "GRCX", "GRS", "GUE", "H2O", - "HIRO", "HOT", "HUC", "HUGE", "HVC", "HYP", "HZ", "IFC", "INDEX", "IOC", - "ITC", "IXC", "JLH", "JPC", "JUG", "KDC", "KEY", "LBC", "LC", "LCL", - "LEAF", "LGC", "LOL", "LOVE", "LQD", "LSK", "LTBC", "LTC", "LTCX", - "MAID", "MAST", "MAX", "MCN", "MEC", "METH", "MIL", "MIN", "MINT", "MMC", - "MMNXT", "MMXIV", "MNTA", "MON", "MRC", "MRS", "MTS", "MUN", "MYR", - "MZC", "N5X", "NAS", "NAUT", "NAV", "NBT", "NEOS", "NL", "NMC", "NOBL", - "NOTE", "NOXT", "NRS", "NSR", "NTX", "NXT", "NXTI", "OMG", "OMNI", "OPAL", - "PAND", "PASC", "PAWN", "PIGGY", "PINK", "PLX", "PMC", "POT", "PPC", "PRC", - "PRT", "PTS", "Q2C", "QBK", "QCN", "QORA", "QTL", "RADS", "RBY", "RDD", "REP", - "RIC", "RZR", "SBD", "SC", "SDC", "SHIBE", "SHOPX", "SILK", "SJCX", - "SLR", "SMC", "SOC", "SPA", "SQL", "SRCC", "SRG", "SSD", "STEEM", "STR", - "SUM", "SUN", "SWARM", "SXC", "SYNC", "SYS", "TAC", "TOR", "TRUST", - "TWE", "UIS", "ULTC", "UNITY", "URO", "USDE", "USDT", "UTC", "UTIL", - "UVC", "VIA", "VOOT", "VOX", "VRC", "VTC", "WC", "WDC", "WIKI", "WOLF", - "X13", "XAI", "XAP", "XBC", "XC", "XCH", "XCN", "XCP", "XCR", "XDN", - "XDP", "XEM", "XHC", "XLB", "XMG", "XMR", "XPB", "XPM", "XRP", "XSI", - "XST", "XSV", "XUSD", "XVC", "XXC", "BCH", "YACC", "YANG", "YC", "YIN", "ZEC", - "ZRX" - ], - "markets": [ - { - "pair": [ - "BTC", - "1CR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ABY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ACH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ADN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AEON" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AERO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AIR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AMP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "APH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ARCH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AUR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "AXIS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BALLS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BANK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BBL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BBR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BCC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BCH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BCY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BDC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BDG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BELA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BITCNY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BITS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BITUSD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BLK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BLOCK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BLU" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BNS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BONES" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BOST" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BTCD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BTCS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BTM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BTS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BURN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "BURST" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "C2" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CACH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CAI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CGA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CHA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CINNI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CLAM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CNL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CNMT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CNOTE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "COMM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CON" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CORG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CRYPT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CURE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CVC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "CYC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DAO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DASH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DCR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DGB" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DICE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DIEM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DIME" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DIS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DNS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DOGE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DRKC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DRM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DSH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "DVK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EAC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EBT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ECC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EFL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EMC2" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EMO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ENC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ETC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ETH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "eTOK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EXE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "EXP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FAC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FCT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FIBRE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FLAP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FLDC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FLO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FLT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FOX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FRAC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FRK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FRQ" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FVZ" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FZ" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "FZN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GAME" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GAP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GAS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GDN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GEMZ" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GEO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GIAR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GLB" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GML" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GNS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GOLD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GPC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GPUC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GRC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GRCX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GRS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "GUE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "H2O" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HIRO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HOT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HUC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HUGE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HVC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HYP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "HZ" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "IFC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "INDEX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "IOC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ITC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "IXC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "JLH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "JPC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "JUG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "KDC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "KEY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LBC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LCL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LEAF" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LGC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LOL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LOVE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LQD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LSK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LTBC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "LTCX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MAID" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MAST" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MAX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MEC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "METH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MIL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MIN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MINT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MMC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MMNXT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MMXIV" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MNTA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MON" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MRC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MRS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MTS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MUN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MYR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "MZC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "N5X" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NAS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NAUT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NAV" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NBT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NEOS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NMC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NOBL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NOTE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NOXT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NRS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NSR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NTX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NXT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "NXTI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "OMG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "OMNI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "OPAL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PAND" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PASC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PAWN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PIGGY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PINK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PLX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PMC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "POT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PPC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PRC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PRT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "PTS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "Q2C" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "QBK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "QCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "QORA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "QTL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "RADS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "RBY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "RDD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "REP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "RIC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "RZR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SBD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SDC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SHIBE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SHOPX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SILK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SJCX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SLR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SMC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SOC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SPA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SQL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SRCC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SRG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SSD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "STEEM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "STR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SUM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SUN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SWARM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SXC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SYNC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "SYS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "TAC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "TOR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "TRUST" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "TWE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "UIS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ULTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "UNITY" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "URO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "USDE" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "USDT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "UTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "UTIL" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "UVC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "VIA" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "VOOT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "VOX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "VRC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "VTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "WC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "WDC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "WIKI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "WOLF" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "X13" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XAI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XAP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XBC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XCH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XCP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XCR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XDN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XDP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XEM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XHC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XLB" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XMG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XMR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XPB" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XPM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XRP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XSI" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XST" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XSV" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XUSD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XVC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "XXC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "YACC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "YANG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "YC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "YIN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ZEC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "BTC", - "ZRX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "BTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "BCH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "DASH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "ETC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "ETH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "LTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "NXT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "REP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "STR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "XMR" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "XRP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "USDT", - "ZEC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "CVC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "ETC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "BCH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "GAS" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "GNO" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "GNT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "LSK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "OMG" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "REP" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "STEEM" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "ZEC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "ETH", - "ZRX" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "BCN" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "BLK" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "BTCD" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "DASH" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "LTC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "MAID" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "NXT" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - }, - { - "pair": [ - "XMR", - "ZEC" - ], - "maxDecimals": 8, - "minimalOrder": { - "amount": 0.0001, - "unit": "asset" - } - } - ] -} \ No newline at end of file diff --git a/Project.njsproj b/Project.njsproj index 79b200eb5..74198b26c 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -53,7 +53,6 @@ Code - diff --git a/SensorBotProcessMainLoop.js b/SensorBotProcessMainLoop.js index 7ce23337c..e8de93346 100644 --- a/SensorBotProcessMainLoop.js +++ b/SensorBotProcessMainLoop.js @@ -144,7 +144,7 @@ const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); - const EXCHANGE_API = require(ROOT_DIR + 'Exchange/ExchangeAPI'); + const EXCHANGE_API = require('@superalgos/exchangegateway.js'); const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies'); /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 610635efb..277874228 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -163,7 +163,7 @@ /* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */ const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); - const EXCHANGE_API = require(ROOT_DIR + 'Exchange/ExchangeAPI'); + const EXCHANGE_API = require('@superalgos/exchangegateway.js'); const CONTEXT = require(ROOT_DIR + 'Context'); const ASSISTANT = require(ROOT_DIR + 'Assistant'); const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); diff --git a/package-lock.json b/package-lock.json index e8e2796f6..8a9b5bfc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,39 @@ { - "name": "CloneExecutor", + "name": "@superalgos/clone-executor", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@superalgos/exchangegateway.js": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@superalgos/exchangegateway.js/-/exchangegateway.js-0.0.1.tgz", + "integrity": "sha512-RgMtDIPayDu2B7+9z/F/FwFcULVmoWGCrXmx63vJFzePmzsaVhtUisZC/qc2b6tbj88VCW1qLiwGh3D55Q7rAA==", + "requires": { + "apollo-boost": "0.1.16", + "assert": "1.4.1", + "axios": "0.18.0", + "azure-storage": "2.10.2", + "dotenv": "6.2.0", + "graphql": "14.0.2", + "jsonwebtoken": "8.4.0", + "lodash": "4.17.11", + "nodemailer": "4.6.8", + "nonce": "1.0.4", + "querystring": "0.2.0", + "retry": "0.12.0", + "superagent": "5.0.2", + "underscore": "1.9.1", + "winston": "3.1.0" + } + }, "@superalgos/mqservice": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@superalgos/mqservice/-/mqservice-0.0.9.tgz", - "integrity": "sha512-YH4BrDAE1+WmxBLu2JeVXzp/QiZwaKLLe6M+bh6ErliNGvGSOoB36/P5Vgmw6MDU81y6OU+hn5LqoRzESBW/CQ==" + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@superalgos/mqservice/-/mqservice-0.0.12.tgz", + "integrity": "sha1-XOfm592AbBFLemFzkO10plDcwos=", + "requires": { + "chai": "4.2.0", + "mocha": "6.0.2" + } }, "@types/async": { "version": "2.0.49", @@ -31,6 +57,24 @@ "json-schema-traverse": "0.3.1" } }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha1-V9NbhoboUeLMBMQD8cACA5dqGBM=" + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "requires": { + "color-convert": "1.9.3" + } + }, "apollo-boost": { "version": "0.1.16", "resolved": "https://registry.npmjs.org/apollo-boost/-/apollo-boost-0.1.16.tgz", @@ -139,6 +183,34 @@ "fclone": "1.0.11" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -160,6 +232,16 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", @@ -173,6 +255,11 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=" + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -217,6 +304,61 @@ } } }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -226,6 +368,47 @@ "tweetnacl": "0.14.5" } }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=" + }, "browserify-mime": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz", @@ -236,16 +419,120 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=" + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha1-dgqnLPION5XoSxKHfODoNzeqKeU=", + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, "color": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", @@ -309,16 +596,45 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, "cookiejar": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "requires": { + "nice-try": "1.0.5", + "path-key": "2.0.1", + "semver": "5.7.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=" + } + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -335,11 +651,79 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "requires": { + "type-detect": "4.0.8" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "requires": { + "object-keys": "1.1.0" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, "diagnostics": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", @@ -350,6 +734,11 @@ "kuler": "1.0.1" } }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=" + }, "dotenv": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", @@ -381,16 +770,197 @@ "env-variable": "0.0.5" } }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "requires": { + "once": "1.4.0" + } + }, "env-variable": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=", + "requires": { + "es-to-primitive": "1.2.0", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.4", + "is-regex": "1.0.4", + "object-keys": "1.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", + "requires": { + "is-callable": "1.1.4", + "is-date-object": "1.0.1", + "is-symbol": "1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "requires": { + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "1.0.3" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -421,6 +991,61 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "3.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "requires": { + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha1-CQvsiwXjnLowl0fx1YjwTbr5jbI=", + "requires": { + "is-buffer": "2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha1-Ts8/z3ScvR5HJonhCaxmJhol5yU=" + } + } + }, "follow-redirects": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", @@ -429,6 +1054,11 @@ "debug": "3.1.0" } }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -459,6 +1089,47 @@ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "requires": { + "pump": "3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -467,6 +1138,41 @@ "assert-plus": "1.0.0" } }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.3", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, "graphql": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", @@ -488,6 +1194,11 @@ "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.0.tgz", "integrity": "sha512-9FD6cw976TLLf9WYIUPCaaTpniawIjHWZSwIRZSjrfufJamcXbVVYfN2TWvJYbw0Xf2JjYbl1/f2+wDnBVw3/w==" }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4=" + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -502,6 +1213,53 @@ "har-schema": "2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "requires": { + "function-bind": "1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", @@ -511,6 +1269,19 @@ "safe-buffer": "5.1.2" } }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha1-dDKYzvTlrz4ZQWH7rcwhUdOgWOg=", + "requires": { + "parse-passwd": "1.0.0" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -521,11 +1292,48 @@ "sshpk": "1.14.2" } }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha1-c5P1r6Weyf9fZ6J2INEcIm4+7AI=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", @@ -536,21 +1344,146 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=" + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "requires": { + "isobject": "3.0.1" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.3" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", + "requires": { + "has-symbols": "1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -561,6 +1494,15 @@ "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha1-6u1lbsg0TxD1J8a/obbiJE3hZ9E=", + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -648,6 +1590,11 @@ "safe-buffer": "5.1.2" } }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=" + }, "kuler": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", @@ -656,6 +1603,23 @@ "colornames": "1.1.1" } }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha1-bvXS32DlL4LrIopMNz6NHzlyU88=", + "requires": { + "invert-kv": "2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "3.0.0", + "path-exists": "3.0.0" + } + }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", @@ -696,6 +1660,14 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "requires": { + "chalk": "2.4.2" + } + }, "logform": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", @@ -715,6 +1687,27 @@ } } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo=", + "requires": { + "p-defer": "1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, "md5.js": { "version": "1.3.4", "resolved": "http://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", @@ -724,11 +1717,41 @@ "inherits": "2.0.1" } }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha1-Rhr0l7xK4JYIzbLmDu+2m/90QXg=", + "requires": { + "map-age-cleaner": "0.1.3", + "mimic-fn": "2.1.0", + "p-is-promise": "2.0.0" + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, "mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", @@ -747,11 +1770,132 @@ "mime-db": "1.36.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.0.2.tgz", + "integrity": "sha1-zcGm/fZkcsB5tWBbrFnSmAdwLSw=", + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "findup-sync": "2.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.12.0", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.4", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "12.0.5", + "yargs-parser": "11.1.1", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "requires": { + "ms": "2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=" + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=" + }, + "node-environment-flags": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.4.tgz", + "integrity": "sha1-C3hKZVFCa/wW07IghCTcvCsv8Dg=", + "requires": { + "object.getownpropertydescriptors": "2.0.3" + } + }, "nodemailer": { "version": "4.6.8", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.8.tgz", @@ -762,21 +1906,192 @@ "resolved": "https://registry.npmjs.org/nonce/-/nonce-1.0.4.tgz", "integrity": "sha1-7nMCrejBvvR28wG4yR9cxRpIdhI=" }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha1-Eb0iNI3S4JagRasG9shbzDQPoDI=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "requires": { + "define-properties": "1.1.3", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.1.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.13.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, "one-time": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha1-qAKm7hfyTBBIOrmTVxnO9O0Wvxo=", + "requires": { + "execa": "1.0.0", + "lcid": "2.0.0", + "mem": "4.3.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha1-dVTj1XIQmofh8/U/an2F0bGU9MU=" + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=", + "requires": { + "p-try": "2.2.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -787,6 +2102,15 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -815,6 +2139,25 @@ "util-deprecate": "1.0.2" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -842,6 +2185,35 @@ "uuid": "3.3.2" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=" + }, "retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -852,6 +2224,14 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -867,6 +2247,50 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==" }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -875,6 +2299,146 @@ "is-arrayish": "0.3.2" } }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "sshpk": { "version": "1.14.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", @@ -896,11 +2460,57 @@ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, "superagent": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.0.2.tgz", @@ -971,6 +2581,14 @@ } } }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha1-ds/nQs8fQbubHCmtAwaMBbTA5Ao=", + "requires": { + "has-flag": "3.0.0" + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -981,6 +2599,44 @@ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -1009,11 +2665,94 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "optional": true }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=" + }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=" + }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -1047,6 +2786,27 @@ "extsprintf": "1.3.0" } }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", + "requires": { + "string-width": "2.1.1" + } + }, "winston": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", @@ -1140,6 +2900,53 @@ } } }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, "xml2js": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", @@ -1153,6 +2960,49 @@ "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=" + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha1-BfWZe2CWR7ZPZrgeO0sQo2jnrRM=", + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "3.0.0", + "get-caller-file": "1.0.3", + "os-locale": "3.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "4.0.0", + "yargs-parser": "11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha1-h5oIZZc7yp9rq1y987HGfsfTvPQ=", + "requires": { + "camelcase": "5.3.1", + "decamelize": "1.2.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha1-8rsqfoPLyHu5XI5XKCigbJrdbg0=", + "requires": { + "flat": "4.1.0", + "lodash": "4.17.11", + "yargs": "12.0.5" + } + }, "zen-observable": { "version": "0.8.9", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.9.tgz", diff --git a/package.json b/package.json index 2495394c9..89732fff0 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "author": "Luis-Fernando-Molina", "license": "ISC", "dependencies": { - "@superalgos/mqservice": "0.0.9", + "@superalgos/exchangegateway.js": "0.0.2", + "@superalgos/mqservice": "0.0.12", "apollo-boost": "^0.1.16", "assert": "^1.4.1", "axios": "^0.18.0", From a595cf34fef0592219192c71bd9ca0c96dfcf0bb Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 3 Apr 2019 20:17:56 +0200 Subject: [PATCH 72/73] Working with exchange gateway library --- SensorBotProcessMainLoop.js | 2 +- TradingBotProcessMainLoop.js | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SensorBotProcessMainLoop.js b/SensorBotProcessMainLoop.js index e8de93346..87a4ccf86 100644 --- a/SensorBotProcessMainLoop.js +++ b/SensorBotProcessMainLoop.js @@ -144,7 +144,7 @@ const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); - const EXCHANGE_API = require('@superalgos/exchangegateway.js'); + const EXCHANGE_API = require('@superalgos/exchangegateway'); const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies'); /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 277874228..f217949d9 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -163,7 +163,7 @@ /* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */ const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); - const EXCHANGE_API = require('@superalgos/exchangegateway.js'); + const EXCHANGE_API = require('@superalgos/exchangegateway'); const CONTEXT = require(ROOT_DIR + 'Context'); const ASSISTANT = require(ROOT_DIR + 'Assistant'); const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); diff --git a/package-lock.json b/package-lock.json index 8a9b5bfc4..6727351a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,10 +4,10 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@superalgos/exchangegateway.js": { + "@superalgos/exchangegateway": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@superalgos/exchangegateway.js/-/exchangegateway.js-0.0.1.tgz", - "integrity": "sha512-RgMtDIPayDu2B7+9z/F/FwFcULVmoWGCrXmx63vJFzePmzsaVhtUisZC/qc2b6tbj88VCW1qLiwGh3D55Q7rAA==", + "resolved": "https://registry.npmjs.org/@superalgos/exchangegateway/-/exchangegateway-0.0.1.tgz", + "integrity": "sha512-x1u+yOwcADT4741Zmm6z3fk580JmP13FlebpUK0uw6fJ5B77DolqwwIi7Tvzk9ipJVB6IVejcqsgndeuumx8Hw==", "requires": { "apollo-boost": "0.1.16", "assert": "1.4.1", diff --git a/package.json b/package.json index 89732fff0..75de40d50 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "author": "Luis-Fernando-Molina", "license": "ISC", "dependencies": { - "@superalgos/exchangegateway.js": "0.0.2", + "@superalgos/exchangegateway": "0.0.1", "@superalgos/mqservice": "0.0.12", "apollo-boost": "^0.1.16", "assert": "^1.4.1", From c866a730d05964a5a55579d4f5d935b012002fbc Mon Sep 17 00:00:00 2001 From: Matias Date: Thu, 4 Apr 2019 22:31:19 +0200 Subject: [PATCH 73/73] Returning the position --- Assistant.js | 82 ++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/Assistant.js b/Assistant.js index 28f5c0065..7300aa196 100644 --- a/Assistant.js +++ b/Assistant.js @@ -1,13 +1,13 @@ exports.newAssistant = function newAssistant(BOT, logger, UTILITIES) { - /* + /* This module allows trading bots to execute actions on the exchange, and also on its current recorded state. */ const MODULE_NAME = "Assistant"; - + var nodemailer = require('nodemailer'); let bot = BOT; @@ -23,13 +23,13 @@ getInvestment: getInvestment, getProfits: getProfits, getCombinedProfits: getCombinedProfits, - getROI: getROI, + getROI: getROI, getMarketRate: getMarketRate, getTicker: getTicker, sendMessage: sendMessage, rememberThis: rememberThis, remindMeOf: remindMeOf, - truncDecimals: truncDecimals, + truncDecimals: truncDecimals, sendEmail: sendEmail, addExtraData: addExtraData }; @@ -37,12 +37,12 @@ let utilities = UTILITIES.newCloudUtilities(bot, logger); let exchangePositions = []; // These are the open positions at the exchange at the account the bot is authorized to use. - let openPositions = []; // These are the open positions the bot knows it made by itself. + let openPositions = []; // These are the open positions the bot knows it made by itself. let context; let exchangeAPI; - let marketRate; + let marketRate; let ticker; return thisObject; @@ -100,7 +100,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getMarketRateFromExchange -> onTicker -> Entering function."); } - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getMarketRateFromExchange -> onTicker -> We could not get the Market Price now."); } @@ -119,7 +119,7 @@ logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromExchange -> onTicker -> err = " + err.message); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } - } + } } catch (err) { logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromExchange -> err = " + err.message); @@ -405,7 +405,7 @@ callBack(global.DEFAULT_FAIL_RESPONSE); } } - + function ordersExecutionCheck(callBack) { try { @@ -534,9 +534,9 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> pPositionId = " + pPositionId); } /* - + Given one position, we request all the associated trades to it. - + */ switch (bot.startMode) { @@ -562,9 +562,9 @@ let thisPosition = context.executionContext.positions[i]; if (thisPosition.id === pPositionId) { - + let feeRate = 0.002; // Default backtesting fee simulation - + let trade = { id: Math.trunc(Math.random(1) * 1000000), type: thisPosition.type, @@ -574,7 +574,7 @@ fee: thisObject.truncDecimals(feeRate).toString(), date: (new Date()).valueOf() } - + trades.push(trade); onResponse(global.DEFAULT_OK_RESPONSE, trades); @@ -646,11 +646,11 @@ if (global.LOG_CONTROL[MODULE_NAME].logContent === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasExecuted -> pTrades = " + JSON.stringify(pTrades)); } /* - + To confirm everything is ok, we will add all the amounts on trades asociated to the order and they must be equal to the one on file. Otherwise something very strange could have happened, in which case we will halt the bot execution. - + */ let sumAssetA = 0; @@ -661,7 +661,7 @@ sumAssetA = sumAssetA + thisObject.truncDecimals(trade.amountA); sumAssetB = sumAssetB + thisObject.truncDecimals(trade.amountB); } - + sumAssetA = thisObject.truncDecimals(sumAssetA); sumAssetB = thisObject.truncDecimals(sumAssetB); @@ -677,9 +677,9 @@ } /* - + Confirmed that order was executed. Next thing to do is to remember the trades and change its status. - + */ position.status = "executed"; @@ -716,27 +716,27 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> Entering function."); } /* - + To confirm everything is ok, we will add all the amounts on trades plus the remaining amounts at the order at the exchange and they must be equal to the one on file. Otherwise an inconsistent state has been detected, in which case we will halt the bot execution. - + */ let sumAssetA = 0; let sumAssetB = 0; - + for (let k = 0; k < pTrades.length; k++) { let trade = pTrades[k]; sumAssetA = sumAssetA + thisObject.truncDecimals(trade.amountA); sumAssetB = sumAssetB + thisObject.truncDecimals(trade.amountB); } - + /* To this we add the current position amounts. */ - + sumAssetA = sumAssetA + thisObject.truncDecimals(exchangePosition.amountA); sumAssetB = sumAssetB + thisObject.truncDecimals(exchangePosition.amountB); - + sumAssetA = thisObject.truncDecimals(sumAssetA); sumAssetB = thisObject.truncDecimals(sumAssetB); @@ -760,16 +760,16 @@ logger.write(MODULE_NAME, "[INFO] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> sumAssetB = " + sumAssetB); logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> Cannot confirm that a partial execution was done well."); - + /* There are diferences on the responses between the getPosition and getTrades that causes some issues, let's retry. */ callBack(global.DEFAULT_RETRY_RESPONSE); return; } /* - + Confirmed that order was partially executed. Next thing to do is to remember the trades and the new position. - + */ position.amountA = exchangePosition.amountA; @@ -818,8 +818,8 @@ let assetB = 0; if (trade.type === 'buy') { - - /* + + /* The fee received at each trade is the factor by which if we multiply asset B, we get the amount of Asset B extracted as fees by the exchange. This happens with each individual trade. Remeber that one order can potentially be executed with 1 to many trades. @@ -842,7 +842,7 @@ if (trade.type === 'sell') { - /* + /* The fee received at each trade is the factor by which if we multiply asset A, we get the amount of Asset A extracted as fees by the exchange. This happens with each individual trade. Remeber that one order can potentially be executed with 1 to many trades. @@ -861,7 +861,7 @@ /* Not the available balance for asset B is not affected since it was already reduced when the order was placed. */ - } + } } } catch (err) { @@ -1041,7 +1041,7 @@ context.newHistoryRecord.newPositions++; - recalculateRateAverages(); + recalculateRateAverages(); /* Recalculate Available Balances */ @@ -1049,7 +1049,7 @@ context.executionContext.availableBalance.assetA = thisObject.truncDecimals(context.executionContext.availableBalance.assetA - pAmountA); context.newHistoryRecord.lastBuyRate = pRate; - } + } if (position.type === 'sell') { @@ -1057,7 +1057,7 @@ context.newHistoryRecord.lastSellRate = pRate; } - callBackFunction(global.DEFAULT_OK_RESPONSE); + callBackFunction(global.DEFAULT_OK_RESPONSE, position); return; } break; @@ -1180,9 +1180,9 @@ context.newHistoryRecord.movedPositions++; - recalculateRateAverages(); + recalculateRateAverages(); - callBackFunction(global.DEFAULT_OK_RESPONSE); + callBackFunction(global.DEFAULT_OK_RESPONSE, newPosition); } break; case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. @@ -1317,7 +1317,7 @@ return JSON.parse(JSON.stringify(ROI)); } - + function getMarketRate() { return marketRate; } @@ -1358,10 +1358,10 @@ return context.executionContext.remember[pKey]; } - + function sendEmail(pTitle, pBody, pTo) { logger.write(MODULE_NAME, "[WARN] sendEmail -> Send emails is currently disabled."); - return; + return; } function addExtraData(pExtraDataArray) { @@ -1376,4 +1376,4 @@ return parseFloat(parseFloat(pFloatValue).toFixed(pDecimals)); } -}; \ No newline at end of file +};