PTMagic/Monitor/Pages/SalesAnalyzer.cshtml

566 lines
27 KiB
Plaintext

@page
@model SalesAnalyzer
@using System.Globalization
@{
ViewData["Title"] = "";
}
@section Styles {
<link href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/tablesaw/css/tablesaw.css" rel="stylesheet" type="text/css" />
<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/datatables/dataTables.bootstrap4.min.css" rel="stylesheet" type="text/css" />
<link href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/buttons.bootstrap4.min.css" rel="stylesheet" type="text/css" />
}
<div class="row">
<div class="col-md-12">
<div class="card-box">
<table class="table table-striped table-sm">
<thead>
<tr>
@{
double totalCurrentValue = double.Parse(Model.PTData.Misc.TotalCurrentValue);
string totalCurrentValueString = Model.PTData.Misc.TotalCurrentValue;
}
<th class="m-t-0 header-title text-left">Total Current Value: &nbsp; <text class="text-autocolor"> @totalCurrentValueString @Model.Summary.MainMarket </text> <small> <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This is based on the Total Current Value reported by Profit Trailer."></i></small></th>
<th class="text-right">Starting Value: &nbsp; <text class="text-autocolor"> @Model.MiscData.StartBalance &nbsp; @Model.Summary.MainMarket </text> <small> <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This is the starting value set in your PT account settings."></i></small></th>
</tr>
</thead>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card-box px-2" style="height:320px;">
<h4 class="m-t-0 header-title"><b>Cumulative Profits</b>
@if (!Model.CumulativeProfitChartDataJSON.Equals("")) {
<div class="cumulative-profit-chart">
<svg style="height:300px;width:100%"></svg>
</div>
} else {
<p>Unable to load graph, no sales data found.</p>
}
</div>
</div>
<div class="col-md-6">
<div class="card-box px-2" style="height:320px;">
<h4 class="m-t-0 header-title"><b>Daily TCV</b>
@if (!Model.TCVChartDataJSON.Equals("")) {
<div class="TCV-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">
<div class="card-box px-3" style="height:340px;">
@{
var days = Math.Min(Model.DailyStats.Count, 30);
}
<h4 class="m-t-0 m-b-20 header-title"><b>Daily Buys/Sales (@days Days) </b>
<div class="sales-chart">
<svg style="height:300px;width:100%"></svg>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card-box px-3" style="height:340px;">
<h4 class="m-t-0 m-b-20 header-title"><b>Daily Profit (All Time) </b>
@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">
<div class="card-box">
@{
int totalDays = Model.PTData.DailyPNL.Count;
double startBalance = Model.MiscData.StartBalance;
double totalSales = Model.PTData.Stats.TotalSales;
double totalProfit = Model.PTData.Stats.TotalProfit;
double totalFundingFees = Model.PTData.Stats.FundingTotal;
double totalPercentGain = ((totalProfit + totalFundingFees) / startBalance) * 100;
double totalProfitFiat = @Math.Round((totalProfit + totalFundingFees) * Model.PTData.Misc.FiatConversionRate, 0);
double avgDailySales = @Math.Round(totalSales/totalDays, 1);
double avgDailyGain = totalPercentGain / totalDays;
var MonthlyAveragesResult = Model.MonthlyAverages(Model.PTData.MonthlyStats, Model.PTData.DailyPNL);
string startDate = MonthlyAveragesResult.startDate.ToString("d");
string endDate = MonthlyAveragesResult.endDate.ToString("d");
double totalMonths = Math.Round(MonthlyAveragesResult.totalMonths, 1);
double avgMonthlySales = @Math.Round(totalSales / totalMonths, 1);
double avgMonthlyProfit = totalProfit / totalMonths;
double avgMonthlyGain = totalPercentGain / totalMonths;
double avgMonthlyFunding = totalFundingFees / totalMonths;
}
<h4 class="m-t-0 header-title" style="display: inline;">Averages</h4>&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: x-small"> (@startDate - @endDate)</span>
<table class="table table-striped table-sm">
<thead>
<tr>
<th></th>
<th class="text-right">Total</th>
<th class="text-right">AVG/Day</span></th>
<th class="text-right">AVG/Month</span> <small><i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top"
title="Months are based on the size of the calendar months. Weighted to compensate for partial months."></i></small></th>
</tr>
</thead>
<tbody>
<tr>
<th>Sales</th>
<td class="text-right">@totalSales</td>
<td class="text-right">@avgDailySales</td>
<td class="text-right">@avgMonthlySales</td>
</tr>
<tr>
<th>@Model.PTData.Misc.Market</th>
<td class="text-right text-autocolor">@totalProfit.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Math.Round(totalProfit / totalDays, 8).ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@avgMonthlyProfit.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
</tr>
@if(Model.PropertiesData.IsLeverageExchange)
{
<tr>
<th>Funding</th>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(totalFundingFees,8).ToString("#0.00000000", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(totalFundingFees / totalDays,8).ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(totalFundingFees / totalMonths,8).ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")))</td>
</tr>
}
<tr>
<th>@Model.PTData.Properties.Currency</th>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(totalProfitFiat,0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(totalProfitFiat / totalDays, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(totalProfitFiat / totalMonths, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
</tr>
<tr>
<th>Gain</th>
<td class="text-right text-autocolor">@totalPercentGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
<td class="text-right text-autocolor">@avgDailyGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
<td class="text-right text-autocolor">@avgMonthlyGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-6">
<div class="card-box">
@{
double estimatedBalance1Week = Math.Round(totalCurrentValue * Math.Pow((1 + (avgDailyGain / 100)), 7.0), 8);
double estimatedBalance1Month = Math.Round(totalCurrentValue * Math.Pow((1 + (avgDailyGain / 100)), 30.0), 8);
double estimatedBalance3Months = Math.Round(totalCurrentValue * Math.Pow((1 + (avgDailyGain / 100)), 90.0), 8);
double estimatedBalance6Months = Math.Round(totalCurrentValue * Math.Pow((1 + (avgDailyGain / 100)), 180.0), 8);
double estimatedBalance1Year = Math.Round(totalCurrentValue * Math.Pow((1 + (avgDailyGain / 100)), 365.0), 8);
}
<h4 class="m-t-0 header-title">TCV Prediction <small><i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The balance prediction is based on your daily average gain of @avgDailyGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))% and your current TCV of @totalCurrentValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))"></i></small></h4>
<table class="table table-striped table-sm">
<thead>
<tr>
<th class="text-right"></th>
<th class="text-right">@Model.PTData.Misc.Market</th>
<th class="text-right">@Model.PTData.Properties.Currency</th>
<th class="text-right">Gain</th>
</tr>
</thead>
<tbody>
<tr>
<th>1 Week</th>
<td class="text-right text-autocolor">@estimatedBalance1Week.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(estimatedBalance1Week * Model.MiscData.FiatConversionRate, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Math.Round((estimatedBalance1Week - totalCurrentValue) / totalCurrentValue * 100, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
<tr>
<th>1 Month</th>
<td class="text-right text-autocolor">@estimatedBalance1Month.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(estimatedBalance1Month * Model.MiscData.FiatConversionRate, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Math.Round((estimatedBalance1Month - totalCurrentValue) / totalCurrentValue * 100, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
<tr>
<th>3 Months</th>
<td class="text-right text-autocolor">@estimatedBalance3Months.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(estimatedBalance3Months * Model.MiscData.FiatConversionRate, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Math.Round((estimatedBalance3Months - totalCurrentValue) / totalCurrentValue * 100, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
<tr>
<th>6 Months</th>
<td class="text-right text-autocolor">@estimatedBalance6Months.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(estimatedBalance6Months * Model.MiscData.FiatConversionRate, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Math.Round((estimatedBalance6Months - totalCurrentValue) / totalCurrentValue * 100, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
<tr>
<th>1 Year</th>
<td class="text-right text-autocolor">@estimatedBalance1Year.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Html.Raw(Math.Round(estimatedBalance1Year * Model.MiscData.FiatConversionRate, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-right text-autocolor">@Math.Round((estimatedBalance1Year - totalCurrentValue) / totalCurrentValue * 100, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card-box">
@{
var maxDays = Math.Min(Model.DailyStats.Count, Math.Min(Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDailySummaries, 30));
}
<h4 class="m-t-0 header-title">Last @maxDays Days</h4>
<table class="table table-sm">
<thead>
<tr>
<th>Day</th>
<th class="text-right">Buys</th>
<th class="text-right">Sales</th>
<th class="text-right">Profit @Model.Summary.MainMarket</th>
<th class="text-right">Profit @Model.PTData.Properties.Currency</th>
<th class="text-right">Gain</th>
</tr>
</thead>
<tbody>
@{
for (int i = 0; i < maxDays; i++)
{
DateTime salesDate = DateTime.ParseExact(Model.PTData.DailyStats[i].Date, "d-M-yyyy", CultureInfo.InvariantCulture);
var buys = Model.PTData.DailyStats[i].TotalBuys;
var sales = Model.PTData.DailyStats[i].TotalSales;
var profit = Model.PTData.DailyStats[i].TotalProfit;
var avgProfit = Model.PTData.DailyStats[i].AvgProfit;
var profitFiat = Math.Round(profit * Model.PTData.Misc.FiatConversionRate, 0);
<tr>
<td>@salesDate.ToString("yyyy-MM-dd")</td>
<td class="text-right text-autocolor"">@buys</td>
<td class="text-right text-autocolor"">@sales</td>
<td class="text-right text-autocolor">@profit.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@Math.Round(profitFiat,0).ToString("#,#0", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@avgProfit.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
<div class="col-md-6">
<div class="card-box">
@{
var maxMonths = Math.Min(Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxMonthlySummaries, Model.MonthlyStats.Count);
}
<h4 class="m-t-0 header-title">Last @maxMonths months</h4>
<table class="table table-sm">
<thead>
<tr>
<th>Month</th>
<th class="text-right">Sales</th>
<th class="text-right">Profit @Model.Summary.MainMarket</th>
<th class="text-right">Profit @Model.PTData.Properties.Currency</th>
<th class="text-right">Growth</th>
</tr>
</thead>
<tbody>
@{
for (int i = 0; i < maxMonths; i++)
{
DateTime monthDate = DateTime.ParseExact(Model.PTData.MonthlyStats[i].Month, "M-yyyy", CultureInfo.InvariantCulture);
string monthName = monthDate.ToString("MMMM", CultureInfo.InvariantCulture);
var sales = Model.PTData.MonthlyStats[i].TotalSales;
var profit = Model.PTData.MonthlyStats[i].TotalProfitCurrency;
var profitFiat = Math.Round(profit * Model.PTData.Misc.FiatConversionRate, 0);
var growth = Math.Round(Model.PTData.MonthlyStats[i].AvgGrowth,2);
<tr>
<td>@monthName</td>
<td class="text-right text-autocolor">@sales</td>
<td class="text-right text-autocolor">@profit.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right text-autocolor">@profitFiat</td>
<td class="text-right text-autocolor">@growth %</td>
</tr>
}
}
</tbody>
</table>
</div
</div>
@* <div class="col-md-6"> *@
<div class="card-box">
<h4 class="m-t-0 header-title"><b>Top @Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets Sales Markets</b></h4>
<table class="tablesaw table m-b-0" data-tablesaw-sortable data-tablesaw-sortable-switch>
<thead>
<tr>
<th scope="col" data-tablesaw-priority="persist" data-tablesaw-sortable-col data-tablesaw-sortable-default-col>Rank</th>
<th scope="col" data-tablesaw-sortable-col>Market</th>
<th scope="col" class="text-right" data-tablesaw-sortable-col>Profit @Model.PTData.Misc.Market</th>
<th scope="col" class="text-right" data-tablesaw-sortable-col>Sales</th>
<th scope="col" class="text-right" data-tablesaw-sortable-col>Avg/Trade</th>
</tr>
</thead>
<tbody>
@{
int rank = 1;
foreach (var pair in Model.ProfitablePairs)
{
string coin = pair.Coin;
double profit = Math.Round(pair.ProfitCurrency,8);
int sales = pair.SoldTimes;
double avg = Math.Round(pair.Avg,8);
double profitFiat = Math.Round(profit * Model.MiscData.FiatConversionRate, 0);
<tr>
<td>@rank</td>
<td><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform, Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, coin, Model.PTData.Misc.Market, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@coin</a></td>
<td class="text-right text-autocolor-saw">@profit</td>
<td class="text-right">@sales</td>
<td class="text-right text-autocolor-saw">@avg </td>
</tr>
rank++;
}
}
</tbody>
</table>
</div>
@* </div> *@
</div>
}
@section Scripts {
<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/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-init.js"></script>
<!-- Required datatable js -->
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/jquery.dataTables.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Buttons examples -->
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/dataTables.buttons.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/buttons.bootstrap4.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/jszip.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/pdfmake.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/vfs_fonts.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/buttons.html5.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/buttons.print.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/datatables/buttons.colVis.min.js"></script>
<script type="text/javascript">
(function ($) {
'use strict';
$('[role="tooltip"]').remove();
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
var salesChart; // Keep a reference to the chart
var salesData; // Keep a reference to the data
@if (!Model.SalesChartDataJSON.Equals("")) {
<text>
nv.addGraph(function () {
salesChart = nv.models.multiBarChart();
var height = 300;
salesChart.groupSpacing(0.5);
salesChart.showControls(false);
//salesChart.useInteractiveGuideline(true);
salesChart.xAxis.tickFormat(function (d) { return d3.time.format('%m/%d')(new Date(d)); });
salesChart.yAxis.axisLabel('').tickFormat(d3.format(',.2f'));
salesData = @Html.Raw(Model.SalesChartDataJSON);
d3.select('.sales-chart svg')
.datum(salesData)
.transition().duration(0)
.call(salesChart);
nv.utils.windowResize(salesChart.update);
return salesChart;
});
</text>
}
})(jQuery);
</script>
<script type="text/javascript">
(function ($) {
'use strict';
$('[role="tooltip"]').remove();
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
var cumulativeProfitChart; // Keep a reference to the chart
var cumulativeProfitData; // Keep a reference to the data
@if (!Model.CumulativeProfitChartDataJSON.Equals("")) {
<text>
nv.addGraph(function () {
cumulativeProfitChart = nv.models.lineChart();
var height = 300;
cumulativeProfitChart.useInteractiveGuideline(true);
cumulativeProfitChart.xAxis.tickFormat(function (d) { return d3.time.format('%m/%d')(new Date(d)); });
cumulativeProfitChart.yAxis.axisLabel('').tickFormat(d3.format(',.2f'));
cumulativeProfitData = @Html.Raw(Model.CumulativeProfitChartDataJSON);
d3.select('.cumulative-profit-chart svg')
.datum(cumulativeProfitData)
.transition().duration(0)
.call(cumulativeProfitChart);
nv.utils.windowResize(cumulativeProfitChart.update);
return cumulativeProfitChart;
});
</text>
}
})(jQuery);
</script>
<script type="text/javascript">
(function ($) {
'use strict';
$('[role="tooltip"]').remove();
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
var TCVChart; // Keep a reference to the chart
var TCVData; // Keep a reference to the data
@if (!Model.TCVChartDataJSON.Equals("")) {
<text>
nv.addGraph(function () {
TCVChart = nv.models.lineChart();
var height = 300;
TCVChart.useInteractiveGuideline(true);
TCVChart.xAxis.tickFormat(function (d) { return d3.time.format('%m/%d')(new Date(d)); });
TCVChart.yAxis.axisLabel('').tickFormat(d3.format(',.2f'));
TCVData = @Html.Raw(Model.TCVChartDataJSON);
d3.select('.TCV-chart svg')
.datum(TCVData)
.transition().duration(0)
.call(TCVChart);
nv.utils.windowResize(TCVChart.update);
return TCVChart;
});
</text>
}
})(jQuery);
</script>
<script type="text/javascript">
(function ($) {
'use strict';
$('[role="tooltip"]').remove();
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
var profitChart; // Keep a reference to the chart
var profitData; // Keep a reference to the data
@if (!Model.ProfitChartDataJSON.Equals("")) {
<text>
nv.addGraph(function () {
profitChart = nv.models.lineChart();
var height = 300;
profitChart.useInteractiveGuideline(true);
profitChart.xAxis.tickFormat(function (d) { return d3.time.format('%m/%d')(new Date(d)); });
profitChart.yAxis.axisLabel('').tickFormat(d3.format(',.2f'));
profitData = @Html.Raw(Model.ProfitChartDataJSON);
d3.select('.profit-chart svg')
.datum(profitData)
.transition().duration(0)
.call(profitChart);
profitChart.dispatch.on('renderEnd', function() {
// Get the chart's container
var container = d3.select('.profit-chart .nv-wrap.nv-lineChart .nv-linesWrap');
// Remove any existing y=0 line
container.selectAll('.zero-line').remove();
// Check if profitData[0].values is not empty
if (profitData[0].values.length > 0) {
// Get the x-values of the first and last data points
var xMin = profitChart.xAxis.scale()(profitData[0].values[0].x);
var xMax = profitChart.xAxis.scale()(profitData[0].values[profitData[0].values.length - 1].x);
// Add a line at y=0
container.insert('line', ':first-child')
.attr('class', 'zero-line') // Add a class to the line for easy selection
.attr('x1', xMin) // x position of the first end of the line
.attr('y1', profitChart.yAxis.scale()(0)) // y position of the first end of the line
.attr('x2', xMax) // x position of the second end of the line
.attr('y2', profitChart.yAxis.scale()(0)) // y position of the second end of the line
.attr('stroke', 'gray') // color of the line
.attr('stroke-width', 2); // width of the line
}
});
nv.utils.windowResize(profitChart.update);
return profitChart;
});
</text>
}
})(jQuery);
</script>
<script type="text/javascript">
function attachTooltipRemoval(chartClass) {
d3.selectAll(chartClass).on('mouseleave', function() {
var tooltip = d3.select(this).select('.nvtooltip');
if (!tooltip.empty()) {
tooltip.style('opacity', 0);
}
});
d3.selectAll(chartClass).on('mouseenter', function() {
var tooltip = d3.select(this).select('.nvtooltip');
if (!tooltip.empty()) {
tooltip.style('opacity', 1);
}
});
}
$(document).ready(function () {
// Hide all tooltips when the page is loaded
d3.selectAll('.nvtooltip').style('opacity', 0);
// Call the function for each chart
attachTooltipRemoval('.asset-distribution svg');
attachTooltipRemoval('.trend-chart svg');
attachTooltipRemoval('.profit-chart svg');
attachTooltipRemoval('.TCVLive-chart svg');
// Add other charts as needed
});
</script>
}