Asset Distribution Chart

This commit is contained in:
HojouFotytu 2019-05-01 00:36:27 +09:00
parent 9070a33e9b
commit 885bb796e2
4 changed files with 148 additions and 75 deletions

View File

@ -161,6 +161,28 @@ namespace Core.Main.DataObjects
this.Summary.PendingValue + this.Summary.PendingValue +
this.Summary.DustValue); this.Summary.DustValue);
} }
public double GetPairsBalance()
{
return
(this.Summary.PairsValue);
}
public double GetDCABalance()
{
return
(this.Summary.DCAValue);
}
public double GetPendingBalance()
{
return
(this.Summary.PendingValue);
}
public double GetDustBalance()
{
return
(this.Summary.DustValue);
}
public double GetSnapshotBalance(DateTime snapshotDateTime) public double GetSnapshotBalance(DateTime snapshotDateTime)
{ {

View File

@ -15,8 +15,6 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card-box"> <div class="card-box">
<table class="table table-striped table-sm"> <table class="table table-striped table-sm">
<thead> <thead>
<tr> <tr>

View File

@ -4,6 +4,11 @@
Layout = null; Layout = null;
} }
@section Styles {
<link href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/nvd3/nv.d3.min.css" rel="stylesheet" type="text/css" />
<link href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/tablesaw/css/tablesaw.css" rel="stylesheet" type="text/css" />
}
<div class="row"> <div class="row">
<div class="col-md-6 px-1"> <div class="col-md-6 px-1">
<div class="card-box px-2"> <div class="card-box px-2">
@ -44,6 +49,39 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-md-2 px-1">
<div class="card-box px-2" style="height:305px;">
<h4 class="m-t-0 header-title">Asset Distribution</h4>
<div id="AssetDistribution">
<svg style="height:290px;width:100%"></svg>
</div>
</div>
</div>
<div class="col-md-4 px-1">
<div class="card-box px-2" style="height:305px;">
@if (!Model.ProfitChartDataJSON.Equals("")) {
<div class="profit-chart">
<svg style="height:300px;width:100%"></svg>
</div>
} else {
<p>Unable to load graph, no sales data found.</p>
}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 px-1">
<div class="card-box px-2" style="height:305px;">
@if (!Model.TrendChartDataJSON.Equals("")) {
<div class="trend-chart">
<svg style="height:300px;width:100%"></svg>
</div>
} else {
<p>Unable to load graph, no market trend data found.</p>
}
</div>
</div>
<div class="col-md-6 px-1"> <div class="col-md-6 px-1">
<div class="card-box px-2"> <div class="card-box px-2">
<h4 class="m-t-0 m-b-20 header-title"><b>Sales Overview</b><small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)SalesAnalyzer">more</a></small></h4> <h4 class="m-t-0 m-b-20 header-title"><b>Sales Overview</b><small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)SalesAnalyzer">more</a></small></h4>
@ -127,81 +165,84 @@
</table> </table>
</div> </div>
</div> </div>
</div>
<div class="row">
<div class="col-md-6 px-1">
<div class="card-box px-2" style="height:305px;">
@if (!Model.TrendChartDataJSON.Equals("")) {
<div class="trend-chart">
<svg style="height:305px;width:100%"></svg>
</div>
} else {
<p>Not able to load graph, no market trend data found.<br />If you still do not see a graph after more than hour, report an issue.</p>
}
</div>
</div>
<div class="col-md-6 px-1">
<div class="card-box px-2" style="height:305px;">
@if (!Model.ProfitChartDataJSON.Equals("")) {
<div class="profit-chart">
<svg style="height:305px;width:100%"></svg>
</div>
} else {
<p>Not able to load graph, no sales data found.<br />If you still do not see a graph after you made your first sale, report an issue.</p>
}
</div>
</div>
</div> </div>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/d3/d3.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/nvd3/nv.d3.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/tablesaw/js/tablesaw.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/tablesaw/js/tablesaw-init.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
@if (!Model.AssetDistributionData.Equals("")) {
<text>
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.showLabels(true) //Display pie labels
.labelThreshold(.1) //Configure the minimum slice size for labels to show up
.labelType("percent") //Configure what type of data to show in the label. Can be "key", "value" or "percent"
.donut(true) //Turn on Donut mode. Makes pie chart look tasty!
.donutRatio(0.3) //Configure how big you want the donut hole size to be.
;
d3.select("#AssetDistribution svg")
.datum(@Html.Raw(Model.AssetDistributionData))
.transition().duration(350)
.call(chart);
return chart;
});
</text>
}
});
(function ($) { (function ($) {
'use strict'; 'use strict';
$('[role="tooltip"]').remove(); $('[role="tooltip"]').remove();
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false); $('.text-autocolor').autocolor(false);
@if (!Model.Summary.CurrentGlobalSetting.SettingName.Equals(Model.LastGlobalSetting)) { @if (!Model.Summary.CurrentGlobalSetting.SettingName.Equals(Model.LastGlobalSetting)) {
<text> <text>
$.Notification.notify('success', 'top left', '@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName) now active!', 'PTMagic switched Profit Trailer settings to "@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName)".'); $.Notification.notify('success', 'top left', '@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName) now active!', 'PTMagic switched Profit Trailer settings to "@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName)".');
</text> </text>
} }
@if (!Model.TrendChartDataJSON.Equals("")) { @if (!Model.TrendChartDataJSON.Equals("")) {
<text> <text>
nv.addGraph(function () { nv.addGraph(function () {
var lineChart = nv.models.lineChart(); var lineChart = nv.models.lineChart();
var height = 300; var height = 300;
var chartData = @Html.Raw(Model.TrendChartDataJSON); var chartData = @Html.Raw(Model.TrendChartDataJSON);
lineChart.useInteractiveGuideline(true); lineChart.useInteractiveGuideline(true);
lineChart.xAxis.tickFormat(function (d) { return d3.time.format('%H:%M')(new Date(d)); }); lineChart.xAxis.tickFormat(function (d) { return d3.time.format('%H:%M')(new Date(d)); });
lineChart.yAxis.axisLabel('Trend %').tickFormat(d3.format(',.2f')); lineChart.yAxis.axisLabel('Trend %').tickFormat(d3.format(',.2f'));
d3.select('.trend-chart svg').attr('perserveAspectRatio', 'xMinYMid').datum(chartData).transition().duration(500).call(lineChart); d3.select('.trend-chart svg').attr('perserveAspectRatio', 'xMinYMid').datum(chartData).transition().duration(500).call(lineChart);
//nv.utils.windowResize(lineChart.update); v1.3.0 => Removed this line to prevent memory leak //nv.utils.windowResize(lineChart.update); v1.3.0 => Removed this line to prevent memory leak
return lineChart;
});
</text>
}
return lineChart; @if (!Model.ProfitChartDataJSON.Equals("")) {
}); <text>
</text> nv.addGraph(function () {
} var lineChart = nv.models.lineChart();
var height = 300;
var chartData = @Html.Raw(Model.ProfitChartDataJSON);
lineChart.useInteractiveGuideline(true);
lineChart.xAxis.tickFormat(function (d) { return d3.time.format('%Y/%m/%d')(new Date(d)); });
lineChart.yAxis.axisLabel('Daily Profit').tickFormat(d3.format(',.2f'));
d3.select('.profit-chart svg').attr('perserveAspectRatio', 'xMinYMid').datum(chartData).transition().duration(500).call(lineChart);
//nv.utils.windowResize(lineChart.update); v1.3.0 => Removed this line to prevent memory leak
@if (!Model.ProfitChartDataJSON.Equals("")) { return lineChart;
<text> });
nv.addGraph(function () { </text>
var lineChart = nv.models.lineChart(); }
var height = 300; })(jQuery);
var chartData = @Html.Raw(Model.ProfitChartDataJSON); </script>
lineChart.useInteractiveGuideline(true);
lineChart.xAxis.tickFormat(function (d) { return d3.time.format('%Y/%m/%d')(new Date(d)); });
lineChart.yAxis.axisLabel('Profit').tickFormat(d3.format(',.2f'));
d3.select('.profit-chart svg').attr('perserveAspectRatio', 'xMinYMid').datum(chartData).transition().duration(500).call(lineChart);
//nv.utils.windowResize(lineChart.update); v1.3.0 => Removed this line to prevent memory leak
return lineChart;
});
</text>
}
})(jQuery);
</script>

View File

@ -16,12 +16,13 @@ namespace Monitor.Pages {
public string ProfitChartDataJSON = ""; public string ProfitChartDataJSON = "";
public string LastGlobalSetting = "Default"; public string LastGlobalSetting = "Default";
public DateTimeOffset DateTimeNow = Constants.confMinDate; public DateTimeOffset DateTimeNow = Constants.confMinDate;
public string AssetDistributionData = "";
public void OnGet() { public void OnGet() {
// Initialize Config // Initialize Config
base.Init(); base.Init();
BindData(); BindData();
BuildAssetDistributionData();
} }
private void BindData() { private void BindData() {
@ -87,7 +88,6 @@ namespace Monitor.Pages {
trendChartTicks++; trendChartTicks++;
} }
} }
// Add most recent tick // Add most recent tick
List<MarketTrendChange> latestTickRange = marketTrendChangeSummaries.OrderByDescending(m => m.TrendDateTime).ToList(); List<MarketTrendChange> latestTickRange = marketTrendChangeSummaries.OrderByDescending(m => m.TrendDateTime).ToList();
if (latestTickRange.Count > 0) { if (latestTickRange.Count > 0) {
@ -115,22 +115,18 @@ namespace Monitor.Pages {
string profitPerDayJSON = ""; string profitPerDayJSON = "";
if (PTData.SellLog.Count > 0) { if (PTData.SellLog.Count > 0) {
DateTime minSellLogDate = PTData.SellLog.OrderBy(sl => sl.SoldDate).First().SoldDate.Date; DateTime minSellLogDate = PTData.SellLog.OrderBy(sl => sl.SoldDate).First().SoldDate.Date;
DateTime graphStartDate = DateTime.UtcNow.Date.AddDays(-30); DateTime graphStartDate = DateTime.UtcNow.Date.AddDays(-10);
if (minSellLogDate > graphStartDate) graphStartDate = minSellLogDate; if (minSellLogDate > graphStartDate) graphStartDate = minSellLogDate;
for (DateTime salesDate = graphStartDate; salesDate <= DateTime.UtcNow.Date; salesDate = salesDate.AddDays(1)) { for (DateTime salesDate = graphStartDate; salesDate <= DateTime.UtcNow.Date; salesDate = salesDate.AddDays(1)) {
if (tradeDayIndex > 0) { if (tradeDayIndex > 0) {
profitPerDayJSON += ",\n"; profitPerDayJSON += ",\n";
} }
int trades = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate).Count; int trades = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate).Count;
double profit = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate).Sum(t => t.Profit); double profit = PTData.SellLog.FindAll(t => t.SoldDate.Date == salesDate).Sum(t => t.Profit);
double profitFiat = Math.Round(profit * Summary.MainMarketPrice, 2); double profitFiat = Math.Round(profit * Summary.MainMarketPrice, 2);
profitPerDayJSON += "{x: new Date('" + salesDate.ToString("yyyy-MM-dd") + "'), y: " + profitFiat.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "}"; profitPerDayJSON += "{x: new Date('" + salesDate.ToString("yyyy-MM-dd") + "'), y: " + profitFiat.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "}";
tradeDayIndex++; tradeDayIndex++;
} }
ProfitChartDataJSON = "["; ProfitChartDataJSON = "[";
ProfitChartDataJSON += "{"; ProfitChartDataJSON += "{";
ProfitChartDataJSON += "key: 'Profit in " + Summary.MainFiatCurrency + "',"; ProfitChartDataJSON += "key: 'Profit in " + Summary.MainFiatCurrency + "',";
@ -140,5 +136,21 @@ namespace Monitor.Pages {
ProfitChartDataJSON += "]"; ProfitChartDataJSON += "]";
} }
} }
private void BuildAssetDistributionData()
{
double PairsBalance = PTData.GetPairsBalance();
double DCABalance = PTData.GetDCABalance();
double PendingBalance = PTData.GetPendingBalance();
double DustBalance = PTData.GetDustBalance();
double TotalValue = PTData.GetCurrentBalance();
double AvailableBalance = (TotalValue - PairsBalance - DCABalance - PendingBalance - DustBalance);
AssetDistributionData = "[";
AssetDistributionData += "{label: 'Pairs',color: '#82E0AA',value: " + PairsBalance.ToString() + "},";
AssetDistributionData += "{label: 'DCA',color: '#D98880',value: " + DCABalance.ToString() + "},";
AssetDistributionData += "{label: 'Pending',color: '#F5B041',value: " + PendingBalance.ToString() + "},";
AssetDistributionData += "{label: 'Dust',color: '#BB8FCE',value: " + DustBalance.ToString() + "},";
AssetDistributionData += "{label: 'Balance',color: '#85C1E9',value: " + AvailableBalance.ToString() + "}]";
}
} }
} }