diff --git a/Conditions.js b/Conditions.js index 7aad536a4..232ef1059 100644 --- a/Conditions.js +++ b/Conditions.js @@ -460,7 +460,7 @@ let maxValue = { x: MAX_PLOTABLE_DATE.valueOf(), - y: nextPorwerOf10(getMaxRate()) / 4 // TODO: This 4 is temporary + y: nextPorwerOf10(USDT_BTC_HTH) / 4 // TODO: This 4 is temporary }; @@ -471,25 +471,6 @@ thisObject.container.frame.height ); - function getMaxRate() { - - if (INFO_LOG === true) { logger.write("[INFO] recalculateScale -> getMaxRate -> Entering function."); } - - let maxValue = 0; - - for (let i = 0; i < marketFile.length; i++) { - - let currentMax = 25000; // TODO Fix this, since when there are not records above 10k the scales is dissincronized with the scale of the candles. marketFile[i][3]; // 3 = rate. - - if (maxValue < currentMax) { - maxValue = currentMax; - } - } - - return maxValue; - - } - } catch (err) { if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err.stack); } diff --git a/Project.njsproj b/Project.njsproj index f3ac2708b..13475abfd 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -26,6 +26,12 @@ Code + + Code + + + Code + diff --git a/Strategies.js b/Strategies.js new file mode 100644 index 000000000..8e2e663f9 --- /dev/null +++ b/Strategies.js @@ -0,0 +1,675 @@ +function newAAMastersPlottersTradingSimulationStrategies() { + + const MODULE_NAME = "Strategies Plotter"; + const INFO_LOG = false; + const ERROR_LOG = true; + const INTENSIVE_LOG = false; + const logger = newWebDebugLog(); + logger.fileName = MODULE_NAME; + + let thisObject = { + + // Main functions and properties. + + initialize: initialize, + finalize: finalize, + container: undefined, + getContainer: getContainer, + setTimePeriod: setTimePeriod, + setDatetime: setDatetime, + draw: draw, + recalculateScale: recalculateScale, + + /* Events declared outside the plotter. */ + + onDailyFileLoaded: onDailyFileLoaded, + + // Secondary functions and properties. + + currentRecord: undefined + }; + + /* this is part of the module template */ + + let container = newContainer(); // Do not touch this 3 lines, they are just needed. + container.initialize(); + thisObject.container = container; + + let timeLineCoordinateSystem = newTimeLineCoordinateSystem(); // Needed to be able to plot on the timeline, otherwise not. + + let timePeriod; // This will hold the current Time Period the user is at. + let datetime; // This will hold the current Datetime the user is at. + + let marketFile; // This is the current Market File being plotted. + let fileCursor; // This is the current File Cursor being used to retrieve Daily Files. + + let marketFiles; // This object will provide the different Market Files at different Time Periods. + let dailyFiles; // This object will provide the different File Cursors at different Time Periods. + + /* these are module specific variables: */ + + let strategies = []; + + let strategyImages = []; + + return thisObject; + + function finalize() { + try { + + if (INFO_LOG === true) { logger.write("[INFO] finalize -> Entering function."); } + + /* Stop listening to the necesary events. */ + + viewPort.eventHandler.stopListening("Zoom Changed", onZoomChanged); + viewPort.eventHandler.stopListening("Offset Changed", onOffsetChanged); + marketFiles.eventHandler.stopListening("Files Updated", onFilesUpdated); + canvas.eventHandler.stopListening("Drag Finished", onDragFinished); + thisObject.container.eventHandler.stopListening('Dimmensions Changed') + + /* Destroyd References */ + + marketFiles = undefined; + dailyFiles = undefined; + + datetime = undefined; + timePeriod = undefined; + + marketFile = undefined; + fileCursor = undefined; + + strategyImages = undefined; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err = " + err.stack); } + } + } + + function initialize(pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] initialize -> Entering function."); } + + /* Store the information received. */ + + marketFiles = pStorage.marketFiles[0]; + dailyFiles = pStorage.dailyFiles[0]; + + datetime = pDatetime; + timePeriod = pTimePeriod; + + /* We need a Market File in order to calculate the Y scale, since this scale depends on actual data. */ + + marketFile = marketFiles.getFile(ONE_DAY_IN_MILISECONDS); // This file is the one processed faster. + + recalculateScale(); + + /* Now we set the right files according to current Period. */ + + marketFile = marketFiles.getFile(pTimePeriod); + fileCursor = dailyFiles.getFileCursor(pTimePeriod); + + /* Listen to the necesary events. */ + + viewPort.eventHandler.listenToEvent("Zoom Changed", onZoomChanged); + viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged); + marketFiles.eventHandler.listenToEvent("Files Updated", onFilesUpdated); + canvas.eventHandler.listenToEvent("Drag Finished", onDragFinished); + + /* Get ready for plotting. */ + + recalculate(); + + /* Ready for when dimmension changes. */ + + thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () { + recalculateScale() + recalculate(); + }) + + for (let i = 1; i < 15; i++) { + let strategyImage = loadEmoji("Symbols/Emoji Symbols-" + (112 + i) + ".png"); + strategyImages.push(strategyImage); + } + + callBackFunction(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err.stack); } + } + } + + function getContainer(point) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] getContainer -> Entering function."); } + + let container; + + /* First we check if this point is inside this space. */ + + if (this.container.frame.isThisPointHere(point) === true) { + + return this.container; + + } else { + + /* This point does not belong to this space. */ + + return undefined; + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] getContainer -> err = " + err.stack); } + } + } + + function onFilesUpdated() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onFilesUpdated -> Entering function."); } + + let newMarketFile = marketFiles.getFile(timePeriod); + + if (newMarketFile !== undefined) { + + marketFile = newMarketFile; + recalculate(); + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onFilesUpdated -> err = " + err.stack); } + } + } + + function setTimePeriod(pTimePeriod) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] setTimePeriod -> Entering function."); } + + if (timePeriod !== pTimePeriod) { + + timePeriod = pTimePeriod; + + if (timePeriod >= _1_HOUR_IN_MILISECONDS) { + + let newMarketFile = marketFiles.getFile(pTimePeriod); + + if (newMarketFile !== undefined) { + + marketFile = newMarketFile; + recalculate(); + } + + } else { + + let newFileCursor = dailyFiles.getFileCursor(pTimePeriod); + + fileCursor = newFileCursor; // In this case, we explicitly want that if there is no valid cursor, we invalidate the data and show nothing. + recalculate(); + + } + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err.stack); } + } + } + + function setDatetime(pDatetime) { + + if (INFO_LOG === true) { logger.write("[INFO] setDatetime -> Entering function."); } + + datetime = pDatetime; + + } + + function onDailyFileLoaded(event) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onDailyFileLoaded -> Entering function."); } + + if (event.currentValue === event.totalValue) { + + /* This happens only when all of the files in the cursor have been loaded. */ + + recalculate(); + + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onDailyFileLoaded -> err = " + err.stack); } + } + } + + function draw() { + + try { + + if (INTENSIVE_LOG === true) { logger.write("[INFO] draw -> Entering function."); } + + this.container.frame.draw(); + + plotChart(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err.stack); } + } + } + + function recalculate() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculate -> Entering function."); } + + if (timePeriod >= _1_HOUR_IN_MILISECONDS) { + + recalculateUsingMarketFiles(); + + } else { + + recalculateUsingDailyFiles(); + + } + + thisObject.container.eventHandler.raiseEvent("Strategies Changed", strategies); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); } + } + } + + function recalculateUsingDailyFiles() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateUsingDailyFiles -> Entering function."); } + + if (fileCursor === undefined) { + strategies = []; + return; + } // We need to wait + + if (fileCursor.files.size === 0) { + strategies = []; + return; + } // We need to wait until there are files in the cursor + + let daysOnSides = getSideDays(timePeriod); + + let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem); + let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem); + + let dateDiff = rightDate.valueOf() - leftDate.valueOf(); + + let farLeftDate = new Date(leftDate.valueOf() - dateDiff * 1.5); + let farRightDate = new Date(rightDate.valueOf() + dateDiff * 1.5); + + let currentDate = new Date(farLeftDate.valueOf()); + + strategies = []; + + + + while (currentDate.valueOf() <= farRightDate.valueOf() + ONE_DAY_IN_MILISECONDS) { + + let stringDate = currentDate.getFullYear() + '-' + pad(currentDate.getMonth() + 1, 2) + '-' + pad(currentDate.getDate(), 2); + + let dailyFile = fileCursor.files.get(stringDate); + + if (dailyFile !== undefined) { + + for (let i = 0; i < dailyFile.length; i++) { + + let record = { + begin: undefined, + end: undefined, + status: undefined, + number: undefined, + beginRate: undefined, + endRate: undefined + }; + + record.begin = dailyFile[i][0]; + record.end = dailyFile[i][1]; + record.status = dailyFile[i][2]; + record.number = dailyFile[i][3]; + record.beginRate = dailyFile[i][4]; + record.endRate = dailyFile[i][5]; + + if (record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) { + + strategies.push(record); + + if (datetime.valueOf() >= record.begin && datetime.valueOf() <= record.end) { + + thisObject.currentRecord = record; + thisObject.container.eventHandler.raiseEvent("Current Strategy Changed", thisObject.currentRecord); + + } + } + } + } + + currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS); + } + + /* Lests check if all the visible screen is going to be covered by strategies. */ + + let lowerEnd = leftDate.valueOf(); + let upperEnd = rightDate.valueOf(); + + if (strategies.length > 0) { + + if (strategies[0].begin > lowerEnd || strategies[strategies.length - 1].end < upperEnd) { + + setTimeout(recalculate, 2000); + + //console.log("File missing while calculating strategies, scheduling a recalculation in 2 seconds."); + + } + } + + //console.log("Olivia > recalculateUsingDailyFiles > total strategies generated : " + strategies.length); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateUsingDailyFiles -> err = " + err.stack); } + } + } + + function recalculateUsingMarketFiles() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateUsingMarketFiles -> Entering function."); } + + if (marketFile === undefined) { return; } // Initialization not complete yet. + + let daysOnSides = getSideDays(timePeriod); + + let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem); + let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem); + + let dateDiff = rightDate.valueOf() - leftDate.valueOf(); + + leftDate = new Date(leftDate.valueOf() - dateDiff * 1.5); + rightDate = new Date(rightDate.valueOf() + dateDiff * 1.5); + + strategies = []; + + for (let i = 0; i < marketFile.length; i++) { + + let record = { + begin: undefined, + end: undefined, + status: undefined, + number: undefined, + beginRate: undefined, + endRate: undefined + }; + + record.begin = marketFile[i][0]; + record.end = marketFile[i][1]; + record.status = marketFile[i][2]; + record.number = marketFile[i][3]; + record.beginRate = marketFile[i][4]; + record.endRate = marketFile[i][5]; + + if (record.begin >= leftDate.valueOf() && record.end <= rightDate.valueOf()) { + + strategies.push(record); + + if (datetime.valueOf() >= record.begin && datetime.valueOf() <= record.end) { + + thisObject.currentRecord = record; + thisObject.container.eventHandler.raiseEvent("Current Strategy Changed", thisObject.currentRecord); + + } + } + } + + //console.log("Olivia > recalculateUsingMarketFiles > total strategies generated : " + strategies.length); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateUsingMarketFiles -> err = " + err.stack); } + } + } + + function recalculateScale() { + + try { + + if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated. + + let minValue = { + x: MIN_PLOTABLE_DATE.valueOf(), + y: 0 + }; + + let maxValue = { + x: MAX_PLOTABLE_DATE.valueOf(), + y: nextPorwerOf10(USDT_BTC_HTH) / 4 // TODO: This 4 is temporary + }; + + + timeLineCoordinateSystem.initialize( + minValue, + maxValue, + thisObject.container.frame.width, + thisObject.container.frame.height + ); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err.stack); } + } + } + + function plotChart() { + + try { + + let userPosition = getUserPosition() + let userPositionDate = userPosition.point.x + + thisObject.container.eventHandler.raiseEvent("Current Strategy Record Changed", undefined); + + let record; + + for (let i = 0; i < strategies.length; i++) { + + record = strategies[i]; + + let recordPoint1 = { + x: record.begin, + y: record.beginRate + }; + + let recordPoint2 = { + x: record.end, + y: record.endRate + }; + + let recordPoint3 = { + x: record.begin, + y: record.beginRate + }; + + let recordPoint4 = { + x: record.end, + y: record.endRate + }; + + recordPoint1 = timeLineCoordinateSystem.transformThisPoint(recordPoint1); + recordPoint2 = timeLineCoordinateSystem.transformThisPoint(recordPoint2); + recordPoint3 = timeLineCoordinateSystem.transformThisPoint(recordPoint3); + recordPoint4 = timeLineCoordinateSystem.transformThisPoint(recordPoint4); + + recordPoint1 = transformThisPoint(recordPoint1, thisObject.container); + recordPoint2 = transformThisPoint(recordPoint2, thisObject.container); + recordPoint3 = transformThisPoint(recordPoint3, thisObject.container); + recordPoint4 = transformThisPoint(recordPoint4, thisObject.container); + + if (recordPoint2.x < viewPort.visibleArea.bottomLeft.x || recordPoint1.x > viewPort.visibleArea.bottomRight.x) { + continue; + } + + recordPoint3.y = recordPoint1.y + 2000; + recordPoint4.y = recordPoint1.y + 2000; + + recordPoint1 = viewPort.fitIntoVisibleArea(recordPoint1); + recordPoint2 = viewPort.fitIntoVisibleArea(recordPoint2); + recordPoint3 = viewPort.fitIntoVisibleArea(recordPoint3); + recordPoint4 = viewPort.fitIntoVisibleArea(recordPoint4); + + let imageSize = 20; + let imageToDraw = strategyImages[record.number]; + + if (record.status === 1) { + /* Draw the line that represents the duration of closed strategy */ + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(recordPoint3.x + imageSize / 2, recordPoint3.y); + browserCanvasContext.lineTo(recordPoint4.x - imageSize / 2, recordPoint4.y); + + browserCanvasContext.closePath(); + + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', 1)'; + browserCanvasContext.lineWidth = 1 + + browserCanvasContext.stroke() + } + + + drawStick(recordPoint1, recordPoint3); + drawStick(recordPoint2, recordPoint4); + + if (imageToDraw.isLoaded === true) { + browserCanvasContext.drawImage(imageToDraw, recordPoint3.x - imageSize / 2, recordPoint3.y - imageSize / 2, imageSize, imageSize); + if (record.status === 1) { + browserCanvasContext.drawImage(imageToDraw, recordPoint4.x - imageSize / 2, recordPoint4.y - imageSize / 2, imageSize, imageSize); + } + } + + /* Send the current record to the panel */ + + if (userPositionDate >= record.begin && userPositionDate <= record.end) { + + let currentRecord = { + }; + thisObject.container.eventHandler.raiseEvent("Current Strategy Record Changed", currentRecord); + } + + function drawStick(point1, point2) { + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + + browserCanvasContext.closePath(); + + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', 0.25)'; + + if (userPositionDate >= record.begin && userPositionDate <= record.end) { + + /* highlight the current record */ + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 1)'; // Current record accroding to time + } + + browserCanvasContext.setLineDash([4, 3]) + browserCanvasContext.lineWidth = 0.2 + browserCanvasContext.stroke() + browserCanvasContext.setLineDash([0, 0]) + + } + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); } + } + } + + + function onZoomChanged(event) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onZoomChanged -> Entering function."); } + + recalculate(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onZoomChanged -> err = " + err.stack); } + } + } + + function onOffsetChanged() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onOffsetChanged -> Entering function."); } + + if (Math.random() * 100 > 95) { + + recalculate() + }; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onOffsetChanged -> err = " + err.stack); } + } + } + + function onDragFinished() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onDragFinished -> Entering function."); } + + recalculate(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onDragFinished -> err = " + err.stack); } + } + } +} + + + + + + + + + + + + + + + + + + + diff --git a/Trades.js b/Trades.js new file mode 100644 index 000000000..fc51c9229 --- /dev/null +++ b/Trades.js @@ -0,0 +1,671 @@ +function newAAMastersPlottersTradingSimulationTrades() { + + const MODULE_NAME = "Trades Plotter"; + const INFO_LOG = false; + const ERROR_LOG = true; + const INTENSIVE_LOG = false; + const logger = newWebDebugLog(); + logger.fileName = MODULE_NAME; + + let thisObject = { + + // Main functions and properties. + + initialize: initialize, + finalize: finalize, + container: undefined, + getContainer: getContainer, + setTimePeriod: setTimePeriod, + setDatetime: setDatetime, + draw: draw, + recalculateScale: recalculateScale, + + /* Events declared outside the plotter. */ + + onDailyFileLoaded: onDailyFileLoaded, + + // Secondary functions and properties. + + currentRecord: undefined + }; + + /* this is part of the module template */ + + let container = newContainer(); // Do not touch this 3 lines, they are just needed. + container.initialize(); + thisObject.container = container; + + let timeLineCoordinateSystem = newTimeLineCoordinateSystem(); // Needed to be able to plot on the timeline, otherwise not. + + let timePeriod; // This will hold the current Time Period the user is at. + let datetime; // This will hold the current Datetime the user is at. + + let marketFile; // This is the current Market File being plotted. + let fileCursor; // This is the current File Cursor being used to retrieve Daily Files. + + let marketFiles; // This object will provide the different Market Files at different Time Periods. + let dailyFiles; // This object will provide the different File Cursors at different Time Periods. + + /* these are module specific variables: */ + + let trades = []; + let headers; + + return thisObject; + + function finalize() { + try { + + if (INFO_LOG === true) { logger.write("[INFO] finalize -> Entering function."); } + + /* Stop listening to the necesary events. */ + + viewPort.eventHandler.stopListening("Zoom Changed", onZoomChanged); + viewPort.eventHandler.stopListening("Offset Changed", onOffsetChanged); + marketFiles.eventHandler.stopListening("Files Updated", onFilesUpdated); + canvas.eventHandler.stopListening("Drag Finished", onDragFinished); + thisObject.container.eventHandler.stopListening('Dimmensions Changed') + + /* Destroyd References */ + + marketFiles = undefined; + dailyFiles = undefined; + + datetime = undefined; + timePeriod = undefined; + + marketFile = undefined; + fileCursor = undefined; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err = " + err.stack); } + } + } + + function initialize(pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] initialize -> Entering function."); } + + /* Store the information received. */ + + marketFiles = pStorage.marketFiles[0]; + dailyFiles = pStorage.dailyFiles[0]; + + datetime = pDatetime; + timePeriod = pTimePeriod; + + /* We need a Market File in order to calculate the Y scale, since this scale depends on actual data. */ + + marketFile = marketFiles.getFile(ONE_DAY_IN_MILISECONDS); // This file is the one processed faster. + + recalculateScale(); + + /* Now we set the right files according to current Period. */ + + marketFile = marketFiles.getFile(pTimePeriod); + fileCursor = dailyFiles.getFileCursor(pTimePeriod); + + /* Listen to the necesary events. */ + + viewPort.eventHandler.listenToEvent("Zoom Changed", onZoomChanged); + viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged); + marketFiles.eventHandler.listenToEvent("Files Updated", onFilesUpdated); + canvas.eventHandler.listenToEvent("Drag Finished", onDragFinished); + + /* Get ready for plotting. */ + + recalculate(); + + /* Ready for when dimmension changes. */ + + thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () { + recalculateScale() + recalculate(); + }) + + callBackFunction(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err.stack); } + } + } + + function getContainer(point) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] getContainer -> Entering function."); } + + let container; + + /* First we check if this point is inside this space. */ + + if (this.container.frame.isThisPointHere(point) === true) { + + return this.container; + + } else { + + /* This point does not belong to this space. */ + + return undefined; + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] getContainer -> err = " + err.stack); } + } + } + + function onFilesUpdated() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onFilesUpdated -> Entering function."); } + + let newMarketFile = marketFiles.getFile(timePeriod); + + if (newMarketFile !== undefined) { + + marketFile = newMarketFile; + recalculate(); + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onFilesUpdated -> err = " + err.stack); } + } + } + + function setTimePeriod(pTimePeriod) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] setTimePeriod -> Entering function."); } + + if (timePeriod !== pTimePeriod) { + + timePeriod = pTimePeriod; + + if (timePeriod >= _1_HOUR_IN_MILISECONDS) { + + let newMarketFile = marketFiles.getFile(pTimePeriod); + + if (newMarketFile !== undefined) { + + marketFile = newMarketFile; + recalculate(); + } + + } else { + + let newFileCursor = dailyFiles.getFileCursor(pTimePeriod); + + fileCursor = newFileCursor; // In this case, we explicitly want that if there is no valid cursor, we invalidate the data and show nothing. + recalculate(); + + } + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err.stack); } + } + } + + function setDatetime(pDatetime) { + + if (INFO_LOG === true) { logger.write("[INFO] setDatetime -> Entering function."); } + + datetime = pDatetime; + + } + + function onDailyFileLoaded(event) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onDailyFileLoaded -> Entering function."); } + + if (event.currentValue === event.totalValue) { + + /* This happens only when all of the files in the cursor have been loaded. */ + + recalculate(); + + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onDailyFileLoaded -> err = " + err.stack); } + } + } + + function draw() { + + try { + + if (INTENSIVE_LOG === true) { logger.write("[INFO] draw -> Entering function."); } + + this.container.frame.draw(); + + plotChart(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err.stack); } + } + } + + function recalculate() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculate -> Entering function."); } + + if (timePeriod >= _1_HOUR_IN_MILISECONDS) { + + recalculateUsingMarketFiles(); + + } else { + + recalculateUsingDailyFiles(); + + } + + thisObject.container.eventHandler.raiseEvent("Trades Changed", trades); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); } + } + } + + function recalculateUsingDailyFiles() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateUsingDailyFiles -> Entering function."); } + + if (fileCursor === undefined) { + trades = []; + return; + } // We need to wait + + if (fileCursor.files.size === 0) { + trades = []; + return; + } // We need to wait until there are files in the cursor + + let daysOnSides = getSideDays(timePeriod); + + let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem); + let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem); + + let dateDiff = rightDate.valueOf() - leftDate.valueOf(); + + let farLeftDate = new Date(leftDate.valueOf() - dateDiff * 1.5); + let farRightDate = new Date(rightDate.valueOf() + dateDiff * 1.5); + + let currentDate = new Date(farLeftDate.valueOf()); + + trades = []; + + + + while (currentDate.valueOf() <= farRightDate.valueOf() + ONE_DAY_IN_MILISECONDS) { + + let stringDate = currentDate.getFullYear() + '-' + pad(currentDate.getMonth() + 1, 2) + '-' + pad(currentDate.getDate(), 2); + + let dailyFile = fileCursor.files.get(stringDate); + + if (dailyFile !== undefined) { + + for (let i = 0; i < dailyFile.length; i++) { + + let record = {}; + + record.begin = dailyFile[i][0]; + record.end = dailyFile[i][1]; + record.status = dailyFile[i][2]; + record.lastProfitPercent = dailyFile[i][3]; + record.beginRate = dailyFile[i][4]; + record.endRate = dailyFile[i][5]; + record.exitType = dailyFile[i][6]; + record.stopRate = dailyFile[i][7]; + + if (record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) { + + trades.push(record); + + if (datetime.valueOf() >= record.begin && datetime.valueOf() <= record.end) { + + thisObject.currentRecord = record; + thisObject.container.eventHandler.raiseEvent("Current Trade Changed", thisObject.currentRecord); + + } + } + } + } + + currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS); + } + + /* Lests check if all the visible screen is going to be covered by trades. */ + + let lowerEnd = leftDate.valueOf(); + let upperEnd = rightDate.valueOf(); + + if (trades.length > 0) { + + if (trades[0].begin > lowerEnd || trades[trades.length - 1].end < upperEnd) { + + setTimeout(recalculate, 2000); + + //console.log("File missing while calculating trades, scheduling a recalculation in 2 seconds."); + + } + } + + //console.log("Olivia > recalculateUsingDailyFiles > total trades generated : " + trades.length); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateUsingDailyFiles -> err = " + err.stack); } + } + } + + function recalculateUsingMarketFiles() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateUsingMarketFiles -> Entering function."); } + + if (marketFile === undefined) { return; } // Initialization not complete yet. + + let daysOnSides = getSideDays(timePeriod); + + let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem); + let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem); + + let dateDiff = rightDate.valueOf() - leftDate.valueOf(); + + leftDate = new Date(leftDate.valueOf() - dateDiff * 1.5); + rightDate = new Date(rightDate.valueOf() + dateDiff * 1.5); + + trades = []; + + for (let i = 0; i < marketFile.length; i++) { + + let record = {}; + + record.begin = marketFile[i][0]; + record.end = marketFile[i][1]; + record.status = marketFile[i][2]; + record.lastProfitPercent = marketFile[i][3]; + record.beginRate = marketFile[i][4]; + record.endRate = marketFile[i][5]; + record.exitType = marketFile[i][6]; + record.stopRate = marketFile[i][7]; + + if (record.begin >= leftDate.valueOf() && record.end <= rightDate.valueOf()) { + + trades.push(record); + + if (datetime.valueOf() >= record.begin && datetime.valueOf() <= record.end) { + + thisObject.currentRecord = record; + thisObject.container.eventHandler.raiseEvent("Current Trade Changed", thisObject.currentRecord); + + } + } + } + + //console.log("Olivia > recalculateUsingMarketFiles > total trades generated : " + trades.length); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateUsingMarketFiles -> err = " + err.stack); } + } + } + + function recalculateScale() { + + try { + + if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated. + + let minValue = { + x: MIN_PLOTABLE_DATE.valueOf(), + y: 0 + }; + + let maxValue = { + x: MAX_PLOTABLE_DATE.valueOf(), + y: nextPorwerOf10(USDT_BTC_HTH) / 4 // TODO: This 4 is temporary + }; + + + timeLineCoordinateSystem.initialize( + minValue, + maxValue, + thisObject.container.frame.width, + thisObject.container.frame.height + ); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err.stack); } + } + } + + function plotChart() { + + try { + + let userPosition = getUserPosition() + let userPositionDate = userPosition.point.x + + thisObject.container.eventHandler.raiseEvent("Current Trade Record Changed", undefined); + + let record; + + for (let i = 0; i < trades.length; i++) { + + record = trades[i]; + + /* Send the current record to the panel */ + + if (userPositionDate >= record.begin && userPositionDate <= record.end) { + + let currentRecord = { + }; + thisObject.container.eventHandler.raiseEvent("Current Trade Record Changed", currentRecord); + } + + let recordPoint1 = { + x: record.begin, + y: record.beginRate + }; + + let recordPoint2 = { + x: record.end, + y: record.beginRate + }; + + let recordPoint3 = { + x: record.end, + y: record.endRate + }; + + let recordPoint4 = { + x: record.end, + y: record.stopRate + }; + + recordPoint1 = timeLineCoordinateSystem.transformThisPoint(recordPoint1); + recordPoint2 = timeLineCoordinateSystem.transformThisPoint(recordPoint2); + recordPoint3 = timeLineCoordinateSystem.transformThisPoint(recordPoint3); + recordPoint4 = timeLineCoordinateSystem.transformThisPoint(recordPoint4); + + recordPoint1 = transformThisPoint(recordPoint1, thisObject.container); + recordPoint2 = transformThisPoint(recordPoint2, thisObject.container); + recordPoint3 = transformThisPoint(recordPoint3, thisObject.container); + recordPoint4 = transformThisPoint(recordPoint4, thisObject.container); + + if (recordPoint2.x < viewPort.visibleArea.bottomLeft.x || recordPoint1.x > viewPort.visibleArea.bottomRight.x) { + continue; + } + + recordPoint1 = viewPort.fitIntoVisibleArea(recordPoint1); + recordPoint2 = viewPort.fitIntoVisibleArea(recordPoint2); + recordPoint3 = viewPort.fitIntoVisibleArea(recordPoint3); + recordPoint4 = viewPort.fitIntoVisibleArea(recordPoint4); + + let line1 = ''; + let line2 = ''; + + switch (record.exitType) { + case 1: { + line1 = 'STOP'; + break; + } + case 2: { + line1 = 'TP'; + break; + } + } + + if (record.lastProfitPercent < 0) { + + line2 = (record.lastProfitPercent).toFixed(2) + ' %'; + + } else { + + line2 = (record.lastProfitPercent).toFixed(2) + ' %'; + } + + /* Draw the triangle that represents the trade. */ + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(recordPoint1.x, recordPoint1.y); + browserCanvasContext.lineTo(recordPoint2.x, recordPoint2.y); + browserCanvasContext.lineTo(recordPoint3.x, recordPoint3.y); + + browserCanvasContext.closePath(); + + let opacity = '0.25'; + + if (record.lastProfitPercent > 0) { + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')'; + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + opacity + ')'; + } else { + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')'; + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')'; + } + + if (userPositionDate >= record.begin && userPositionDate <= record.end) { + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; + } + + browserCanvasContext.fill(); + + browserCanvasContext.lineWidth = 1; + browserCanvasContext.stroke(); + + if ( + recordPoint4.x < viewPort.visibleArea.topLeft.x + 250 + || + recordPoint4.x > viewPort.visibleArea.bottomRight.x - 250 + || + recordPoint4.y > viewPort.visibleArea.bottomRight.y - 100 + || + recordPoint4.y < viewPort.visibleArea.topLeft.y + 100 + ) { + // we do not write any text + } else { + + + printLabel(line1, recordPoint2.x - (recordPoint2.x - recordPoint1.x) / 2 - line1.length * FONT_ASPECT_RATIO, recordPoint4.y - 30, '0.50', 12); + printLabel(line2, recordPoint2.x - (recordPoint2.x - recordPoint1.x) / 2 - line2.length * FONT_ASPECT_RATIO, recordPoint4.y - 15, '0.50', 12); + + + } + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); } + } + } + + + function onZoomChanged(event) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onZoomChanged -> Entering function."); } + + recalculate(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onZoomChanged -> err = " + err.stack); } + } + } + + function onOffsetChanged() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onOffsetChanged -> Entering function."); } + + if (Math.random() * 100 > 95) { + + recalculate() + }; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onOffsetChanged -> err = " + err.stack); } + } + } + + function onDragFinished() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] onDragFinished -> Entering function."); } + + recalculate(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] onDragFinished -> err = " + err.stack); } + } + } +} + + + + + + + + + + + + + + + + + + + diff --git a/TradingSimulation.js b/TradingSimulation.js index 989a6fd12..f6b6c2a61 100644 --- a/TradingSimulation.js +++ b/TradingSimulation.js @@ -49,13 +49,6 @@ let records = []; // Here we keep the records to be ploted every time the Draw() function is called by the AAWebPlatform. - let smileyHappy; - let smileySad; - let strategyImages = []; - let smileyMonkeyEyes; - let smileyMonkeyEars; - let imageStrategy; - let imageStrategyPhase; let imageStopLossPhase; let imageBuyOrderPhase; @@ -80,13 +73,6 @@ /* icons */ - smileyHappy = undefined; - smileySad = undefined; - strategyImages = undefined; - smileyMonkeyEyes = undefined; - smileyMonkeyEars = undefined; - imageStrategy = undefined; - imageStrategyPhase = undefined; imageStopLossPhase = undefined; imageBuyOrderPhase = undefined; @@ -150,36 +136,9 @@ /* Loading a few icons */ - smileyHappy = loadEmoji("Smiley/Emoji Smiley-51.png"); - smileySad = loadEmoji("Smiley/Emoji Smiley-26.png"); - smileyMonkeyEyes = loadEmoji("Smiley/Emoji Smiley-85.png"); - smileyMonkeyEars = loadEmoji("Smiley/Emoji Smiley-86.png"); - imageStrategy = loadEmoji("Places/Emoji Orte-90.png"); - imageStrategyPhase = loadEmoji("Places/Emoji Orte-91.png"); imageStopLossPhase = loadEmoji("stop.png"); imageBuyOrderPhase = loadEmoji("Nature/Emoji Natur-67.png"); - for (let i = 1; i < 15; i++) { - let strategyImage = loadEmoji("Symbols/Emoji Symbols-" + (112 + i) + ".png"); - strategyImages.push(strategyImage); - } - - function loadEmoji(pPath) { - - let newImage; - - newImage = new Image(); - newImage.onload = onImageLoaded; - - function onImageLoaded() { - newImage.isLoaded = true; - } - - newImage.src = window.canvasApp.urlPrefix + "Images/Emoji/" + pPath; - - return newImage; - } - callBackFunction(); } catch (err) { @@ -591,44 +550,17 @@ let userPosition = getUserPosition() let userPositionDate = userPosition.point.x - let directionShort; - let directionLong; - let record; - let strategy = { - begin: undefined, - end: undefined, - image: undefined, - entryPoint: undefined - } - - let trade = { - begin: undefined, - end: undefined, - image: undefined, - entryPoint: undefined - } - /* Now we calculate and plot the records */ for (let i = 1; i < records.length; i++) { // We do not start in 0 so as to be able to read the previous record i - 1 record = records[i]; - directionShort = 0; - let strategyNumber; - let strategyPhase = 0; + let stopLossPhase = 0; let buyOrderPhase = 0; - if (record.strategy !== records[i - 1].strategy) { // When a change in the strategy field is detected, it is time to plot it. - strategyNumber = record.strategy; - } - - if (record.strategyPhase !== records[i - 1].strategyPhase) { - strategyPhase = record.strategyPhase; - } - if (record.stopLossPhase !== records[i - 1].stopLossPhase) { stopLossPhase = record.stopLossPhase; } @@ -637,41 +569,6 @@ buyOrderPhase = record.buyOrderPhase; } - if (record.type === 'Buy@BuyOrder') { directionShort = +1; } - if (record.type === 'Buy@StopLoss') { directionShort = +1; } - if (record.type === 'Sell') { directionShort = +1; } - - if (strategyPhase > 0) { - if (strategyPhase % 2 !== 0) { //Depending if the phase is oddd or even goes above or below. - directionLong = 1; - } else { - directionLong = -1; - } - } - - if (strategyNumber === 0) { - directionLong = -1; - } - - if (strategyNumber > 0) { - directionLong = -1; - } - - let recordPoint1 = { - x: record.begin + (record.end - record.begin) / 2, - y: record.rate - }; - - let recordPoint2 = { // Long Stick Head - x: record.begin + (record.end - record.begin) / 2, - y: 0 - }; - - let recordPoint3 = { // Short Stick Head - x: record.end, - y: 0 - }; - let recordPoint4 = { x: record.begin, y: record.stopLoss @@ -720,9 +617,6 @@ recordPoint9.x = 0; } - recordPoint1 = timeLineCoordinateSystem.transformThisPoint(recordPoint1); - recordPoint2 = timeLineCoordinateSystem.transformThisPoint(recordPoint2); - recordPoint3 = timeLineCoordinateSystem.transformThisPoint(recordPoint3); recordPoint4 = timeLineCoordinateSystem.transformThisPoint(recordPoint4); recordPoint5 = timeLineCoordinateSystem.transformThisPoint(recordPoint5); recordPoint6 = timeLineCoordinateSystem.transformThisPoint(recordPoint6); @@ -730,9 +624,6 @@ recordPoint8 = timeLineCoordinateSystem.transformThisPoint(recordPoint8); recordPoint9 = timeLineCoordinateSystem.transformThisPoint(recordPoint9); - recordPoint1 = transformThisPoint(recordPoint1, thisObject.container); - recordPoint2 = transformThisPoint(recordPoint2, thisObject.container); - recordPoint3 = transformThisPoint(recordPoint3, thisObject.container); recordPoint4 = transformThisPoint(recordPoint4, thisObject.container); recordPoint5 = transformThisPoint(recordPoint5, thisObject.container); recordPoint6 = transformThisPoint(recordPoint6, thisObject.container); @@ -740,16 +631,10 @@ recordPoint8 = transformThisPoint(recordPoint8, thisObject.container); recordPoint9 = transformThisPoint(recordPoint9, thisObject.container); - if (recordPoint1.x < viewPort.visibleArea.bottomLeft.x || recordPoint1.x > viewPort.visibleArea.bottomRight.x) { + if (recordPoint4.x < viewPort.visibleArea.bottomLeft.x || recordPoint4.x > viewPort.visibleArea.bottomRight.x) { continue; } - recordPoint2.y = recordPoint1.y - 2000 * directionLong; - recordPoint3.y = recordPoint1.y - 0 * directionShort; - - recordPoint1 = viewPort.fitIntoVisibleArea(recordPoint1); - recordPoint2 = viewPort.fitIntoVisibleArea(recordPoint2); - recordPoint3 = viewPort.fitIntoVisibleArea(recordPoint3); recordPoint4 = viewPort.fitIntoVisibleArea(recordPoint4); recordPoint5 = viewPort.fitIntoVisibleArea(recordPoint5); recordPoint6 = viewPort.fitIntoVisibleArea(recordPoint6); @@ -843,190 +728,6 @@ printLabel(buyOrderPhase, recordPoint9.x - imageSize * 1 / 3, recordPoint9.y + imageSize * 1.9, '0.9', 8); } - if ( - record.type !== '' - ) { - - /* Next we are drawing the SHORT stick */ - - drawStick(recordPoint3); - - } - - function drawStick(headPoint) { - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(recordPoint1.x, recordPoint1.y); - browserCanvasContext.lineTo(headPoint.x, headPoint.y); - - browserCanvasContext.closePath(); - - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', 0.25)'; - - if (userPositionDate >= record.begin && userPositionDate <= record.end) { - - /* highlight the current record */ - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 1)'; // Current record accroding to time - } - - browserCanvasContext.setLineDash([4, 3]) - browserCanvasContext.lineWidth = 0.2 - browserCanvasContext.stroke() - browserCanvasContext.setLineDash([0, 0]) - - } - - //browserCanvasContext.beginPath(); - - let line1; - let line2; - - drawStrategy(); - drawTrade(); - - function drawStrategy() { - - if (strategyNumber < 15 && strategyNumber > 0) { - strategy.image = strategyImages[strategyNumber - 1]; - strategy.entryPoint = recordPoint2; - strategy.begin = record.begin - strategy.end = record.end - - imageToDraw = strategy.image; - - } - - if (strategyNumber === 0) { - - if (strategy.entryPoint !== undefined) { - /* Draw the line that represents the duration of closed strategy */ - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(strategy.entryPoint.x + imageSize / 2, strategy.entryPoint.y); - browserCanvasContext.lineTo(recordPoint2.x - imageSize / 2, recordPoint2.y); - - browserCanvasContext.closePath(); - - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', 1)'; - browserCanvasContext.lineWidth = 1 - - browserCanvasContext.stroke() - } - - imageToDraw = strategy.image; - } - - if (imageToDraw !== undefined) { - - if (strategyNumber !== undefined) { - - drawStick(recordPoint2); - - } - - if (imageToDraw.isLoaded === true) { - browserCanvasContext.drawImage(imageToDraw, recordPoint2.x - imageSize / 2, recordPoint2.y - imageSize / 2, imageSize, imageSize); - imageToDraw = undefined; - } - } - - if (strategyNumber === 0) { - strategy = { - begin: undefined, - end: undefined, - image: undefined, - entryPoint: undefined - } - } - } - - function drawTrade() { - - if (record.type === 'Buy@StopLoss' || record.type === 'Buy@BuyOrder') { - - if (record.type === 'Buy@StopLoss') { - - line1 = 'STOP'; - - } else { - - line1 = 'TP'; - } - - if (record.lastProfit < 0) { - - line2 = (record.lastProfitPercent).toFixed(2) + ' %'; - imageToDraw = smileySad; - - } else { - - line2 = (record.lastProfitPercent).toFixed(2) + ' %'; - imageToDraw = smileyHappy; - } - - if (trade.entryPoint !== undefined) { - /* Draw the triangle that represents the trade. */ - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(trade.entryPoint.x, trade.entryPoint.y); - browserCanvasContext.lineTo(recordPoint3.x, recordPoint3.y); - browserCanvasContext.lineTo(recordPoint3.x, trade.entryPoint.y); - - browserCanvasContext.closePath(); - - let opacity = '0.25'; - - if (recordPoint3.y > trade.entryPoint.y) { - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')'; - browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + opacity + ')'; - } else { - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')'; - browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')'; - } - - browserCanvasContext.fill(); - - browserCanvasContext.lineWidth = 1; - browserCanvasContext.stroke(); - } - - if ( - recordPoint3.x < viewPort.visibleArea.topLeft.x + 250 - || - recordPoint3.x > viewPort.visibleArea.bottomRight.x - 250 - || - recordPoint3.y > viewPort.visibleArea.bottomRight.y - 100 - || - recordPoint3.y < viewPort.visibleArea.topLeft.y + 100 - ) { - // we do not write any text - } else { - if (line1 !== undefined && trade.entryPoint !== undefined) { - - printLabel(line1, recordPoint3.x - (recordPoint3.x - trade.entryPoint.x) / 2 - line1.length * FONT_ASPECT_RATIO, recordPoint4.y - 30, '0.50', 12); - printLabel(line2, recordPoint3.x - (recordPoint3.x - trade.entryPoint.x) / 2 - line2.length * FONT_ASPECT_RATIO, recordPoint4.y - 15, '0.50', 12); - - } - } - - } - - if (record.type === 'Sell') { - - line1 = ''; - line2 = ''; - - imageToDraw = smileyHappy; - - trade.begin = record.begin; - trade.end = record.end; - trade.entryPoint = recordPoint3; - } - } - /* Send the current record to the panel */ if (userPositionDate >= record.begin && userPositionDate <= record.end) { @@ -1036,25 +737,6 @@ }; thisObject.container.eventHandler.raiseEvent("Current Record Changed", currentRecord); } - - /* This is how we write the text */ - - function printLabel(labelToPrint, x, y, opacity, fontSize) { - - let labelPoint; - - browserCanvasContext.font = fontSize + 'px ' + UI_FONT.SECONDARY + ' Saira'; - - let label = '' + labelToPrint; - - let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO; - - browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')'; - browserCanvasContext.fillText(label, x, y); - - } - - } @@ -1069,8 +751,6 @@ try { - if (INFO_LOG === true) { logger.write("[INFO] onZoomChanged -> Entering function."); } - recalculate(); } catch (err) { @@ -1083,8 +763,6 @@ try { - if (INFO_LOG === true) { logger.write("[INFO] onOffsetChanged -> Entering function."); } - if (Math.random() * 100 > 95) { recalculate() @@ -1100,8 +778,6 @@ try { - if (INFO_LOG === true) { logger.write("[INFO] onDragFinished -> Entering function."); } - recalculate(); } catch (err) { diff --git a/this.plotter.config.json b/this.plotter.config.json index 38e54024c..d8ea7453e 100644 --- a/this.plotter.config.json +++ b/this.plotter.config.json @@ -29,6 +29,22 @@ } ] }, + { + "codeName": "Strategies", + "moduleName": "Strategies", + "description": "Plots Strategies.", + "profilePicture": "Strategies.png", + "panels": [ + ] + }, + { + "codeName": "Trades", + "moduleName": "Trades", + "description": "Plots Trades.", + "profilePicture": "Trades.png", + "panels": [ + ] + }, { "codeName": "SimulationExecution", "moduleName": "SimulationExecution",