diff --git a/.vs/Plotters-Trading/v15/.suo b/.vs/Plotters-Trading/v15/.suo index 8365e412f..dee52a83b 100644 Binary files a/.vs/Plotters-Trading/v15/.suo and b/.vs/Plotters-Trading/v15/.suo differ diff --git a/History.js b/History.js index 5e9b51fdf..6ad071132 100644 --- a/History.js +++ b/History.js @@ -1,5 +1,12 @@ function newAAMastersPlottersTradingHistory() { + const MODULE_NAME = "AAMasters Plotters Trading History"; + const INFO_LOG = true; + const INTENSIVE_LOG = false; + const ERROR_LOG = true; + const logger = newDebugLog(); + logger.fileName = MODULE_NAME; + let thisObject = { // Main functions and properties. @@ -46,262 +53,110 @@ function initialize(pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) { - datetime = pDatetime; - timePeriod = pTimePeriod; + try { - fileSequence = pStorage.fileSequence[0]; + if (INFO_LOG === true) { logger.write("[INFO] initialize -> Entering function."); } - recalculate(); - recalculateScale(); - callBackFunction(); + datetime = pDatetime; + timePeriod = pTimePeriod; + fileSequence = pStorage.fileSequence[0]; + + recalculate(callBackFunction); + recalculateScale(callBackFunction); + + callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } } function getContainer(point) { - let container; + try { - /* First we check if this point is inside this space. */ + if (INFO_LOG === true) { logger.write("[INFO] getContainer -> Entering function."); } - if (this.container.frame.isThisPointHere(point) === true) { + let container; - return this.container; + /* First we check if this point is inside this space. */ - } else { + if (this.container.frame.isThisPointHere(point) === true) { - /* This point does not belong to this space. */ + return this.container; - return undefined; + } else { + + /* This point does not belong to this space. */ + + return undefined; + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err); } } - } function setTimePeriod(pTimePeriod) { - timePeriod = pTimePeriod; + try { - recalculate(); + if (INFO_LOG === true) { logger.write("[INFO] setTimePeriod -> Entering function."); } + timePeriod = pTimePeriod; + + recalculate(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err); } + } } function setDatetime(newDatetime) { - datetime = newDatetime; + try { - } + if (INFO_LOG === true) { logger.write("[INFO] setDatetime -> Entering function."); } - function draw() { + datetime = newDatetime; - plotChart(); + } catch (err) { - } - - function recalculate() { - - if (fileSequence === undefined) { return; } - - /* - - We are going to filter the records depending on the Time Period. We want that for a 1 min time peroid all the records appears on screen, - but for higher periods, we will filter out some records, so that they do not overlap ever. - - */ - - plotElements = []; - plotLines = []; - notes = []; - - let lastSellRate; - let lastSellDate; - let sellExecRate; - - let lastBuyRate; - let lastBuyDate; - let buyExecRate; - - let maxSequence = fileSequence.getFilesLoaded(); - - for (let j = 0; j < maxSequence; j++) { - - let file = fileSequence.getFile(j); - - let history = []; - let lines = []; - - let oneMin = 60000; - let step = timePeriod / oneMin; - - /* First the small balls */ - - for (let i = 0; i < file.length; i = i + step) { - - let newHistoryRecord = { - - date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, - buyAvgRate: file[i][1], - sellAvgRate: file[i][2], - - lastSellRate: file[i][3], - sellExecRate: file[i][4], - lastBuyRate: file[i][5], - buyExecRate: file[i][6], - - marketRate: file[i][7], - newPositions: file[i][8], - newTrades: file[i][9], - movedPositions: file[i][10], - profitsAssetA: file[i][11], - profitsAssetB: file[i][12], - combinedProfitsA: file[i][13], - combinedProfitsB: file[i][14], - - messageRelevance: file[i][15], - messageTitle: file[i][16], - messageBody: file[i][17] - }; - - history.push(newHistoryRecord); - - if (timePeriod <= 1 * 60 * 1000) { - - /* Here we build the lines. */ - - if (newHistoryRecord.lastSellRate > 0) { - - lastSellRate = newHistoryRecord.lastSellRate; - lastSellDate = newHistoryRecord.date; - - } - - if (newHistoryRecord.sellExecRate > 0) { - - let newLine = { - type: "sell", - x1: lastSellDate, - y1: lastSellRate, - x2: newHistoryRecord.date, - y2: newHistoryRecord.sellExecRate - }; - - lines.push(newLine); - - } - - if (newHistoryRecord.lastBuyRate > 0) { - - lastBuyRate = newHistoryRecord.lastBuyRate; - lastBuyDate = newHistoryRecord.date; - - } - - if (newHistoryRecord.buyExecRate > 0) { - - let newLine = { - type: "buy", - x1: lastBuyDate, - y1: lastBuyRate, - x2: newHistoryRecord.date, - y2: newHistoryRecord.buyExecRate - }; - - lines.push(newLine); - - } - } - } - - /* Second we process the text */ - - for (let i = 0; i < file.length; i++) { - - let newHistoryRecord = { - - date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, - buyAvgRate: file[i][1], - sellAvgRate: file[i][2], - - lastSellRate: file[i][3], - sellExecRate: file[i][4], - lastBuyRate: file[i][5], - buyExecRate: file[i][6], - - marketRate: file[i][7], - newPositions: file[i][8], - newTrades: file[i][9], - movedPositions: file[i][10], - profitsAssetA: file[i][11], - profitsAssetB: file[i][12], - combinedProfitsA: file[i][13], - combinedProfitsB: file[i][14], - - messageRelevance: file[i][15], - messageTitle: file[i][16], - messageBody: file[i][17] - }; - - if (newHistoryRecord.messageTitle !== "" && newHistoryRecord.messageBody !== "") { - - if (newHistoryRecord.messageRelevance >= 0 && newHistoryRecord.messageRelevance <= 10) { - - let relevanceTimePeriod = (dailyFilePeriods[10 - newHistoryRecord.messageRelevance][0]); - - if (timePeriod <= relevanceTimePeriod) { - - let note = { - title: newHistoryRecord.messageTitle, - body: newHistoryRecord.messageBody, - date: newHistoryRecord.date, - rate: newHistoryRecord.marketRate, - position: { - x: 0, - y: 0 - }, - visible: false - }; - - notes.push(note); - } - } - } - } - - plotElements.push(history); - plotLines.push(lines); - - notesChangedEventRaised = false; + if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err); } } - - thisObject.container.eventHandler.raiseEvent("History Changed", history); - } - function recalculateScale() { + function recalculate(callBackFunction) { - if (fileSequence === undefined) { return; } // We need the market file to be loaded to make the calculation. + try { - if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated. + if (INFO_LOG === true) { logger.write("[INFO] recalculate -> Entering function."); } - let minValue = { - x: EARLIEST_DATE.valueOf(), - y: 0 - }; + if (fileSequence === undefined) { return; } - let maxValue = { - x: MAX_PLOTABLE_DATE.valueOf(), - y: nextPorwerOf10(USDT_BTC_HTH) - }; + /* + + We are going to filter the records depending on the Time Period. We want that for a 1 min time peroid all the records appears on screen, + but for higher periods, we will filter out some records, so that they do not overlap ever. + + */ + plotElements = []; + plotLines = []; + notes = []; - timeLineCoordinateSystem.initialize( - minValue, - maxValue, - thisObject.container.frame.width, - thisObject.container.frame.height - ); + let lastSellRate; + let lastSellDate; + let sellExecRate; - function getMaxRate() { - - let maxValue = 0; + let lastBuyRate; + let lastBuyDate; + let buyExecRate; let maxSequence = fileSequence.getFilesLoaded(); @@ -309,192 +164,292 @@ let file = fileSequence.getFile(j); + let history = []; + let lines = []; + + let oneMin = 60000; + let step = timePeriod / oneMin; + + /* First the small balls */ + + for (let i = 0; i < file.length; i = i + step) { + + let newHistoryRecord = { + + date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, + buyAvgRate: file[i][1], + sellAvgRate: file[i][2], + + lastSellRate: file[i][3], + sellExecRate: file[i][4], + lastBuyRate: file[i][5], + buyExecRate: file[i][6], + + marketRate: file[i][7], + newPositions: file[i][8], + newTrades: file[i][9], + movedPositions: file[i][10], + profitsAssetA: file[i][11], + profitsAssetB: file[i][12], + combinedProfitsA: file[i][13], + combinedProfitsB: file[i][14], + + messageRelevance: file[i][15], + messageTitle: file[i][16], + messageBody: file[i][17] + }; + + history.push(newHistoryRecord); + + if (timePeriod <= 1 * 60 * 1000) { + + /* Here we build the lines. */ + + if (newHistoryRecord.lastSellRate > 0) { + + lastSellRate = newHistoryRecord.lastSellRate; + lastSellDate = newHistoryRecord.date; + + } + + if (newHistoryRecord.sellExecRate > 0) { + + let newLine = { + type: "sell", + x1: lastSellDate, + y1: lastSellRate, + x2: newHistoryRecord.date, + y2: newHistoryRecord.sellExecRate + }; + + lines.push(newLine); + + } + + if (newHistoryRecord.lastBuyRate > 0) { + + lastBuyRate = newHistoryRecord.lastBuyRate; + lastBuyDate = newHistoryRecord.date; + + } + + if (newHistoryRecord.buyExecRate > 0) { + + let newLine = { + type: "buy", + x1: lastBuyDate, + y1: lastBuyRate, + x2: newHistoryRecord.date, + y2: newHistoryRecord.buyExecRate + }; + + lines.push(newLine); + + } + } + } + + /* Second we process the text */ + for (let i = 0; i < file.length; i++) { - let currentMax = file[i][1] + file[i][2]; // 1 = rates. + let newHistoryRecord = { - if (maxValue < currentMax) { - maxValue = currentMax; + date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, + buyAvgRate: file[i][1], + sellAvgRate: file[i][2], + + lastSellRate: file[i][3], + sellExecRate: file[i][4], + lastBuyRate: file[i][5], + buyExecRate: file[i][6], + + marketRate: file[i][7], + newPositions: file[i][8], + newTrades: file[i][9], + movedPositions: file[i][10], + profitsAssetA: file[i][11], + profitsAssetB: file[i][12], + combinedProfitsA: file[i][13], + combinedProfitsB: file[i][14], + + messageRelevance: file[i][15], + messageTitle: file[i][16], + messageBody: file[i][17] + }; + + if (newHistoryRecord.messageTitle !== "" && newHistoryRecord.messageBody !== "") { + + if (newHistoryRecord.messageRelevance >= 0 && newHistoryRecord.messageRelevance <= 10) { + + let relevanceTimePeriod = (dailyFilePeriods[10 - newHistoryRecord.messageRelevance][0]); + + if (timePeriod <= relevanceTimePeriod) { + + let note = { + title: newHistoryRecord.messageTitle, + body: newHistoryRecord.messageBody, + date: newHistoryRecord.date, + rate: newHistoryRecord.marketRate, + position: { + x: 0, + y: 0 + }, + visible: false + }; + + notes.push(note); + } + } } } + + plotElements.push(history); + plotLines.push(lines); + + notesChangedEventRaised = false; + } + + thisObject.container.eventHandler.raiseEvent("History Changed", history); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } + } + + function recalculateScale(callBackFunction) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateScale -> Entering function."); } + + if (fileSequence === undefined) { return; } // We need the market file to be loaded to make the calculation. + + if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated. + + let minValue = { + x: EARLIEST_DATE.valueOf(), + y: 0 + }; + + let maxValue = { + x: MAX_PLOTABLE_DATE.valueOf(), + y: nextPorwerOf10(USDT_BTC_HTH) + }; + + + timeLineCoordinateSystem.initialize( + minValue, + maxValue, + thisObject.container.frame.width, + thisObject.container.frame.height + ); + + function getMaxRate() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateScale -> getMaxRate > Entering function."); } + + let maxValue = 0; + + let maxSequence = fileSequence.getFilesLoaded(); + + for (let j = 0; j < maxSequence; j++) { + + let file = fileSequence.getFile(j); + + for (let i = 0; i < file.length; i++) { + + let currentMax = file[i][1] + file[i][2]; // 1 = rates. + + if (maxValue < currentMax) { + maxValue = currentMax; + } + } + } + + return maxValue; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> getMaxRate -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } } - return maxValue; + } catch (err) { + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } + } + + function draw() { + + try { + + if (INTENSIVE_LOG === true) { logger.write("[INFO] draw -> Entering function."); } + + plotChart(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err); } } } function plotChart() { - let point; - let history; + try { - for (let j = 0; j < plotElements.length; j++) { + if (INTENSIVE_LOG === true) { logger.write("[INFO] plotChart -> Entering function."); } - let history = plotElements[j]; + let point; + let history; - for (let i = 0; i < history.length; i++) { + for (let j = 0; j < plotElements.length; j++) { - record = history[i]; + let history = plotElements[j]; - point = { - x: record.date, - y: record.marketRate - }; + for (let i = 0; i < history.length; i++) { - point = timeLineCoordinateSystem.transformThisPoint(point); - point = transformThisPoint(point, thisObject.container); + record = history[i]; - if (point.x < viewPort.visibleArea.bottomLeft.x || point.x > viewPort.visibleArea.bottomRight.x) { continue;} - - point = viewPort.fitIntoVisibleArea(point); - - let isCurrentRecord = false; - - if (datetime !== undefined) { - let dateValue = datetime.valueOf(); - if (dateValue >= record.date - timePeriod / 2 && dateValue <= record.date + timePeriod / 2 - 1) { - isCurrentRecord = true; - } - } - - let radius = 3; - - let opacity = '0.2'; - - browserCanvasContext.lineWidth = 1; - - /* Outer Circle */ - - browserCanvasContext.beginPath(); - - browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; - - if (isCurrentRecord === false) { - browserCanvasContext.fillStyle = 'rgba(64, 217, 26, ' + opacity + ')'; - } else { - browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ - } - - browserCanvasContext.arc(point.x, point.y, radius, 0, Math.PI * 2, true); - browserCanvasContext.closePath(); - - if (point.x < viewPort.visibleArea.topLeft.x + 50 || point.x > viewPort.visibleArea.bottomRight.x - 50) {/*we leave this history without fill. */ } else { - browserCanvasContext.fill(); - } - - browserCanvasContext.stroke(); - - /* Draw a red inverted triangle on exec sell */ - - if (record.sellExecRate > 0) { - - opacity = '0.3'; - - let point1 = { + point = { x: record.date, - y: record.sellExecRate + y: record.marketRate }; - let point2 = { - x: record.date + timePeriod / 7 * 2, - y: record.sellExecRate - }; + point = timeLineCoordinateSystem.transformThisPoint(point); + point = transformThisPoint(point, thisObject.container); - let point3 = { - x: record.date - timePeriod / 7 * 2, - y: record.sellExecRate - }; + if (point.x < viewPort.visibleArea.bottomLeft.x || point.x > viewPort.visibleArea.bottomRight.x) { continue; } - point1 = timeLineCoordinateSystem.transformThisPoint(point1); - point1 = transformThisPoint(point1, thisObject.container); - point1 = viewPort.fitIntoVisibleArea(point1); + point = viewPort.fitIntoVisibleArea(point); - point2 = timeLineCoordinateSystem.transformThisPoint(point2); - point2 = transformThisPoint(point2, thisObject.container); - point2 = viewPort.fitIntoVisibleArea(point2); + let isCurrentRecord = false; - point3 = timeLineCoordinateSystem.transformThisPoint(point3); - point3 = transformThisPoint(point3, thisObject.container); - point3 = viewPort.fitIntoVisibleArea(point3); - - let diff = point2.x - point3.x; - point2.y = point2.y - diff; - point3.y = point3.y - diff; - - point2 = viewPort.fitIntoVisibleArea(point2); - point3 = viewPort.fitIntoVisibleArea(point3); - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(point1.x, point1.y); - browserCanvasContext.lineTo(point2.x, point2.y); - browserCanvasContext.lineTo(point3.x, point3.y); - browserCanvasContext.lineTo(point1.x, point1.y); - - browserCanvasContext.closePath(); - - if (isCurrentRecord === false) { - browserCanvasContext.fillStyle = 'rgba(219, 18, 18, ' + opacity + ')'; - } else { - browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + if (datetime !== undefined) { + let dateValue = datetime.valueOf(); + if (dateValue >= record.date - timePeriod / 2 && dateValue <= record.date + timePeriod / 2 - 1) { + isCurrentRecord = true; + } } - browserCanvasContext.fill(); + let radius = 3; - browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; - browserCanvasContext.stroke(); + let opacity = '0.2'; - } + browserCanvasContext.lineWidth = 1; - /* Draw a green triangle on exec buy */ - - if (record.buyExecRate > 0) { - - opacity = '0.3'; - - let point1 = { - x: record.date, - y: record.buyExecRate - }; - - let point2 = { - x: record.date + timePeriod / 7 * 2, - y: record.buyExecRate - }; - - let point3 = { - x: record.date - timePeriod / 7 * 2, - y: record.buyExecRate - }; - - point1 = timeLineCoordinateSystem.transformThisPoint(point1); - point1 = transformThisPoint(point1, thisObject.container); - point1 = viewPort.fitIntoVisibleArea(point1); - - point2 = timeLineCoordinateSystem.transformThisPoint(point2); - point2 = transformThisPoint(point2, thisObject.container); - point2 = viewPort.fitIntoVisibleArea(point2); - - point3 = timeLineCoordinateSystem.transformThisPoint(point3); - point3 = transformThisPoint(point3, thisObject.container); - point3 = viewPort.fitIntoVisibleArea(point3); - - let diff = point2.x - point3.x; - point2.y = point2.y + diff; - point3.y = point3.y + diff; - - point2 = viewPort.fitIntoVisibleArea(point2); - point3 = viewPort.fitIntoVisibleArea(point3); + /* Outer Circle */ browserCanvasContext.beginPath(); - browserCanvasContext.moveTo(point1.x, point1.y); - browserCanvasContext.lineTo(point2.x, point2.y); - browserCanvasContext.lineTo(point3.x, point3.y); - browserCanvasContext.lineTo(point1.x, point1.y); - - browserCanvasContext.closePath(); + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; if (isCurrentRecord === false) { browserCanvasContext.fillStyle = 'rgba(64, 217, 26, ' + opacity + ')'; @@ -502,32 +457,287 @@ browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ } - browserCanvasContext.fill(); + browserCanvasContext.arc(point.x, point.y, radius, 0, Math.PI * 2, true); + browserCanvasContext.closePath(); + + if (point.x < viewPort.visibleArea.topLeft.x + 50 || point.x > viewPort.visibleArea.bottomRight.x - 50) {/*we leave this history without fill. */ } else { + browserCanvasContext.fill(); + } - browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; browserCanvasContext.stroke(); + /* Draw a red inverted triangle on exec sell */ + + if (record.sellExecRate > 0) { + + opacity = '0.3'; + + let point1 = { + x: record.date, + y: record.sellExecRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.sellExecRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.sellExecRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y - diff; + point3.y = point3.y - diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(219, 18, 18, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + /* Draw a green triangle on exec buy */ + + if (record.buyExecRate > 0) { + + opacity = '0.3'; + + let point1 = { + x: record.date, + y: record.buyExecRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.buyExecRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.buyExecRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y + diff; + point3.y = point3.y + diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(64, 217, 26, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + /* Draw a red inverted triangle on sell */ + + if (record.lastSellRate > 0) { + + opacity = '0.3'; + + let point1 = { + x: record.date, + y: record.lastSellRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.lastSellRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.lastSellRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y - diff; + point3.y = point3.y - diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(255, 255, 255, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + /* Draw a green triangle on buy */ + + if (record.lastBuyRate > 0) { + + opacity = '0.3'; + + let point1 = { + x: record.date, + y: record.lastBuyRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.lastBuyRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.lastBuyRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y + diff; + point3.y = point3.y + diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(255, 255, 255, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + + /* Since there is at least some point plotted, then the profile should be visible. */ + + thisObject.payload.profile.visible = true; } - /* Draw a red inverted triangle on sell */ + /* Draw the lines connecting plot elements. */ - if (record.lastSellRate > 0) { + let lines = plotLines[j]; - opacity = '0.3'; + for (let i = 0; i < lines.length; i++) { + + let line = lines[i]; + + opacity = '0.2'; let point1 = { - x: record.date, - y: record.lastSellRate + x: line.x1, + y: line.y1 }; let point2 = { - x: record.date + timePeriod / 7 * 2, - y: record.lastSellRate - }; - - let point3 = { - x: record.date - timePeriod / 7 * 2, - y: record.lastSellRate + x: line.x2, + y: line.y2 }; point1 = timeLineCoordinateSystem.transformThisPoint(point1); @@ -538,201 +748,76 @@ point2 = transformThisPoint(point2, thisObject.container); point2 = viewPort.fitIntoVisibleArea(point2); - point3 = timeLineCoordinateSystem.transformThisPoint(point3); - point3 = transformThisPoint(point3, thisObject.container); - point3 = viewPort.fitIntoVisibleArea(point3); - - let diff = point2.x - point3.x; - point2.y = point2.y - diff; - point3.y = point3.y - diff; - - point2 = viewPort.fitIntoVisibleArea(point2); - point3 = viewPort.fitIntoVisibleArea(point3); - browserCanvasContext.beginPath(); browserCanvasContext.moveTo(point1.x, point1.y); browserCanvasContext.lineTo(point2.x, point2.y); - browserCanvasContext.lineTo(point3.x, point3.y); - browserCanvasContext.lineTo(point1.x, point1.y); browserCanvasContext.closePath(); - if (isCurrentRecord === false) { - browserCanvasContext.fillStyle = 'rgba(255, 255, 255, ' + opacity + ')'; + if (line.type === "sell") { + + browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; + } else { - browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; + } - browserCanvasContext.fill(); - - browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; browserCanvasContext.stroke(); } - /* Draw a green triangle on buy */ + /* Now we calculate the anchor position of notes. */ - if (record.lastBuyRate > 0) { - opacity = '0.3'; + for (let i = 0; i < notes.length; i++) { - let point1 = { - x: record.date, - y: record.lastBuyRate + let note = notes[i]; + + opacity = '0.2'; + + note.position = { + x: note.date, + y: note.rate }; - let point2 = { - x: record.date + timePeriod / 7 * 2, - y: record.lastBuyRate - }; + note.position = timeLineCoordinateSystem.transformThisPoint(note.position); + note.position = transformThisPoint(note.position, thisObject.container); - let point3 = { - x: record.date - timePeriod / 7 * 2, - y: record.lastBuyRate - }; - - point1 = timeLineCoordinateSystem.transformThisPoint(point1); - point1 = transformThisPoint(point1, thisObject.container); - point1 = viewPort.fitIntoVisibleArea(point1); - - point2 = timeLineCoordinateSystem.transformThisPoint(point2); - point2 = transformThisPoint(point2, thisObject.container); - point2 = viewPort.fitIntoVisibleArea(point2); - - point3 = timeLineCoordinateSystem.transformThisPoint(point3); - point3 = transformThisPoint(point3, thisObject.container); - point3 = viewPort.fitIntoVisibleArea(point3); - - let diff = point2.x - point3.x; - point2.y = point2.y + diff; - point3.y = point3.y + diff; - - point2 = viewPort.fitIntoVisibleArea(point2); - point3 = viewPort.fitIntoVisibleArea(point3); - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(point1.x, point1.y); - browserCanvasContext.lineTo(point2.x, point2.y); - browserCanvasContext.lineTo(point3.x, point3.y); - browserCanvasContext.lineTo(point1.x, point1.y); - - browserCanvasContext.closePath(); - - if (isCurrentRecord === false) { - browserCanvasContext.fillStyle = 'rgba(255, 255, 255, ' + opacity + ')'; + if (note.position.x < (viewPort.visibleArea.bottomRight.x) * (-1) || note.position.x > (viewPort.visibleArea.bottomRight.x) * (2)) { + note.visible = false; } else { - browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + note.visible = true; } - browserCanvasContext.fill(); - - browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; - browserCanvasContext.stroke(); - } + if (notesChangedEventRaised === false) { - /* Since there is at least some point plotted, then the profile should be visible. */ + thisObject.container.eventHandler.raiseEvent("Notes Changed", notes); + thisObject.payload.notes = notes; - thisObject.payload.profile.visible = true; - } - - /* Draw the lines connecting plot elements. */ - - let lines = plotLines[j]; - - for (let i = 0; i < lines.length; i++) { - - let line = lines[i]; - - opacity = '0.2'; - - let point1 = { - x: line.x1, - y: line.y1 - }; - - let point2 = { - x: line.x2, - y: line.y2 - }; - - point1 = timeLineCoordinateSystem.transformThisPoint(point1); - point1 = transformThisPoint(point1, thisObject.container); - point1 = viewPort.fitIntoVisibleArea(point1); - - point2 = timeLineCoordinateSystem.transformThisPoint(point2); - point2 = transformThisPoint(point2, thisObject.container); - point2 = viewPort.fitIntoVisibleArea(point2); - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(point1.x, point1.y); - browserCanvasContext.lineTo(point2.x, point2.y); - - browserCanvasContext.closePath(); - - if (line.type === "sell") { - - browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; - - } else { - - browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; - - } - - browserCanvasContext.stroke(); - - } - - /* Now we calculate the anchor position of notes. */ - - - for (let i = 0; i < notes.length; i++) { - - let note = notes[i]; - - opacity = '0.2'; - - note.position = { - x: note.date, - y: note.rate - }; - - note.position = timeLineCoordinateSystem.transformThisPoint(note.position); - note.position = transformThisPoint(note.position, thisObject.container); - - if (note.position.x < (viewPort.visibleArea.bottomRight.x) * (-1) || note.position.x > (viewPort.visibleArea.bottomRight.x) * (2)) { - note.visible = false; - } else { - note.visible = true; + notesChangedEventRaised = true; } } - if (notesChangedEventRaised === false) { + /* + + We replace the coordinate of the profile point so that whoever has a reference to it, gets the new position. + We will use the last point plotted on screen as the profilePoint. + + */ - thisObject.container.eventHandler.raiseEvent("Notes Changed", notes); - thisObject.payload.notes = notes; + thisObject.payload.profile.position.x = point.x; + thisObject.payload.profile.position.y = point.y; - notesChangedEventRaised = true; - } + } catch (err) { + if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err); } } - - /* - - We replace the coordinate of the profile point so that whoever has a reference to it, gets the new position. - We will use the last point plotted on screen as the profilePoint. - - */ - - thisObject.payload.profile.position.x = point.x; - thisObject.payload.profile.position.y = point.y; } - }