More Dashboard bottom optimizations
This commit is contained in:
parent
16fada1443
commit
08554da6ee
|
@ -33,11 +33,6 @@
|
|||
$("#baglist-refresh-icon").html('<i class="fa fa-circle-o-notch fa-spin fa-fw" data-toggle="tooltip" data-placement="top" title="Loading fresh data..."></i>');
|
||||
$("#buylist-refresh-icon").html('<i class="fa fa-circle-o-notch fa-spin fa-fw" data-toggle="tooltip" data-placement="top" title="Loading fresh data..."></i>');
|
||||
|
||||
// Add the page refresh code here
|
||||
setTimeout(function(){
|
||||
location.reload();
|
||||
}, 60 * 60 * 1000); // 60 minutes
|
||||
|
||||
// Clear exisitng interval to stop multiple attempts to load at the same time.
|
||||
if (intervalDashboardTop != null)
|
||||
{
|
||||
|
@ -69,13 +64,16 @@
|
|||
|
||||
var loadDashboardBottom = function () {
|
||||
//destroy all d3 svg graph to avoid memory leak
|
||||
//$(".nvtooltip").remove();
|
||||
//$("svg > *").remove();
|
||||
//$("svg").remove();
|
||||
//nv.charts = {};
|
||||
//nv.graphs = [];
|
||||
//nv.logs = {};
|
||||
//nv.tooltip = {};
|
||||
setTimeout(function()
|
||||
{
|
||||
$(".nvtooltip").remove();
|
||||
$("svg > *").remove();
|
||||
$("svg").remove();
|
||||
nv.charts = {};
|
||||
nv.graphs = [];
|
||||
nv.logs = {};
|
||||
nv.tooltip = {};
|
||||
}, 10 * intervalDashboardBottom * 1000); // 10 times intervalDashboardBottom in milliseconds
|
||||
|
||||
// Clear exisitng interval to stop multiple attempts to load at the same time.
|
||||
if (intervalDashboardBottom != null)
|
||||
|
|
|
@ -196,21 +196,21 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-4 col-form-label">Market Trend Graph Interval Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The time interval for the market trend graph between points."></i></label>
|
||||
<label class="col-md-4 col-form-label">Market Trend Graph Interval Minutes <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The time interval for the market trend graph (Dashboard and Sales Analyzer) between data points. Very small intervals on large timeframe graphs can significantly impact performance."></i></label>
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="Monitor_GraphIntervalMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes.ToString(new System.Globalization.CultureInfo("en-US"))">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-md-4 col-form-label">Market Trend Graph Max Timeframe <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the market trends graph in hours."></i></label>
|
||||
<label class="col-md-4 col-form-label">Market Trend Graph Max Timeframe <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the market trends graph (Dashboard and Sales Analyzer) in hours. Large timeframe graphs can significantly impact performance."></i></label>
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="Monitor_GraphMaxTimeframeHours" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours.ToString(new System.Globalization.CultureInfo("en-US"))">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-md-4 col-form-label">Daily Profit Graph Max Timeframe <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the daily profits graph on the dashboard in days."></i></label>
|
||||
<label class="col-md-4 col-form-label">Daily Profit Graph Max Timeframe <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This defines the total timeframe for the daily profits graph on the dashboard in days. Large timeframes can significantly impact performance."></i></label>
|
||||
<div class="col-md-8">
|
||||
<input type="text" class="form-control" name="Monitor_ProfitsMaxTimeframeDays" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.ProfitsMaxTimeframeDays.ToString(new System.Globalization.CultureInfo("en-US"))">
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card-box">
|
||||
<h4 class="m-t-0 header-title">PTMagic Status <small id="last-refresh" class="pull-right"></small></h4>
|
||||
@{
|
||||
|
@ -71,7 +72,6 @@
|
|||
@{
|
||||
string maxCostCaption = "Initial";
|
||||
}
|
||||
|
||||
<table class="table table-striped table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -99,35 +99,32 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-7">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card-box">
|
||||
<h4 class="m-t-0 header-title">Settings Active Time (Last 24h)</h4>
|
||||
|
||||
<div id="gsChart24h">
|
||||
<svg style="height:300px;width:100%"></svg>
|
||||
<svg style="height:200px;width:100%"></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
|
||||
<div class="card-box">
|
||||
<h4 class="m-t-0 header-title">Settings Active Time (Last 3 days)</h4>
|
||||
|
||||
<div id="gsChart3d">
|
||||
<svg style="height:300px;width:100%"></svg>
|
||||
<svg style="height:200px;width:100%"></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-box">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card-box">
|
||||
<h4 class="m-t-0 header-title">Global Settings Log</h4>
|
||||
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -159,9 +156,6 @@
|
|||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-5 px-1">
|
||||
<div class="card-box px-2" style="height:305px;">
|
||||
<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"></div>
|
||||
<div class="card-box px-2" style="height:320px;">
|
||||
<h4 class="m-t-0 m-b-20 header-title" style="display: inline;"><b>Market Trend History </b><i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="@Math.Round(Model.DataHours, 1) hours of data available. Currently set to show @Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours hours in general settings."></i></h4>
|
||||
@if (!Model.TrendChartDataJSON.Equals("")) {
|
||||
<div class="trend-chart">
|
||||
<svg style="height: 300px;width: 100%;"></svg>
|
||||
|
@ -22,9 +22,10 @@
|
|||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 px-1">
|
||||
<div class="card-box px-3" style="height:305px;">
|
||||
@*<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"></div>*@
|
||||
<div class="card-box px-3" style="height:320px;">
|
||||
<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"><i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="You dashboard is set to refresh every @Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds seconds in general settings."></i></div>
|
||||
@{
|
||||
string totalCurrentValueString = Model.totalCurrentValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"));
|
||||
if (Model.totalCurrentValue > 100) {
|
||||
|
@ -50,7 +51,8 @@
|
|||
|
||||
<div class="col-md-4 px-1">
|
||||
@*<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"></div>*@
|
||||
<div class="card-box px-2" style="height:305px;">
|
||||
<div class="card-box px-2" style="height:320px;">
|
||||
<h4 class="m-t-0 m-b-20 header-title" style="display: inline;"><b>Daily Profit </b><i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="@Model.ProfitDays days of data available. Currently Set to @Model.PTMagicConfiguration.GeneralSettings.Monitor.ProfitsMaxTimeframeDays days in general settings."></i>
|
||||
@if (!Model.ProfitChartDataJSON.Equals("")) {
|
||||
<div class="profit-chart">
|
||||
<svg style="height:300px;width:100%"></svg>
|
||||
|
@ -65,8 +67,8 @@
|
|||
<div class="row">
|
||||
<div class="col-md-5 px-1">
|
||||
<div class="card-box px-2">
|
||||
<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"></div>
|
||||
<br>
|
||||
@* <div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"></div>
|
||||
<br> *@
|
||||
<h4 class="m-t-0 m-b-20 header-title"><b>Market Trends at @Model.PTMagicConfiguration.GeneralSettings.Application.Exchange</b>
|
||||
<small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)MarketAnalyzer">more</a></small></h4>
|
||||
<table class="table table-sm">
|
||||
|
@ -293,6 +295,22 @@
|
|||
.datum(assetDistributionData)
|
||||
.transition().duration(0)
|
||||
.call(assetDistributionChart);
|
||||
|
||||
// Add mouseleave, and mousemove event listeners to hide tooltip
|
||||
d3.select('.profit-chart').on('mouseleave', function() {
|
||||
d3.select('.nvtooltip').style('opacity', 0);
|
||||
});
|
||||
|
||||
d3.select('body').on('mousemove', function() {
|
||||
var chartBounds = d3.select('.profit-chart')[0][0].getBoundingClientRect();
|
||||
var mouseX = d3.event.clientX;
|
||||
var mouseY = d3.event.clientY;
|
||||
|
||||
if (mouseX < chartBounds.left || mouseX > chartBounds.right || mouseY < chartBounds.top || mouseY > chartBounds.bottom) {
|
||||
d3.select('.nvtooltip').style('opacity', 0);
|
||||
}
|
||||
});
|
||||
|
||||
return assetDistributionChart;
|
||||
});
|
||||
</text>
|
||||
|
@ -325,6 +343,21 @@
|
|||
.datum(trendData)
|
||||
.transition().duration(0)
|
||||
.call(trendChart);
|
||||
// Add mouseleave, and mousemove event listeners to hide tooltip
|
||||
d3.select('.profit-chart').on('mouseleave', function() {
|
||||
d3.select('.nvtooltip').style('opacity', 0);
|
||||
});
|
||||
|
||||
d3.select('body').on('mousemove', function() {
|
||||
var chartBounds = d3.select('.profit-chart')[0][0].getBoundingClientRect();
|
||||
var mouseX = d3.event.clientX;
|
||||
var mouseY = d3.event.clientY;
|
||||
|
||||
if (mouseX < chartBounds.left || mouseX > chartBounds.right || mouseY < chartBounds.top || mouseY > chartBounds.bottom) {
|
||||
d3.select('.nvtooltip').style('opacity', 0);
|
||||
}
|
||||
});
|
||||
|
||||
return trendChart;
|
||||
});
|
||||
</text>
|
||||
|
@ -348,7 +381,7 @@
|
|||
profitChart = nv.models.lineChart();
|
||||
var height = 300;
|
||||
profitChart.useInteractiveGuideline(true);
|
||||
profitChart.xAxis.tickFormat(function (d) { return d3.time.format('%Y/%m/%d')(new Date(d)); });
|
||||
profitChart.xAxis.tickFormat(function (d) { return d3.time.format('%m/%d')(new Date(d)); });
|
||||
profitChart.yAxis.axisLabel('Daily Profit').tickFormat(d3.format(',.2f'));
|
||||
|
||||
profitData = @Html.Raw(Model.ProfitChartDataJSON);
|
||||
|
@ -357,9 +390,54 @@
|
|||
.datum(profitData)
|
||||
.transition().duration(0)
|
||||
.call(profitChart);
|
||||
|
||||
// Add mouseleave, and mousemove event listeners to hide tooltip
|
||||
d3.select('.profit-chart').on('mouseleave', function() {
|
||||
d3.select('.nvtooltip').style('opacity', 0);
|
||||
});
|
||||
|
||||
d3.select('body').on('mousemove', function() {
|
||||
var chartBounds = d3.select('.profit-chart')[0][0].getBoundingClientRect();
|
||||
var mouseX = d3.event.clientX;
|
||||
var mouseY = d3.event.clientY;
|
||||
|
||||
if (mouseX < chartBounds.left || mouseX > chartBounds.right || mouseY < chartBounds.top || mouseY > chartBounds.bottom) {
|
||||
d3.select('.nvtooltip').style('opacity', 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return profitChart;
|
||||
});
|
||||
</text>
|
||||
}
|
||||
})(jQuery);
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
var originalLeave = $.fn.tooltip.Constructor.prototype.leave;
|
||||
$.fn.tooltip.Constructor.prototype.leave = function(obj){
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type);
|
||||
var container, timeout;
|
||||
|
||||
originalLeave.call(this, obj);
|
||||
|
||||
if(obj.currentTarget) {
|
||||
container = $(obj.currentTarget).siblings('.tooltip');
|
||||
timeout = self.timeout;
|
||||
container.one('mouseenter', function(){
|
||||
//We entered the actual tooltip – call off the dogs
|
||||
clearTimeout(timeout);
|
||||
//Let's monitor tooltip content instead
|
||||
container.one('mouseleave', function(){
|
||||
$.fn.tooltip.Constructor.prototype.leave.call(self, self);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -8,6 +8,7 @@ using Core.Main.DataObjects;
|
|||
using Core.Main.DataObjects.PTMagicData;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Monitor.Pages
|
||||
{
|
||||
|
@ -19,6 +20,8 @@ namespace Monitor.Pages
|
|||
public SummaryData SummaryData { get; set; }
|
||||
|
||||
public List<MarketTrend> MarketTrends { get; set; } = new List<MarketTrend>();
|
||||
public double DataHours { get; set; }
|
||||
public int ProfitDays { get; set; }
|
||||
public string TrendChartDataJSON = "";
|
||||
public string ProfitChartDataJSON = "";
|
||||
public string LastGlobalSetting = "Default";
|
||||
|
@ -32,7 +35,6 @@ namespace Monitor.Pages
|
|||
|
||||
BindData();
|
||||
|
||||
BuildAssetDistributionData();
|
||||
}
|
||||
|
||||
private void BindData()
|
||||
|
@ -62,10 +64,11 @@ namespace Monitor.Pages
|
|||
MarketTrends = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.OrderBy(mt => mt.TrendMinutes).ThenByDescending(mt => mt.Platform).ToList();
|
||||
|
||||
BuildMarketTrendChartData();
|
||||
BuildAssetDistributionData();
|
||||
BuildProfitChartData();
|
||||
}
|
||||
private void BuildMarketTrendChartData()
|
||||
{
|
||||
{
|
||||
List<string> trendChartData = new List<string>();
|
||||
if (MarketTrends.Count > 0)
|
||||
{
|
||||
|
@ -91,10 +94,24 @@ namespace Monitor.Pages
|
|||
marketTrendChangeSummaries = marketTrendChangeSummaries.OrderBy(m => m.TrendDateTime).ToList();
|
||||
|
||||
// Get trend ticks for chart
|
||||
DateTime currentDateTime = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, DateTime.UtcNow.Hour, 0, 0);
|
||||
TimeSpan offset;
|
||||
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
|
||||
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
|
||||
|
||||
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
|
||||
{
|
||||
offset = TimeSpan.Zero; // If offset is invalid, set it to zero
|
||||
}
|
||||
|
||||
DateTime currentDateTime = DateTime.UtcNow;
|
||||
DateTime startDateTime = currentDateTime.AddHours(-PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours);
|
||||
DateTime endDateTime = currentDateTime;
|
||||
|
||||
// Ensure startDateTime doesn't exceed the available data
|
||||
DateTime earliestTrendDateTime = marketTrendChangeSummaries.Min(mtc => mtc.TrendDateTime);
|
||||
startDateTime = startDateTime > earliestTrendDateTime ? startDateTime : earliestTrendDateTime;
|
||||
DataHours = (currentDateTime - earliestTrendDateTime).TotalHours;
|
||||
|
||||
// Cache the result of SplitCamelCase(mt.Name)
|
||||
string splitCamelCaseName = SystemHelper.SplitCamelCase(mt.Name);
|
||||
|
||||
|
@ -108,14 +125,19 @@ namespace Monitor.Pages
|
|||
MarketTrendChange mtc = marketTrendChangeSummaries[index];
|
||||
if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0;
|
||||
|
||||
trendValues.Add("{ x: new Date('" + tickTime.ToString("yyyy-MM-ddTHH:mm:ss").Replace(".", ":") + "'), y: " + mtc.TrendChange.ToString("0.00", CultureInfo.InvariantCulture) + "}");
|
||||
// Adjust tickTime to the desired timezone before converting to string
|
||||
DateTime adjustedTickTime = tickTime.Add(isNegative ? -offset : offset);
|
||||
trendValues.Add("{ x: new Date('" + adjustedTickTime.ToString("yyyy-MM-ddTHH:mm:ss").Replace(".", ":") + "'), y: " + mtc.TrendChange.ToString("0.00", CultureInfo.InvariantCulture) + "}");
|
||||
}
|
||||
}
|
||||
|
||||
// Add most recent tick
|
||||
MarketTrendChange latestMtc = marketTrendChangeSummaries.Last();
|
||||
if (Double.IsInfinity(latestMtc.TrendChange)) latestMtc.TrendChange = 0;
|
||||
trendValues.Add("{ x: new Date('" + latestMtc.TrendDateTime.ToString("yyyy-MM-ddTHH:mm:ss").Replace(".", ":") + "'), y: " + latestMtc.TrendChange.ToString("0.00", CultureInfo.InvariantCulture) + "}");
|
||||
|
||||
// Adjust latestMtc.TrendDateTime to the desired timezone before converting to string
|
||||
DateTime adjustedLatestTrendDateTime = latestMtc.TrendDateTime.Add(isNegative ? -offset : offset);
|
||||
trendValues.Add("{ x: new Date('" + adjustedLatestTrendDateTime.ToString("yyyy-MM-ddTHH:mm:ss").Replace(".", ":") + "'), y: " + latestMtc.TrendChange.ToString("0.00", CultureInfo.InvariantCulture) + "}");
|
||||
|
||||
// Use cached splitCamelCaseName
|
||||
trendChartData.Add("{ key: '" + splitCamelCaseName + "', color: '" + lineColor + "', values: [" + string.Join(",\n", trendValues) + "] }");
|
||||
|
@ -124,25 +146,56 @@ namespace Monitor.Pages
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
TrendChartDataJSON = "[" + string.Join(",", trendChartData) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildProfitChartData()
|
||||
{
|
||||
StringBuilder profitPerDayJSON = new StringBuilder();
|
||||
{
|
||||
List<object> profitPerDayList = new List<object>();
|
||||
|
||||
if (PTData.DailyPNL.Count > 0)
|
||||
{
|
||||
DateTime endDate = DateTime.UtcNow.Date;
|
||||
// Get timezone offset
|
||||
TimeSpan offset;
|
||||
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
|
||||
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
|
||||
|
||||
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
|
||||
{
|
||||
offset = TimeSpan.Zero; // If offset is invalid, set it to zero
|
||||
}
|
||||
|
||||
DateTime endDate = DateTime.UtcNow.Add(isNegative ? -offset : offset).Date;
|
||||
|
||||
// Parse dates once and adjust them to the local timezone
|
||||
Dictionary<DateTime, DailyPNLData> dailyPNLByDate = PTData.DailyPNL
|
||||
.Select(data => {
|
||||
DateTime dateUtc = DateTime.ParseExact(data.Date, "d-M-yyyy", CultureInfo.InvariantCulture);
|
||||
DateTime dateLocal = dateUtc.Add(isNegative ? -offset : offset);
|
||||
return new { Date = dateLocal.Date, Data = data };
|
||||
})
|
||||
.ToDictionary(
|
||||
item => item.Date,
|
||||
item => item.Data
|
||||
);
|
||||
|
||||
DateTime earliestDataDate = dailyPNLByDate.Keys.Min();
|
||||
DateTime startDate = endDate.AddDays(-PTMagicConfiguration.GeneralSettings.Monitor.ProfitsMaxTimeframeDays - 1); // Fetch data for timeframe + 1 days
|
||||
if (startDate < earliestDataDate)
|
||||
{
|
||||
startDate = earliestDataDate;
|
||||
}
|
||||
|
||||
// Calculate the total days of data available
|
||||
ProfitDays = (endDate - startDate).Days;
|
||||
|
||||
double previousDayCumulativeProfit = 0;
|
||||
bool isFirstDay = true;
|
||||
for (DateTime date = startDate; date <= endDate; date = date.AddDays(1))
|
||||
{
|
||||
DailyPNLData dailyPNL = PTData.DailyPNL.Find(ds => DateTime.ParseExact(ds.Date, "d-M-yyyy", CultureInfo.InvariantCulture) == date);
|
||||
if (dailyPNL != null)
|
||||
// Use the dictionary to find the DailyPNLData for the date
|
||||
if (dailyPNLByDate.TryGetValue(date, out DailyPNLData dailyPNL))
|
||||
{
|
||||
if (isFirstDay)
|
||||
{
|
||||
|
@ -153,19 +206,22 @@ namespace Monitor.Pages
|
|||
// Calculate the profit for the current day
|
||||
double profitFiat = Math.Round(dailyPNL.CumulativeProfitCurrency - previousDayCumulativeProfit, 2);
|
||||
|
||||
// Add the data point to the JSON string
|
||||
if (profitPerDayJSON.Length > 0)
|
||||
{
|
||||
profitPerDayJSON.Append(",\n");
|
||||
}
|
||||
profitPerDayJSON.Append("{x: new Date('" + date.ToString("yyyy-MM-dd") + "'), y: " + profitFiat.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "}");
|
||||
// Add the data point to the list
|
||||
profitPerDayList.Add(new { x = new DateTimeOffset(date).ToUnixTimeMilliseconds(), y = profitFiat });
|
||||
}
|
||||
previousDayCumulativeProfit = dailyPNL.CumulativeProfitCurrency;
|
||||
}
|
||||
}
|
||||
ProfitChartDataJSON = "[{key: 'Profit in " + PTData.Properties.Currency + "',color: '" + Constants.ChartLineColors[1] + "',values: [" + profitPerDayJSON.ToString() + "]}]";
|
||||
// Convert the list to a JSON string using Newtonsoft.Json
|
||||
ProfitChartDataJSON = Newtonsoft.Json.JsonConvert.SerializeObject(new[] {
|
||||
new {
|
||||
key = "Profit in " + PTData.Properties.Currency,
|
||||
color = Constants.ChartLineColors[1],
|
||||
values = profitPerDayList
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildAssetDistributionData()
|
||||
{
|
||||
|
@ -180,7 +236,6 @@ namespace Monitor.Pages
|
|||
foreach (Core.Main.DataObjects.PTMagicData.DCALogData dcaLogEntry in PTData.DCALog)
|
||||
{
|
||||
string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive);
|
||||
|
||||
// Aggregate totals
|
||||
double leverage = dcaLogEntry.Leverage;
|
||||
if (leverage == 0)
|
||||
|
|
Loading…
Reference in New Issue