Merge pull request #56 from AAVikings/develop
Adding clone executor child process
This commit is contained in:
12 files changed
+138
-733
No files matched your search
Submodule Plotters/AAMasters/plotters/Plotters-Bollinger-Bands deleted from b801eb222c.
Submodule Plotters/AAMasters/plotters/Plotters-Bollinger-Channels deleted from f1466c8b43.
Submodule Plotters/AAMasters/plotters/Plotters-Candles-Volumes deleted from f2254b9a21.
@@ -1,711 +0,0 @@
|
||||
function newAAMastersPlottersROICombinedProfits() {
|
||||
|
||||
const MODULE_NAME = "AAArena Plotters ROI Combined Profits";
|
||||
const ERROR_LOG = true;
|
||||
const INTENSIVE_LOG = false;
|
||||
const logger = newWebDebugLog();
|
||||
logger.fileName = MODULE_NAME;
|
||||
|
||||
let thisObject = {
|
||||
|
||||
// Main functions and properties.
|
||||
|
||||
initialize: initialize,
|
||||
container: undefined,
|
||||
getContainer: getContainer,
|
||||
setTimePeriod: setTimePeriod,
|
||||
setDatetime: setDatetime,
|
||||
recalculateScale: recalculateScale,
|
||||
draw: draw,
|
||||
payload: []
|
||||
};
|
||||
|
||||
/* this is part of the module template */
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
|
||||
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.
|
||||
|
||||
/* these are module specific variables: */
|
||||
|
||||
let competition;
|
||||
|
||||
let competitorsSequences;
|
||||
|
||||
let updatedFilesEventsReceived = 0;
|
||||
|
||||
let fileStyles = [];
|
||||
|
||||
let offsetChangedEventSubscriptionId
|
||||
let filesUpdatedEventSubscriptionId
|
||||
let dimmensionsChangedEventSubscriptionId
|
||||
|
||||
return thisObject;
|
||||
|
||||
function finalize() {
|
||||
try {
|
||||
|
||||
/* Stop listening to the necesary events. */
|
||||
|
||||
viewPort.eventHandler.stopListening(offsetChangedEventSubscriptionId);
|
||||
fileSequence.eventHandler.stopListening(filesUpdatedEventSubscriptionId);
|
||||
thisObject.container.eventHandler.stopListening(dimmensionsChangedEventSubscriptionId)
|
||||
|
||||
/* Destroyd References */
|
||||
|
||||
datetime = undefined;
|
||||
timePeriod = undefined;
|
||||
|
||||
fileSequence = undefined;
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(pCompetition, pStorage, pDatetime, pTimePeriod, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
competition = pCompetition;
|
||||
competitorsSequences = pStorage.competitorsSequences;
|
||||
|
||||
datetime = pDatetime;
|
||||
timePeriod = pTimePeriod;
|
||||
|
||||
recalculate();
|
||||
recalculateScale();
|
||||
|
||||
offsetChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged);
|
||||
|
||||
/* Create the Payload structure */
|
||||
|
||||
for (let k = 0; k < competition.participants.length; k++) {
|
||||
|
||||
let participant = competition.participants[k];
|
||||
|
||||
let payload = {
|
||||
profile: {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
visible: false,
|
||||
plot: true
|
||||
}
|
||||
}
|
||||
|
||||
thisObject.payload.push(payload);
|
||||
}
|
||||
|
||||
for (let k = 0; k < competition.participants.length; k++) {
|
||||
|
||||
let fileSequence = competitorsSequences[0][k]; // Only the first dataSet is considered for now.
|
||||
|
||||
filesUpdatedEventSubscriptionId = fileSequence.eventHandler.listenToEvent("Files Updated", onFilesUpdated); // Only the first sequence is supported right now.
|
||||
|
||||
}
|
||||
|
||||
/* Here we will choose the colors of each participants path. */
|
||||
|
||||
for (let k = 0; k < competition.participants.length; k++) {
|
||||
|
||||
let red = Math.trunc(Math.random() * 5) * 50;
|
||||
let green = Math.trunc(Math.random() * 5) * 50;
|
||||
let blue = Math.trunc(Math.random() * 5) * 50;
|
||||
|
||||
let fillStyle = " " + red + "," + green + "," + blue;
|
||||
|
||||
fileStyles.push(fillStyle);
|
||||
|
||||
}
|
||||
|
||||
dimmensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () {
|
||||
recalculateScale()
|
||||
recalculate();
|
||||
})
|
||||
|
||||
recalculate();
|
||||
recalculateScale();
|
||||
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
|
||||
try {
|
||||
|
||||
let container;
|
||||
|
||||
/* First we check if this point is inside this space. */
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point) === true) {
|
||||
|
||||
return thisObject.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 {
|
||||
|
||||
updatedFilesEventsReceived++;
|
||||
|
||||
if (updatedFilesEventsReceived === competition.participants.length) {
|
||||
|
||||
recalculate();
|
||||
updatedFilesEventsReceived = 0;
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] onFilesUpdated -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function setTimePeriod(pTimePeriod) {
|
||||
|
||||
try {
|
||||
|
||||
timePeriod = pTimePeriod;
|
||||
|
||||
recalculate();
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime(newDatetime) {
|
||||
|
||||
try {
|
||||
|
||||
datetime = newDatetime;
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] setDatetime -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
try {
|
||||
return; // This plotter is currently disabled.
|
||||
|
||||
if (INTENSIVE_LOG === true) { logger.write("[INFO] setDatetime -> Entering function."); }
|
||||
|
||||
plotStartFinishLines();
|
||||
plotChart();
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function onOffsetChanged() {
|
||||
|
||||
try {
|
||||
|
||||
if (Math.random() * 100 > 95) {
|
||||
|
||||
recalculate()
|
||||
};
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] onOffsetChanged -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function recalculate() {
|
||||
|
||||
try {
|
||||
|
||||
if (competitorsSequences === 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.
|
||||
|
||||
*/
|
||||
|
||||
for (let k = 0; k < competition.participants.length; k++) {
|
||||
|
||||
let fileSequence = competitorsSequences[0][k]; // Only the first dataSet is considered for now.
|
||||
|
||||
competition.participants[k].plotElements = [];
|
||||
|
||||
let maxSequence = fileSequence.getFilesLoaded();
|
||||
|
||||
for (let j = 0; j < maxSequence; j++) {
|
||||
|
||||
let file = fileSequence.getFile(j);
|
||||
|
||||
/* First the small balls */
|
||||
|
||||
const ONE_MIN_IN_MILISECONDS = 60 * 1000;
|
||||
let step = timePeriod / ONE_MIN_IN_MILISECONDS;
|
||||
|
||||
let i = 0;
|
||||
let lastRecordPushed = 0;
|
||||
|
||||
for (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]
|
||||
};
|
||||
|
||||
competition.participants[k].plotElements.push(newHistoryRecord);
|
||||
lastRecordPushed = i;
|
||||
}
|
||||
|
||||
/* We allways want to put the last record of the file on the filterd dataset, so as to allways show the latest advance of the bot. */
|
||||
|
||||
i = file.length - 1;
|
||||
|
||||
if (lastRecordPushed !== 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]
|
||||
};
|
||||
|
||||
competition.participants[k].plotElements.push(newHistoryRecord);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateScale() {
|
||||
|
||||
try {
|
||||
|
||||
if (competitorsSequences === undefined) { return; } // We need the market file to be loaded to make the calculation.
|
||||
|
||||
if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated.
|
||||
|
||||
let minValue = {
|
||||
x: MIN_PLOTABLE_DATE.valueOf(),
|
||||
y: 0
|
||||
};
|
||||
|
||||
let maxValue = {
|
||||
x: MAX_PLOTABLE_DATE.valueOf(),
|
||||
y: 200 * 100
|
||||
};
|
||||
|
||||
|
||||
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 plotStartFinishLines() {
|
||||
|
||||
try {
|
||||
|
||||
let startDatetime = new Date(competition.startDatetime);
|
||||
let finishDatetime = new Date(competition.finishDatetime);
|
||||
|
||||
let startPointDown = {
|
||||
x: startDatetime.valueOf(),
|
||||
y: 0
|
||||
};
|
||||
|
||||
let startPointUp = {
|
||||
x: startDatetime.valueOf(),
|
||||
y: 0
|
||||
};
|
||||
|
||||
startPointDown = timeLineCoordinateSystem.transformThisPoint(startPointDown);
|
||||
startPointDown = transformThisPoint(startPointDown, thisObject.container);
|
||||
|
||||
startPointUp = timeLineCoordinateSystem.transformThisPoint(startPointUp);
|
||||
startPointUp.y = startPointUp.y - thisObject.container.frame.height;
|
||||
startPointUp = transformThisPoint(startPointUp, thisObject.container);
|
||||
|
||||
if (startPointUp.x > viewPort.visibleArea.bottomLeft.x && startPointUp.x < viewPort.visibleArea.bottomRight.x) {
|
||||
|
||||
startPointDown = viewPort.fitIntoVisibleArea(startPointDown);
|
||||
startPointUp = viewPort.fitIntoVisibleArea(startPointUp);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(startPointDown.x, startPointDown.y);
|
||||
browserCanvasContext.lineTo(startPointUp.x, startPointUp.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(100, 10, 10, 0.5)';
|
||||
browserCanvasContext.lineWidth = 2;
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
}
|
||||
|
||||
/* Here we draw the finish line. */
|
||||
|
||||
let SQUARE_SIDE_REDUCTION_FACTOR = 4;
|
||||
|
||||
if (timePeriod <= _1_HOUR_IN_MILISECONDS) { SQUARE_SIDE_REDUCTION_FACTOR = 2; }
|
||||
if (timePeriod <= _10_MINUTES_IN_MILISECONDS) { SQUARE_SIDE_REDUCTION_FACTOR = 1; }
|
||||
if (timePeriod < _5_MINUTES_IN_MILISECONDS) { SQUARE_SIDE_REDUCTION_FACTOR = 0.5; }
|
||||
|
||||
const TOTAL_SQUARES_TALL = ONE_DAY_IN_MILISECONDS / timePeriod * (timePeriod / _1_MINUTE_IN_MILISECONDS) / SQUARE_SIDE_REDUCTION_FACTOR;
|
||||
const SQUARE_SIDE = thisObject.container.frame.height / TOTAL_SQUARES_TALL;
|
||||
|
||||
let paintThis = true;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
|
||||
for (j = 0; j < TOTAL_SQUARES_TALL; j++) {
|
||||
|
||||
let finishPointDown = {
|
||||
x: finishDatetime.valueOf(),
|
||||
y: 0
|
||||
};
|
||||
|
||||
let finishPointUp = {
|
||||
x: finishDatetime.valueOf(),
|
||||
y: 0
|
||||
};
|
||||
|
||||
finishPointDown = timeLineCoordinateSystem.transformThisPoint(finishPointDown);
|
||||
|
||||
finishPointDown.x = finishPointDown.x + SQUARE_SIDE * i;
|
||||
finishPointDown.y = finishPointDown.y - SQUARE_SIDE * j;
|
||||
|
||||
finishPointDown = transformThisPoint(finishPointDown, thisObject.container);
|
||||
|
||||
finishPointUp = timeLineCoordinateSystem.transformThisPoint(finishPointUp);
|
||||
|
||||
finishPointUp.x = finishPointUp.x + SQUARE_SIDE * i + SQUARE_SIDE;
|
||||
finishPointUp.y = finishPointUp.y - SQUARE_SIDE * j - SQUARE_SIDE;
|
||||
|
||||
finishPointUp = transformThisPoint(finishPointUp, thisObject.container);
|
||||
|
||||
if (finishPointUp.x < viewPort.visibleArea.bottomLeft.x || finishPointDown.x > viewPort.visibleArea.bottomRight.x) { continue; }
|
||||
|
||||
finishPointDown = viewPort.fitIntoVisibleArea(finishPointDown);
|
||||
finishPointUp = viewPort.fitIntoVisibleArea(finishPointUp);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(finishPointDown.x, finishPointDown.y);
|
||||
browserCanvasContext.lineTo(finishPointUp.x, finishPointDown.y);
|
||||
browserCanvasContext.lineTo(finishPointUp.x, finishPointUp.y);
|
||||
browserCanvasContext.lineTo(finishPointDown.x, finishPointUp.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
/*
|
||||
browserCanvasContext.strokeStyle = 'rgba(100, 100, 100, 1)';
|
||||
browserCanvasContext.lineWidth = 1;
|
||||
browserCanvasContext.stroke();
|
||||
*/
|
||||
|
||||
if (paintThis === true) {
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(100, 100, 100, ' + (0.6 - i / 5) + ')';
|
||||
browserCanvasContext.fill();
|
||||
|
||||
}
|
||||
|
||||
if (paintThis === true) { paintThis = false; } else { paintThis = true; }
|
||||
}
|
||||
|
||||
if (paintThis === true) { paintThis = false; } else { paintThis = true; }
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] plotStartFinishLines -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function plotChart() {
|
||||
|
||||
try {
|
||||
|
||||
let userPosition = getUserPosition()
|
||||
let userPositionDate = userPosition.point.x
|
||||
|
||||
for (let k = 0; k < competition.participants.length; k++) {
|
||||
|
||||
let point = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
let upLabel = "";
|
||||
|
||||
let participant = competition.participants[k];
|
||||
let plotElements = participant.plotElements;
|
||||
|
||||
if (plotElements !== undefined) {
|
||||
|
||||
let profileIntervalCounter = 0;
|
||||
let previousPoint;
|
||||
|
||||
for (let i = 0; i < plotElements.length; i++) {
|
||||
|
||||
record = plotElements[i];
|
||||
|
||||
point = {
|
||||
x: record.date,
|
||||
y: record.combinedProfitsB * 100
|
||||
};
|
||||
|
||||
upLabel = "ROI: " + Math.trunc(record.combinedProfitsB * 10000) / 10000 + " %";
|
||||
|
||||
point = timeLineCoordinateSystem.transformThisPoint(point);
|
||||
|
||||
point.y = point.y - thisObject.container.frame.height / 2;
|
||||
|
||||
point = transformThisPoint(point, thisObject.container);
|
||||
|
||||
if (point.x < viewPort.visibleArea.bottomLeft.x || point.x > viewPort.visibleArea.bottomRight.x) { continue; }
|
||||
|
||||
point = viewPort.fitIntoVisibleArea(point);
|
||||
|
||||
let isCurrentRecord = false;
|
||||
|
||||
if (userPositionDate >= record.date - timePeriod / 2 && userPositionDate <= record.date + timePeriod / 2 - 1) {
|
||||
isCurrentRecord = true;
|
||||
}
|
||||
|
||||
let opacity = '0.2';
|
||||
|
||||
let radius = 2;
|
||||
|
||||
browserCanvasContext.lineWidth = 1;
|
||||
|
||||
|
||||
/* Circles */
|
||||
|
||||
if (thisObject.payload[k].profile.plot === true) {
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
|
||||
|
||||
if (isCurrentRecord === false) {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + fileStyles[k] + ', ' + 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();
|
||||
|
||||
}
|
||||
|
||||
/* Since there is at least some point plotted, then the profile should be visible. */
|
||||
|
||||
thisObject.payload[k].profile.visible = true;
|
||||
|
||||
/* Line */
|
||||
|
||||
if (previousPoint !== undefined && thisObject.payload[k].profile.plot === true) {
|
||||
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + fileStyles[k] + ', ' + opacity + ')';
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(previousPoint.x, previousPoint.y);
|
||||
browserCanvasContext.lineTo(point.x, point.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
}
|
||||
|
||||
previousPoint = {
|
||||
x: point.x,
|
||||
y: point.y
|
||||
};
|
||||
|
||||
/* Image */
|
||||
|
||||
if (thisObject.payload[k].profile.plot === true) {
|
||||
|
||||
profileIntervalCounter++;
|
||||
|
||||
if (profileIntervalCounter === 25) {
|
||||
|
||||
profileIntervalCounter = 0;
|
||||
|
||||
if (participant.profilePicture !== undefined) {
|
||||
|
||||
let imageId = participant.devTeam + "." + participant.profilePicture;
|
||||
imageSize = 15;
|
||||
|
||||
if (imageId !== undefined) {
|
||||
|
||||
let image = document.getElementById(imageId);
|
||||
|
||||
if (image !== null) {
|
||||
|
||||
let offset = imageSize * 1.5;
|
||||
|
||||
if (point.y > viewPort.visibleArea.bottomLeft.y / 2) { offset = - offset; }
|
||||
|
||||
/* The line */
|
||||
|
||||
browserCanvasContext.lineWidth = 0.3;
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(point.x, point.y + offset);
|
||||
browserCanvasContext.lineTo(point.x, point.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
/* The Image */
|
||||
|
||||
browserCanvasContext.drawImage(image, point.x - imageSize / 2, point.y - imageSize / 2 + offset, imageSize, imageSize);
|
||||
|
||||
/* Now the border */
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
opacity = '0.5';
|
||||
|
||||
browserCanvasContext.lineWidth = 1;
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
|
||||
|
||||
let radius = imageSize / 2 + 2;
|
||||
|
||||
browserCanvasContext.arc(point.x, point.y + offset, radius, 0, Math.PI * 2, true);
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
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[k].profile.position.x = point.x;
|
||||
thisObject.payload[k].profile.position.y = point.y;
|
||||
thisObject.payload[k].profile.upLabel = upLabel;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"displayName": "Plotters ROI",
|
||||
"codeName": "PlottersROI",
|
||||
"devTeam": "AAMasters",
|
||||
"modules": [
|
||||
{
|
||||
"codeName": "CombinedProfits",
|
||||
"moduleName": "CombinedProfits",
|
||||
"description": "Plots participants of a competition by the ROI each one had over time.",
|
||||
"panels": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Submodule Plotters/AAMasters/plotters/Plotters-Stairs-Patterns deleted from f2c3d2ad39.
Submodule Plotters/AAMasters/plotters/Plotters-Trading deleted from 316a2a8476.
Submodule Plotters/AAMasters/plotters/Plotters-Trading-Simulation deleted from 54f9c8d647.
Submodule Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve deleted from df092daaa2.
Generated
+66
@@ -199,6 +199,11 @@
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz",
|
||||
"integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg=="
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
@@ -245,6 +250,20 @@
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"event-stream": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
|
||||
"integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
|
||||
"requires": {
|
||||
"duplexer": "~0.1.1",
|
||||
"from": "~0",
|
||||
"map-stream": "~0.1.0",
|
||||
"pause-stream": "0.0.11",
|
||||
"split": "0.3",
|
||||
"stream-combiner": "~0.0.4",
|
||||
"through": "~2.3.1"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
||||
@@ -305,6 +324,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"from": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
|
||||
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -486,6 +510,11 @@
|
||||
"p-defer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"map-stream": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
|
||||
"integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ="
|
||||
},
|
||||
"mem": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
||||
@@ -683,6 +712,22 @@
|
||||
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
|
||||
"integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA="
|
||||
},
|
||||
"pause-stream": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
|
||||
"requires": {
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"ps-tree": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz",
|
||||
"integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==",
|
||||
"requires": {
|
||||
"event-stream": "=3.3.4"
|
||||
}
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
@@ -730,11 +775,27 @@
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
||||
},
|
||||
"split": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
|
||||
"integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
|
||||
"requires": {
|
||||
"through": "2"
|
||||
}
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"stream-combiner": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
|
||||
"integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
|
||||
"requires": {
|
||||
"duplexer": "~0.1.1"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
@@ -770,6 +831,11 @@
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
|
||||
+2
-1
@@ -11,7 +11,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@superalgos/mqservice": "0.0.12",
|
||||
"axios": "0.19.0",
|
||||
"dotenv": "8.0.0",
|
||||
"axios": "0.19.0"
|
||||
"ps-tree": "^1.2.0"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
|
||||
require('dotenv').config()
|
||||
require('dotenv').config();
|
||||
const { spawn } = require('child_process');
|
||||
const psTree = require('ps-tree');
|
||||
|
||||
CONSOLE_LOG = process.env.CONSOLE_LOG === 'true'
|
||||
CONSOLE_ERROR_LOG = process.env.CONSOLE_ERROR_LOG === 'true'
|
||||
@@ -33,8 +35,10 @@ global.CUSTOM_FAIL_RESPONSE = {
|
||||
let http = require('http')
|
||||
let port = process.env.PORT || 1337
|
||||
let isHttpServerStarted = false
|
||||
let cloneExecutorChildProcess
|
||||
|
||||
startHtttpServer()
|
||||
startCloneExecutor()
|
||||
|
||||
function startHtttpServer() {
|
||||
if (CONSOLE_LOG === true) { console.log('[INFO] server -> startHtttpServer -> Entering function.') }
|
||||
@@ -49,6 +53,49 @@ function startHtttpServer() {
|
||||
}
|
||||
}
|
||||
|
||||
function startCloneExecutor() {
|
||||
if (CONSOLE_LOG === true) { console.log('[INFO] server -> startCloneExecutor -> Entering function.') };
|
||||
|
||||
let path = process.env.CLONE_EXECUTOR_PATH + '/run.js'
|
||||
cloneExecutorChildProcess = spawn('node', [path], { shell: true, stdio: 'inherit' });
|
||||
|
||||
cloneExecutorChildProcess.on('error', (err) => {
|
||||
console.log(`[ERROR] server -> startCloneExecutor -> Clone Executor exited with error ${err}`);
|
||||
});
|
||||
cloneExecutorChildProcess.on('close', (code, signal) => {
|
||||
console.log(`[INFO] CloneExecutor process terminated.`);
|
||||
});
|
||||
}
|
||||
|
||||
function stopCloneExecutor() {
|
||||
if (CONSOLE_LOG === true) { console.log('[INFO] server -> stopCloneExecutor -> Entering function.') };
|
||||
|
||||
var kill = function (pid, signal, callback) {
|
||||
signal = signal || 'SIGKILL';
|
||||
callback = callback || function () { };
|
||||
var killTree = true;
|
||||
if (killTree) {
|
||||
psTree(pid, function (err, children) {
|
||||
[pid].concat(
|
||||
children.map(function (p) {
|
||||
return p.PID;
|
||||
})
|
||||
).forEach(function (tpid) {
|
||||
try { process.kill(tpid, signal) }
|
||||
catch (ex) { }
|
||||
});
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
try { process.kill(pid, signal) }
|
||||
catch (ex) { }
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
kill(cloneExecutorChildProcess.pid);
|
||||
}
|
||||
|
||||
function onBrowserRequest(request, response) {
|
||||
if (CONSOLE_LOG === true && request.url.indexOf('NO-LOG') === -1) { console.log('[INFO] server -> onBrowserRequest -> request.url = ' + request.url) }
|
||||
|
||||
@@ -75,6 +122,28 @@ function onBrowserRequest(request, response) {
|
||||
|
||||
switch (requestParameters[1]) {
|
||||
|
||||
case 'RestartCloneExecutor':
|
||||
{
|
||||
try {
|
||||
stopCloneExecutor();
|
||||
startCloneExecutor();
|
||||
respondWithContent('Restart Clone Executor ok.', response)
|
||||
} catch (err) {
|
||||
respondWithContent('There was an error restarting clone executor.', response)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
case 'StopCloneExecutor':
|
||||
{
|
||||
try {
|
||||
stopCloneExecutor();
|
||||
respondWithContent('Stop Clone Executor ok.', response)
|
||||
} catch (err) {
|
||||
respondWithContent('There was an error stopping clone executor.', response)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'MQService':
|
||||
{
|
||||
let filePath = './node_modules/@superalgos/mqservice/orderLifeCicle/webDependency.js'
|
||||
|
||||
Reference in new issue
Block a user