Merge remote-tracking branch 'PlotterTrading/develop' into develop

This commit is contained in:
Luis Fernando Molina committed 2020-11-20 18:55:10 +01:00
commit 594ed79a08
12 files changed
+1806

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
+11
View File
@@ -0,0 +1,11 @@
.vs/*
obj/*
bin/*
*.config
*.log
*.cache
node_modules/*
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+727
View File
@@ -0,0 +1,727 @@
function newAAMastersPlottersTradingDetails() {
let thisObject = {
// Main functions and properties.
initialize: initialize,
container: undefined,
getContainer: getContainer,
setTimePeriod: setTimePeriod,
setDatetime: setDatetime,
draw: draw
};
/* 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 timeLineCoordinateSystemFrame = newTimeLineCoordinateSystem(); // This chart uses this extra object.
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 fileCache; // This object will provide the different Market Files at different Time Periods.
let fileCursorCache; // This object will provide the different File Cursors at different Time Periods.
/* these are module specific variables: */
let volumes = []; // Here we keep the volumes to be ploted every time the Draw() function is called by the AAWebPlatform.
return thisObject;
function initialize(pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) {
let cursorCacheInProgress = false;
let finaleStepsInProgress = false;
datetime = pDatetime;
timePeriod = pTimePeriod;
fileCache = newFileCache();
fileCache.initialize("AAMasters", "AAOlivia", "Market Volumes", "Market Volumes", pExchange, pMarket, onFileReady);
function onFileReady() {
let newMarketFile = fileCache.getFile(ONE_DAY_IN_MILISECONDS);
if (newMarketFile !== undefined) {
marketFile = newMarketFile;
initializeFileCursorCache();
}
}
function initializeFileCursorCache() {
if (cursorCacheInProgress === false) {
cursorCacheInProgress = true;
fileCursorCache = newFileCursorCache();
fileCursorCache.initialize("AAMasters", "AAOlivia", "Daily Volumes", "Daily Volumes", pExchange, pMarket, pDatetime, pTimePeriod, onFileCursorReady);
}
}
function onFileCursorReady() {
recalculate();
let newFileCursor = fileCursorCache.getFileCursor(pTimePeriod);
if (newFileCursor !== undefined) { // if the file ready is the one we need then it and we dont have it yet, then we will continue here.
let stringDate = datetime.getUTCFullYear() + '-' + pad(datetime.getUTCMonth() + 1, 2) + '-' + pad(datetime.getUTCDate(), 2);
let dailyFile = newFileCursor.files.get(stringDate);
if (dailyFile !== undefined) {
if (finaleStepsInProgress === false) {
finaleStepsInProgress = true;
fileCursor = newFileCursor;
recalculateScaleX();
recalculate();
recalculateScaleY();
viewPort.eventHandler.listenToEvent("Zoom Changed", onZoomChanged);
canvas.eventHandler.listenToEvent("Drag Finished", onDragFinished);
callBackFunction();
}
}
}
}
}
function getContainer(point) {
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;
}
}
function setTimePeriod(pTimePeriod) {
timePeriod = pTimePeriod;
if (timePeriod >= _1_HOUR_IN_MILISECONDS) {
let newMarketFile = fileCache.getFile(pTimePeriod);
if (newMarketFile !== undefined) {
marketFile = newMarketFile;
recalculate();
}
} else {
fileCursorCache.setTimePeriod(pTimePeriod);
fileCursorCache.setDatetime(datetime);
let newFileCursor = fileCursorCache.getFileCursor(pTimePeriod);
if (newFileCursor !== undefined) {
fileCursor = newFileCursor;
recalculate();
}
}
if (timePeriod === _1_HOUR_IN_MILISECONDS) {
fileCursorCache.setTimePeriod(pTimePeriod);
fileCursorCache.setDatetime(datetime);
}
}
function setDatetime(pDatetime) {
datetime = pDatetime;
}
function draw() {
this.container.frame.draw();
if (timePeriod < _1_HOUR_IN_MILISECONDS) {
if (Math.random() * 1000 > 995) {
recalculateScaleX();
recalculate();
recalculateScaleY();
}
}
plotChart();
}
function recalculate() {
if (timePeriod >= _1_HOUR_IN_MILISECONDS) {
recalculateUsingMarketFiles();
} else {
recalculateUsingDailyFiles();
}
thisObject.container.eventHandler.raiseEvent("Volumes Changed", volumes);
}
function recalculateUsingDailyFiles() {
if (fileCursor.files.size === 0) { 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());
volumes = [];
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 volume = {
amountBuy: 0,
amountSell: 0,
begin: undefined,
end: undefined
};
volume.amountBuy = dailyFile[i][0];
volume.amountSell = dailyFile[i][1];
volume.begin = dailyFile[i][2];
volume.end = dailyFile[i][3];
if (volume.begin >= farLeftDate.valueOf() && volume.end <= farRightDate.valueOf()) {
volumes.push(volume);
if (datetime.valueOf() >= volume.begin && datetime.valueOf() <= volume.end) {
thisObject.container.eventHandler.raiseEvent("Current Candle Changed", thisObject.currentCandle);
}
}
}
}
currentDate = new Date(currentDate.valueOf() + ONE_DAY_IN_MILISECONDS);
}
/* Lests check if all the visible screen is going to be covered by volumes. */
let lowerEnd = leftDate.valueOf();
let upperEnd = rightDate.valueOf();
if (volumes.length > 0) {
if (volumes[0].begin > lowerEnd || volumes[volumes.length - 1].end < upperEnd) {
setTimeout(recalculate, 2000);
//console.log("File missing while calculating volumes, scheduling a recalculation in 2 seconds.");
}
}
//console.log("Olivia > recalculateUsingDailyFiles > total volumes generated : " + volumes.length);
}
function recalculateUsingMarketFiles() {
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);
volumes = [];
for (let i = 0; i < marketFile.length; i++) {
let volume = {
amountBuy: 0,
amountSell: 0,
begin: undefined,
end: undefined
};
volume.amountBuy = marketFile[i][0];
volume.amountSell = marketFile[i][1];
volume.begin = marketFile[i][2];
volume.end = marketFile[i][3];
if (volume.begin >= leftDate.valueOf() && volume.end <= rightDate.valueOf()) {
volumes.push(volume);
if (datetime.valueOf() >= volume.begin && datetime.valueOf() <= volume.end) {
thisObject.container.eventHandler.raiseEvent("Current Volume Changed", thisObject.currentCandle);
}
}
}
//console.log("Olivia > recalculateUsingMarketFiles > total volumes generated : " + volumes.length);
}
function recalculateScaleX() {
var minValue = {
x: MIN_PLOTABLE_DATE.valueOf()
};
var maxValue = {
x: MAX_PLOTABLE_DATE.valueOf()
};
timeLineCoordinateSystem.initializeX(
minValue,
maxValue,
thisObject.container.frame.width
);
timeLineCoordinateSystemFrame.initializeX(
minValue,
maxValue,
thisObject.container.frame.width
);
}
function recalculateScaleY() {
var minValue = {
y: 0
};
var maxValue = {
y: 0
};
let timePeriodRatio = ONE_DAY_IN_MILISECONDS / timePeriod;
maxValue.y = getMaxVolume() / (timePeriodRatio / 10);
timeLineCoordinateSystem.initializeY(
minValue,
maxValue,
viewPort.visibleArea.bottomRight.y - viewPort.visibleArea.topLeft.y
);
timeLineCoordinateSystemFrame.initializeY(
minValue,
maxValue,
thisObject.container.frame.height
);
function getMaxVolume() {
let maxValue = 0;
for (var i = 0; i < marketFile.length; i++) {
let currentMax = (marketFile[i][0] + marketFile[i][1]) * 4;
if (maxValue < currentMax) {
maxValue = currentMax;
}
}
return maxValue;
}
}
function plotChart() {
if (volumes.length > 0) {
/* Now we calculate and plot the volumes */
let visibleHeight = viewPort.visibleArea.bottomRight.y - viewPort.visibleArea.topLeft.y;
let frameCorner1 = {
x: 0,
y: 0
};
let frameCorner2 = {
x: thisObject.container.frame.width,
y: thisObject.container.frame.height
};
/* Now the transformations. */
frameCorner1 = transformThisPoint(frameCorner1, thisObject.container.frame.container);
frameCorner2 = transformThisPoint(frameCorner2, thisObject.container.frame.container);
let frameHeightInViewPort = frameCorner2.y - frameCorner1.y;
if (volumes.length > 0) {
for (var i = 0; i < volumes.length; i++) {
volume = volumes[i];
let volumePointA1;
let volumePointA2;
let volumePointA3;
let volumePointA4;
function calculateBuys(plot, height) {
volumePointA1 = {
x: volume.begin + timePeriod / 7 * 2,
y: 0
};
volumePointA2 = {
x: volume.begin + timePeriod / 7 * 2,
y: volume.amountBuy
};
volumePointA3 = {
x: volume.begin + timePeriod / 7 * 5,
y: volume.amountBuy
};
volumePointA4 = {
x: volume.begin + timePeriod / 7 * 5,
y: 0
};
volumePointA1 = plot.transformThisPoint(volumePointA1);
volumePointA2 = plot.transformThisPoint(volumePointA2);
volumePointA3 = plot.transformThisPoint(volumePointA3);
volumePointA4 = plot.transformThisPoint(volumePointA4);
volumePointA1 = transformThisPoint(volumePointA1, thisObject.container);
volumePointA2 = transformThisPoint(volumePointA2, thisObject.container);
volumePointA3 = transformThisPoint(volumePointA3, thisObject.container);
volumePointA4 = transformThisPoint(volumePointA4, thisObject.container);
let baseIncrement = (volumePointA3.x - volumePointA1.x) * WIDHTER_VOLUME_BAR_BASE_FACTOR;
volumePointA1.x = volumePointA1.x - baseIncrement;
volumePointA4.x = volumePointA4.x + baseIncrement;
if (volumePointA4.x < viewPort.visibleArea.bottomLeft.x || volumePointA1.x > viewPort.visibleArea.bottomRight.x) {
return false;
}
return true;
}
if (calculateBuys(timeLineCoordinateSystemFrame, thisObject.container.frame.height) === false) { continue; } // We try to see if it fits in the visible area.
if (volumePointA1.y > viewPort.visibleArea.bottomLeft.y && frameHeightInViewPort > visibleHeight * 2 / 3) {
if (calculateBuys(timeLineCoordinateSystem, visibleHeight) === false) { continue; } // We snap t to the view port.
/* Now we set the real value of y. */
volumePointA1.y = viewPort.visibleArea.bottomRight.y;
volumePointA2.y = viewPort.visibleArea.bottomRight.y - volume.amountBuy * timeLineCoordinateSystem.scale.y;
volumePointA3.y = viewPort.visibleArea.bottomRight.y - volume.amountBuy * timeLineCoordinateSystem.scale.y;
volumePointA4.y = viewPort.visibleArea.bottomRight.y;
}
let volumePointB1;
let volumePointB2;
let volumePointB3;
let volumePointB4;
function calculateSells(plot, height) {
volumePointB1 = {
x: volume.begin + timePeriod / 7 * 2,
y: height
};
volumePointB2 = {
x: volume.begin + timePeriod / 7 * 2,
y: height - volume.amountSell
};
volumePointB3 = {
x: volume.begin + timePeriod / 7 * 5,
y: height - volume.amountSell
};
volumePointB4 = {
x: volume.begin + timePeriod / 7 * 5,
y: height
};
volumePointB1 = plot.transformThisPoint2(volumePointB1);
volumePointB2 = plot.transformThisPoint2(volumePointB2);
volumePointB3 = plot.transformThisPoint2(volumePointB3);
volumePointB4 = plot.transformThisPoint2(volumePointB4);
volumePointB1 = transformThisPoint(volumePointB1, thisObject.container);
volumePointB2 = transformThisPoint(volumePointB2, thisObject.container);
volumePointB3 = transformThisPoint(volumePointB3, thisObject.container);
volumePointB4 = transformThisPoint(volumePointB4, thisObject.container);
}
calculateSells(timeLineCoordinateSystemFrame, thisObject.container.frame.height); // We try to see if it fits in the visible area.
if (volumePointB1.y < viewPort.visibleArea.topLeft.y && frameHeightInViewPort > visibleHeight * 2 / 3) {
calculateSells(timeLineCoordinateSystem, visibleHeight); // We snap it to the view port.
/* Now we set the real value of y. */
volumePointB1.y = viewPort.visibleArea.topLeft.y;
volumePointB2.y = viewPort.visibleArea.topLeft.y + volume.amountSell * timeLineCoordinateSystem.scale.y;
volumePointB3.y = viewPort.visibleArea.topLeft.y + volume.amountSell * timeLineCoordinateSystem.scale.y;
volumePointB4.y = viewPort.visibleArea.topLeft.y;
}
/* We put a wider base */
let baseIncrement = (volumePointB3.x - volumePointB1.x) * WIDHTER_VOLUME_BAR_BASE_FACTOR;
volumePointB1.x = volumePointB1.x - baseIncrement;
volumePointB4.x = volumePointB4.x + baseIncrement;
/* We put a less wider top */
let baseDencrement = (volumePointA3.x - volumePointA2.x) * LESS_WIDHTER_VOLUME_BAR_TOP_FACTOR;
volumePointA2.x = volumePointA2.x + baseDencrement;
volumePointA3.x = volumePointA3.x - baseDencrement;
volumePointB2.x = volumePointB2.x + baseDencrement;
volumePointB3.x = volumePointB3.x - baseDencrement;
/* Everything must fit within the visible area */
volumePointA1 = viewPort.fitIntoVisibleArea(volumePointA1);
volumePointA2 = viewPort.fitIntoVisibleArea(volumePointA2);
volumePointA3 = viewPort.fitIntoVisibleArea(volumePointA3);
volumePointA4 = viewPort.fitIntoVisibleArea(volumePointA4);
volumePointB1 = viewPort.fitIntoVisibleArea(volumePointB1);
volumePointB2 = viewPort.fitIntoVisibleArea(volumePointB2);
volumePointB3 = viewPort.fitIntoVisibleArea(volumePointB3);
volumePointB4 = viewPort.fitIntoVisibleArea(volumePointB4);
/* Everything must fit within the Frame. We know that that is equivalent to say that each bar con not be higher than the base of the opposite . */
if (volumePointA2.y < volumePointB1.y) {
volumePointA2.y = volumePointB1.y;
volumePointA3.y = volumePointB1.y;
}
if (volumePointB2.y > volumePointA1.y) {
volumePointB2.y = volumePointA1.y;
volumePointB3.y = volumePointA1.y;
}
/* Now the drawing of the volume bars*/
browserCanvasContext.beginPath();
browserCanvasContext.moveTo(volumePointA1.x, volumePointA1.y);
browserCanvasContext.lineTo(volumePointA2.x, volumePointA2.y);
browserCanvasContext.lineTo(volumePointA3.x, volumePointA3.y);
browserCanvasContext.lineTo(volumePointA4.x, volumePointA4.y);
browserCanvasContext.closePath();
if (datetime !== undefined) {
let dateValue = datetime.valueOf();
if (dateValue >= volume.begin && dateValue <= volume.end) {
browserCanvasContext.fillStyle = 'rgba(255, 233, 31, 0.40)'; // Current bar accroding to time
} else {
browserCanvasContext.fillStyle = 'rgba(64, 217, 26, 0.40)';
}
} else {
browserCanvasContext.fillStyle = 'rgba(64, 217, 26, 0.40)';
}
browserCanvasContext.fill();
browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, 0.40)';
browserCanvasContext.lineWidth = 1;
browserCanvasContext.stroke();
browserCanvasContext.beginPath();
browserCanvasContext.moveTo(volumePointB1.x, volumePointB1.y);
browserCanvasContext.lineTo(volumePointB2.x, volumePointB2.y);
browserCanvasContext.lineTo(volumePointB3.x, volumePointB3.y);
browserCanvasContext.lineTo(volumePointB4.x, volumePointB4.y);
browserCanvasContext.closePath();
if (datetime !== undefined) {
let dateValue = datetime.valueOf();
if (dateValue >= volume.begin && dateValue <= volume.end) {
browserCanvasContext.fillStyle = 'rgba(255, 233, 31, 0.40)'; // Current candle accroding to time
} else {
browserCanvasContext.fillStyle = 'rgba(219, 18, 18, 0.40)';
}
} else {
browserCanvasContext.fillStyle = 'rgba(219, 18, 18, 0.40)';
}
browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, 0.40)';
browserCanvasContext.fill();
browserCanvasContext.lineWidth = 1;
browserCanvasContext.stroke();
if (datetime !== undefined) {
let dateValue = datetime.valueOf();
if (dateValue >= volume.begin && dateValue <= volume.end) {
let buyInfo = {
baseWidth: volumePointA4.x - volumePointA1.x,
topWidth: volumePointA3.x - volumePointA2.x,
height: volumePointA2.y - volumePointA1.y
};
let sellInfo = {
baseWidth: volumePointB4.x - volumePointB1.x,
topWidth: volumePointB3.x - volumePointB2.x,
height: volumePointB2.y - volumePointB1.y
};
let currentVolume = {
buyInfo: buyInfo,
sellInfo: sellInfo,
period: timePeriod,
innerVolumeBar: volume
};
thisObject.container.eventHandler.raiseEvent("Current Volume Info Changed", currentVolume);
}
}
}
}
}
}
function onZoomChanged(event) {
recalculateScaleX();
recalculate();
recalculateScaleY();
}
function onDragFinished() {
recalculateScaleX();
recalculate();
recalculateScaleY();
}
}
+926
View File
@@ -0,0 +1,926 @@
function newAAMastersPlottersTradingHistory() {
const MODULE_NAME = "AAMasters Plotters Trading History";
const INTENSIVE_LOG = false;
const ERROR_LOG = true;
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,
recalculateScale: recalculateScale,
draw: draw,
payload: {
profile: {
position: {
x: 0,
y: 0
},
visible: false
},
notes: []
}
};
/* 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 fileSequence;
let plotElements = []; // This is where the elements to be plotted are stored before plotting.
let plotLines = []; // Here we store the lines of open positions.
let notes = []; // Here we store the notes with messages from the bot.
let notesChangedEventRaised = true; // This controls when to raise the event that notes changed.
let previousNotesSetKey;
let currentNotesSetKey;
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;
plotElements = undefined;
plotLines = undefined;
notes = undefined;
} catch (err) {
if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err.message = " + err.message); }
}
}
function initialize(pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) {
try {
datetime = pDatetime;
timePeriod = pTimePeriod;
fileSequence = pStorage.fileSequences[0];
recalculate(callBackFunction);
recalculateScale(callBackFunction);
filesUpdatedEventSubscriptionId = fileSequence.eventHandler.listenToEvent("Files Updated", onFilesUpdated);// Only the first sequence is supported right now.
offsetChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged);
immensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () {
recalculate(callBackFunction);
recalculateScale(callBackFunction);
})
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE);
} catch (err) {
if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err.stack); }
callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE);
}
}
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] initialize -> err = " + err.stack); }
}
}
function onFilesUpdated() {
recalculate();
}
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] setTimePeriod -> err = " + err.stack); }
}
}
function onOffsetChanged() {
if (Math.random() * 100 > 95) {
recalculate()
};
}
function recalculate(callBackFunction) {
try {
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 = [];
/* 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]
};
history.push(newHistoryRecord);
lastRecordPushed = i;
/* Here we build the lines. */
if (timePeriod <= 1 * 60 * 1000) {
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);
}
}
}
/* 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]
};
history.push(newHistoryRecord);
}
/* 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;
thisObject.container.eventHandler.raiseEvent("History Changed", history);
} catch (err) {
if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); }
callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE);
}
}
function recalculateScale(callBackFunction) {
try {
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: 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
);
function getMaxRate() {
try {
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.stack); }
callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE);
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err.stack); }
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.stack); }
}
}
function plotChart() {
try {
let userPosition = getUserPosition()
let userPositionDate = userPosition.point.x
let point = {
x: 0,
y: 0
};
let history;
for (let j = 0; j < plotElements.length; j++) {
let history = plotElements[j];
for (let i = 0; i < history.length; i++) {
record = history[i];
let timestamp = Math.trunc(record.date / timePeriod) * timePeriod + timePeriod / 2;
point = {
x: timestamp,
y: record.marketRate
};
point = timeLineCoordinateSystem.transformThisPoint(point);
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 radius = 3;
let opacity = '0.2';
browserCanvasContext.lineWidth = 1;
/* Outer Circle */
browserCanvasContext.beginPath();
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
if (isCurrentRecord === false) {
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.LIGHT + ', ' + opacity + ')';
} else {
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + 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.5';
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.5';
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.5';
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.5';
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 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. */
currentNotesSetKey = "";
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 / 2) * (-1) || note.position.x > (viewPort.visibleArea.bottomRight.x) * (1.5)) {
note.visible = false;
currentNotesSetKey = currentNotesSetKey + "0";
} else {
note.visible = true;
currentNotesSetKey = currentNotesSetKey + "1";
}
}
if (notesChangedEventRaised === false) {
/* In this case the event is raised because we might have a different set of notes. */
thisObject.container.eventHandler.raiseEvent("Notes Changed", notes);
thisObject.payload.notes = notes;
notesChangedEventRaised = true;
} else {
if (currentNotesSetKey !== previousNotesSetKey) {
/* In this case the event is raised because the visibility of some of the notes changed. */
thisObject.container.eventHandler.raiseEvent("Notes Changed", notes);
thisObject.payload.notes = notes;
previousNotesSetKey = currentNotesSetKey;
}
}
}
/*
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;
} catch (err) {
if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); }
}
}
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

+24
View File
@@ -0,0 +1,24 @@
Financial Beings License
Collective Copyright by the Advanced Algos Community
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software including without limitation the rights to use, copy, modify,
merge, publish, distribute and sublicense copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following
conditions:
1. Using, copying, modifying, publishing, distributing and sublicensing rights
are restricted to the Advanced Algos Platform, meaning the rights granted can
only be exercised through the Advanced Algos Service.
2. The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+25
View File
@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "Project", "Project.njsproj", "{096B35AD-F86F-47B9-A99F-04CA93397DA8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{096B35AD-F86F-47B9-A99F-04CA93397DA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{096B35AD-F86F-47B9-A99F-04CA93397DA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{096B35AD-F86F-47B9-A99F-04CA93397DA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{096B35AD-F86F-47B9-A99F-04CA93397DA8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E75EDC9D-66A7-4C54-8EA1-5ADC148CACA8}
EndGlobalSection
EndGlobal
+70
View File
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{096b35ad-f86f-47b9-a99f-04ca93397da8}</ProjectGuid>
<ProjectHome />
<ProjectView>ShowAllFiles</ProjectView>
<StartupFile>History.js</StartupFile>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<Name>Project</Name>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
<PropertyGroup Condition="'$(Configuration)' == 'Release'" />
<ItemGroup>
<Compile Include="History.js" />
<Compile Include="Details.js">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Include="this.plotter.config.json" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<!--Do not delete the following Import Project. While this appears to do nothing it is a marker for setting TypeScript properties before our import that depends on them.-->
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="False" />
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:48022/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://localhost:1337</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}" User="">
<WebProjectProperties>
<StartPageUrl>
</StartPageUrl>
<StartAction>CurrentPage</StartAction>
<AspNetDebugging>True</AspNetDebugging>
<SilverlightDebugging>False</SilverlightDebugging>
<NativeDebugging>False</NativeDebugging>
<SQLDebugging>False</SQLDebugging>
<ExternalProgram>
</ExternalProgram>
<StartExternalURL>
</StartExternalURL>
<StartCmdLineArguments>
</StartCmdLineArguments>
<StartWorkingDirectory>
</StartWorkingDirectory>
<EnableENC>False</EnableENC>
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
+1
View File
@@ -0,0 +1 @@
# AAMariam-Plotter
+20
View File
@@ -0,0 +1,20 @@
{
"displayName": "Plotters Trading",
"codeName": "PlottersTrading",
"devTeam": "AAMasters",
"modules": [
{
"codeName": "Details",
"moduleName": "Details",
"description": "Plots trading decitions in an easy to understand way.",
"panels": []
},
{
"codeName": "History",
"moduleName": "History",
"description": "Plots trading history.",
"profilePicture": "History.png",
"panels": []
}
]
}