diff --git a/AAWebPlatform.njsproj b/AAWebPlatform.njsproj index bd33a2d0c..8a7d5eba3 100644 --- a/AAWebPlatform.njsproj +++ b/AAWebPlatform.njsproj @@ -45,6 +45,9 @@ Code + + Code + Code diff --git a/Dashboard.js b/Dashboard.js index 6df667f92..0c62151ed 100644 --- a/Dashboard.js +++ b/Dashboard.js @@ -5,6 +5,35 @@ var canvas; var markets; let ecosystem = newEcosystem(); +let marketFilesPeriods = + '[' + + '[' + 24 * 60 * 60 * 1000 + ',' + '"24-hs"' + ']' + ',' + + '[' + 12 * 60 * 60 * 1000 + ',' + '"12-hs"' + ']' + ',' + + '[' + 8 * 60 * 60 * 1000 + ',' + '"08-hs"' + ']' + ',' + + '[' + 6 * 60 * 60 * 1000 + ',' + '"06-hs"' + ']' + ',' + + '[' + 4 * 60 * 60 * 1000 + ',' + '"04-hs"' + ']' + ',' + + '[' + 3 * 60 * 60 * 1000 + ',' + '"03-hs"' + ']' + ',' + + '[' + 2 * 60 * 60 * 1000 + ',' + '"02-hs"' + ']' + ',' + + '[' + 1 * 60 * 60 * 1000 + ',' + '"01-hs"' + ']' + ']'; + +marketFilesPeriods = JSON.parse(marketFilesPeriods); + +let dailyFilePeriods = + '[' + + '[' + 45 * 60 * 1000 + ',' + '"45-min"' + ']' + ',' + + '[' + 40 * 60 * 1000 + ',' + '"40-min"' + ']' + ',' + + '[' + 30 * 60 * 1000 + ',' + '"30-min"' + ']' + ',' + + '[' + 20 * 60 * 1000 + ',' + '"20-min"' + ']' + ',' + + '[' + 15 * 60 * 1000 + ',' + '"15-min"' + ']' + ',' + + '[' + 10 * 60 * 1000 + ',' + '"10-min"' + ']' + ',' + + '[' + 05 * 60 * 1000 + ',' + '"05-min"' + ']' + ',' + + '[' + 04 * 60 * 1000 + ',' + '"04-min"' + ']' + ',' + + '[' + 03 * 60 * 1000 + ',' + '"03-min"' + ']' + ',' + + '[' + 02 * 60 * 1000 + ',' + '"02-min"' + ']' + ',' + + '[' + 01 * 60 * 1000 + ',' + '"01-min"' + ']' + ']'; + +dailyFilePeriods = JSON.parse(dailyFilePeriods); + var viewPort = newViewPort(); diff --git a/Ecosystem.js b/Ecosystem.js index 355ab03e6..5f7fccc0a 100644 --- a/Ecosystem.js +++ b/Ecosystem.js @@ -50,7 +50,7 @@ function newEcosystem() { }, products: { product: [{ - codeName: "Candles", + codeName: "Market Candles", displayName: "Market Candles per Period", description: "A set of files per period that contains all candles of one whole market.", storageAccount: "aaolivia", @@ -67,7 +67,7 @@ function newEcosystem() { }, layers: { layer: [{ - codeName: "Candlesticks", + codeName: "Market Candlesticks", displayName: "Candlesticks", exchangeList: ["Poloniex"], validPeriods: ["24-hs", "12-hs", "06-hs", "03-hs", "01-hs"], @@ -87,7 +87,7 @@ function newEcosystem() { }] } }, { - codeName: "Volumes", + codeName: "Market Volumes", displayName: "Market Volumes per Period", description: "A set of files per period that contains all volumes of one whole market.", storageAccount: "aaolivia", @@ -104,7 +104,7 @@ function newEcosystem() { }, layers: { layer: [{ - codeName: "Volumes", + codeName: "Market Volumes", displayName: "Volumes", exchangeList: ["Poloniex"], validPeriods: ["24-hs", "12-hs", "06-hs", "03-hs", "01-hs"], @@ -123,7 +123,81 @@ function newEcosystem() { } }] } - }] + }, { + codeName: "Daily Candles", + displayName: "Daily Candles per Period", + description: "A set of files per period that contains all candles of one whole market.", + storageAccount: "aaolivia", + filePath: "@Exchange/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day", + fileName: "@AssetA_@AssetB.json", + exchangeList: { + exchange: [{ + name: "Poloniex", + datetimeRange: { + minDatetime: "2017-02-19 19:15:00.000 GMT+0000", + maxDatetime: "2018-02-13 10:10:00.000 GMT+0000" + } + }] + }, + layers: { + layer: [{ + codeName: "Daily Candlesticks", + displayName: "Candlesticks", + exchangeList: ["Poloniex"], + validPeriods: ["30-min", "15-min", "10-min", "05-min", "01-min"], + plotter: { + devTeam: "AAMasters", + repo: "AAOlivia-Plotter", + moduleName: "Candlesticks", + target: "Timeline", + dependencies: { + dependency: { + devTeam: "AAMasters", + repo: "Plotters-Utilities", + moduleName: "Candlesticks" + } + } + } + }] + } + }, { + codeName: "Daily Volumes", + displayName: "Daily Volumes per Period", + description: "A set of files per period that contains all volumes of one whole market.", + storageAccount: "aaolivia", + filePath: "@Exchange/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day", + fileName: "@AssetA_@AssetB.json", + exchangeList: { + exchange: [{ + name: "Poloniex", + datetimeRange: { + minDatetime: "2017-02-19 19:15:00.000 GMT+0000", + maxDatetime: "2018-02-13 10:10:00.000 GMT+0000" + } + }] + }, + layers: { + layer: [{ + codeName: "Daily Volumes", + displayName: "Volumes", + exchangeList: ["Poloniex"], + validPeriods: ["30-min", "15-min", "10-min", "05-min", "01-min"], + plotter: { + devTeam: "AAMasters", + repo: "AAOlivia-Plotter", + moduleName: "Volumes", + target: "Timeline", + dependencies: { + dependency: { + devTeam: "AAMasters", + repo: "Plotters-Utilities", + moduleName: "Volumes" + } + } + } + }] + } + }] }, processes: { diff --git a/FileCache.js b/FileCache.js index 07c7a3013..90783d31b 100644 --- a/FileCache.js +++ b/FileCache.js @@ -1,52 +1,20 @@  function newFileCache() { - let marketFilesPeriods = - '[' + - '[' + 24 * 60 * 60 * 1000 + ',' + '"24-hs"' + ']' + ',' + - '[' + 12 * 60 * 60 * 1000 + ',' + '"12-hs"' + ']' + ',' + - '[' + 8 * 60 * 60 * 1000 + ',' + '"08-hs"' + ']' + ',' + - '[' + 6 * 60 * 60 * 1000 + ',' + '"06-hs"' + ']' + ',' + - '[' + 4 * 60 * 60 * 1000 + ',' + '"04-hs"' + ']' + ',' + - '[' + 3 * 60 * 60 * 1000 + ',' + '"03-hs"' + ']' + ',' + - '[' + 2 * 60 * 60 * 1000 + ',' + '"02-hs"' + ']' + ',' + - '[' + 1 * 60 * 60 * 1000 + ',' + '"01-hs"' + ']' + ']'; - - marketFilesPeriods = JSON.parse(marketFilesPeriods); - - let dailyFilePeriods = - '[' + - '[' + 45 * 60 * 1000 + ',' + '"45-min"' + ']' + ',' + - '[' + 40 * 60 * 1000 + ',' + '"40-min"' + ']' + ',' + - '[' + 30 * 60 * 1000 + ',' + '"30-min"' + ']' + ',' + - '[' + 20 * 60 * 1000 + ',' + '"20-min"' + ']' + ',' + - '[' + 15 * 60 * 1000 + ',' + '"15-min"' + ']' + ',' + - '[' + 10 * 60 * 1000 + ',' + '"10-min"' + ']' + ',' + - '[' + 05 * 60 * 1000 + ',' + '"05-min"' + ']' + ',' + - '[' + 04 * 60 * 1000 + ',' + '"04-min"' + ']' + ',' + - '[' + 03 * 60 * 1000 + ',' + '"03-min"' + ']' + ',' + - '[' + 02 * 60 * 1000 + ',' + '"02-min"' + ']' + ',' + - '[' + 01 * 60 * 1000 + ',' + '"01-min"' + ']' + ']'; - - dailyFilePeriods = JSON.parse(dailyFilePeriods); - let fileCache = { - getMarketFile: getMarketFile, - getFileCursor: getFileCursor, - setDatetime: setDatetime, + getFile: getFile, initialize: initialize } let fileCloud; - let marketFiles = new Map; - let fileCursors = new Map; + let files = new Map; let datetime; return fileCache; - function initialize(pTeamCodeName, pBotCodeName, pProductCodeName, pLayerCodeName, pExchange, pMarket, pDatetime, callBackFunction) { + function initialize(pTeamCodeName, pBotCodeName, pProductCodeName, pLayerCodeName, pExchange, pMarket, callBackFunction) { let product = ecosystem.getProduct(ecosystem.getBot(ecosystem.getTeam(pTeamCodeName), pBotCodeName), pProductCodeName); @@ -75,6 +43,8 @@ function newFileCache() { fileCloud = newFileCloud(); fileCloud.initialize(pTeamCodeName, pBotCodeName); + /* Now we will get the market files */ + for (i = 0; i < marketFilesPeriods.length; i++) { let periodTime = marketFilesPeriods[i][0]; @@ -82,11 +52,11 @@ function newFileCache() { if (layer.validPeriods.includes(periodName) === true) { - fileCloud.getMarketFile(product, exchange, pMarket, periodName, onFileReceived); + fileCloud.getFile(product, exchange, pMarket, periodName, undefined, onFileReceived); function onFileReceived(file) { - marketFiles.set(periodTime, file); + files.set(periodTime, file); callBackFunction(); // Note that the call back is called for every file loaded. @@ -94,24 +64,10 @@ function newFileCache() { } } } - - function getMarketFile(pPeriod) { + function getFile(pPeriod) { - return marketFiles.get(pPeriod); - - } - - - function getFileCursor(pPeriod) { - - return fileCursors.get(pPeriod); - - } - - function setDatetime(newDatetime) { - - datetime = newDatetime; + return files.get(pPeriod); } diff --git a/FileCloud.js b/FileCloud.js index cae04e5af..a8c4a324e 100644 --- a/FileCloud.js +++ b/FileCloud.js @@ -2,7 +2,7 @@ function newFileCloud() { var fileCloud = { - getMarketFile: getMarketFile, + getFile: getFile, initialize: initialize }; @@ -18,7 +18,7 @@ function newFileCloud() { } - function getMarketFile(pProduct, pExchange, pMarket, pPeriodName, callBackFunction) { + function getFile(pProduct, pExchange, pMarket, pPeriodName, pDatetime, callBackFunction) { let fileName = pProduct.fileName; let filePath = pProduct.filePath; @@ -29,6 +29,14 @@ function newFileCloud() { filePath = filePath.replace("@Exchange", pExchange.name); filePath = filePath.replace("@Period", pPeriodName); + if (pDatetime !== undefined) { + + filePath = filePath.replace("@Year", pDatetime.getUTCFullYear()); + filePath = filePath.replace("@Month", pad(pDatetime.getUTCMonth() + 1, 2)); + filePath = filePath.replace("@Month", pad(pDatetime.getUTCDate(), 2)); + + } + fileService.getFileToText('data', filePath, fileName, undefined, onFileReceived); function onFileReceived(err, text, response) { @@ -56,6 +64,8 @@ function newFileCloud() { } } + + } diff --git a/FileCursor.js b/FileCursor.js index 5f6d3244d..7085c4bb1 100644 --- a/FileCursor.js +++ b/FileCursor.js @@ -1,33 +1,35 @@  function newFileCursor() { - - - let dailyFiles = new Map; - let cursorDate = new Date(INITIAL_DATE); + let files = new Map; + let cursorDate; let fileCursor = { setDatetime: setDatetime, - dailyFiles: undefined, + files: undefined, initialize: initialize } - fileCursor.dailyFiles = dailyFiles; + fileCursor.files = files; + + let cursorSize = 3; let market; let exchange; - let cursorSize = 3; - - let server = newFileServer(); + let fileCloud; + let product; + let periodName; return fileCursor; - function initialize(pExchange, pMarket, callBackFunction) { + function initialize(pFileCloud, pProduct, pExchange, pMarket, pPeriodName, pCursorDate, callBackFunction) { market = pMarket; exchange = pExchange; - - server.initialize(); + fileCloud = pFileCloud; + product = pProduct; + periodName = pPeriodName; + cursorDate = pCursorDate; getFiles(callBackFunction); @@ -56,8 +58,9 @@ function newFileCursor() { function getNextFile() { let targetDate = new Date(cursorDate); - targetDate.setDate(targetDate.getDate() + j); + targetDate.setUTCDate(targetDate.getUTCDate() + j); + /* Small algorith to allow load first the current date, then alternate between the most forwad and the most backwards ones. */ if (j === 0) { j++; } else { if (j < 0) { @@ -80,9 +83,9 @@ function newFileCursor() { } else { - if (fileCursor.dailyFiles.get(dateString) === undefined) { + if (fileCursor.files.get(dateString) === undefined) { // We dont reload files we already have. - server.getDailyFile(exchange, market, targetDate, newDailyFilesReady) + fileCloud.getFile(product, exchange, market, periodName, targetDate, onFileReceived); } else { @@ -93,9 +96,9 @@ function newFileCursor() { } - function newDailyFilesReady(dailyFileReceived) { + function onFileReceived(file) { - fileCursor.dailyFiles.set(dateString, dailyFileReceived); + fileCursor.files.set(dateString, file); controlLoop(); @@ -104,19 +107,11 @@ function newFileCursor() { function controlLoop() { - if (j === 3) { // We call the callBack after we have the first few files. + if (callBackFunction !== undefined) { - if (callBackFunction !== undefined) { + callBackFunction(); - callBackFunction(); - - if (market === INITIAL_DEFAULT_MARKET) { // This is when we dont need a splash screen anymore! - - splashScreenNeeded = false; - - } - - } + splashScreenNeeded = false; // This is when we dont need a splash screen anymore! } @@ -138,13 +133,13 @@ function newFileCursor() { let minDate = date.valueOf() - cursorSize / 2 * 24 * 60 * 60 * 1000; let maxDate = date.valueOf() + cursorSize / 2 * 24 * 60 * 60 * 1000; - for (let key of fileCursor.dailyFiles.keys()) { + for (let key of fileCursor.files.keys()) { let keyDate = new Date(key); if (keyDate.valueOf() < minDate || keyDate.valueOf() > maxDate) { - fileCursor.dailyFiles.delete(key); + fileCursor.files.delete(key); } diff --git a/FileCursorCache.js b/FileCursorCache.js new file mode 100644 index 000000000..84745c6eb --- /dev/null +++ b/FileCursorCache.js @@ -0,0 +1,89 @@ + +function newFileCursorCache() { + + let fileCursorCache = { + getFileCursor: getFileCursor, + setDatetime: setDatetime, + initialize: initialize + } + + let fileCloud; + + let marketFiles = new Map; + let fileCursors = new Map; + + let datetime; + + return fileCursorCache; + + function initialize(pTeamCodeName, pBotCodeName, pProductCodeName, pLayerCodeName, pExchange, pMarket, pDatetime, callBackFunction) { + + let product = ecosystem.getProduct(ecosystem.getBot(ecosystem.getTeam(pTeamCodeName), pBotCodeName), pProductCodeName); + + if (product === undefined) { + + throw "Product not found at this bot of the ecosystem! - pTeamCodeName = " + pTeamCodeName + ", pBotCodeName = " + pBotCodeName + ", pProductCodeName = " + pProductCodeName; + + } + + let exchange = ecosystem.getExchange(product, pExchange); + + if (exchange === undefined) { + + throw "Exchange not supoorted by this product of the ecosystem! - pTeamCodeName = " + pTeamCodeName + ", pBotCodeName = " + pBotCodeName + ", pProductCodeName = " + pProductCodeName + ", pExchange = " + pExchange; + + } + + let layer = ecosystem.getLayer(product, pLayerCodeName); + + if (layer === undefined) { + + throw "Layer not found at this product of the ecosystem! - pTeamCodeName = " + pTeamCodeName + ", pBotCodeName = " + pBotCodeName + ", pProductCodeName = " + pProductCodeName + ", pLayerCodeName = " + pLayerCodeName; + + } + + fileCloud = newFileCloud(); + fileCloud.initialize(pTeamCodeName, pBotCodeName); + + /* Now we will get the daily files */ + + for (i = 0; i < dailyFilePeriods.length; i++) { + + let periodTime = dailyFilePeriods[i][0]; + let periodName = dailyFilePeriods[i][1]; + + if (layer.validPeriods.includes(periodName) === true) { + + let fileCursor = newFileCursos(); + fileCursor.initialize(fileCloud, product, exchange, pMarket, periodName, pDatetime, onFileReceived); + + fileCursors.set(periodTime, fileCursor); + + function onFileReceived() { + + callBackFunction(); // Note that the call back is called for every file loaded at each cursor. + + } + } + } + } + + function getFileCursor(pPeriod) { + + return fileCursors.get(pPeriod); + + } + + function setDatetime(newDatetime) { + + datetime = newDatetime; + + fileCursors.forEach(setDatetime) + + function setDatetimeToEach(value, key, map) { + + value.setDatetime(newDatetime); + + } + } +} \ No newline at end of file