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",