PTMagic/Monitor/Pages/_get/DashboardBottom.cshtml.cs

267 lines
12 KiB
C#
Raw Normal View History

2018-05-22 10:11:50 +02:00
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Core.Main;
using Core.Helper;
using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData;
2024-01-07 22:53:49 +01:00
using System.Globalization;
using System.Text;
2024-01-13 20:10:44 +01:00
using System.Diagnostics;
2018-05-22 10:11:50 +02:00
namespace Monitor.Pages
{
public class DashboardBottomModel : _Internal.BasePageModelSecureAJAX
{
2018-05-22 10:11:50 +02:00
public ProfitTrailerData PTData = null;
2024-01-07 22:53:49 +01:00
public StatsData StatsData { get; set; }
public PropertiesData PropertiesData { get; set; }
public SummaryData SummaryData { get; set; }
2024-01-10 16:58:09 +01:00
2018-05-22 10:11:50 +02:00
public List<MarketTrend> MarketTrends { get; set; } = new List<MarketTrend>();
2024-01-13 20:10:44 +01:00
public double DataHours { get; set; }
public int ProfitDays { get; set; }
2018-05-22 10:11:50 +02:00
public string TrendChartDataJSON = "";
public string ProfitChartDataJSON = "";
public string LastGlobalSetting = "Default";
public DateTimeOffset DateTimeNow = Constants.confMinDate;
2019-04-30 17:36:27 +02:00
public string AssetDistributionData = "";
2020-07-17 13:35:43 +02:00
public double totalCurrentValue = 0;
public void OnGet()
{
2018-05-22 10:11:50 +02:00
// Initialize Config
base.Init();
BindData();
2024-01-13 20:10:44 +01:00
2018-05-22 10:11:50 +02:00
}
2024-01-13 20:10:44 +01:00
private void BindData()
{
PTData = this.PtDataObject;
StatsData = this.PTData.Stats;
2024-01-07 22:53:49 +01:00
PropertiesData = this.PTData.Properties;
SummaryData = this.PTData.Summary;
2024-01-10 16:58:09 +01:00
2024-01-07 22:53:49 +01:00
List<DailyPNLData> dailyPNLData = this.PTData.DailyPNL;
2018-05-22 10:11:50 +02:00
// Cleanup temp files
FileHelper.CleanupFilesMinutes(PTMagicMonitorBasePath + "wwwroot" + System.IO.Path.DirectorySeparatorChar + "assets" + System.IO.Path.DirectorySeparatorChar + "tmp" + System.IO.Path.DirectorySeparatorChar, 5);
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
DateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
// Get last and current active setting
if (!String.IsNullOrEmpty(HttpContext.Session.GetString("LastGlobalSetting")))
{
2018-05-22 10:11:50 +02:00
LastGlobalSetting = HttpContext.Session.GetString("LastGlobalSetting");
}
HttpContext.Session.SetString("LastGlobalSetting", Summary.CurrentGlobalSetting.SettingName);
// Get market trends
MarketTrends = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.OrderBy(mt => mt.TrendMinutes).ThenByDescending(mt => mt.Platform).ToList();
BuildMarketTrendChartData();
2024-01-13 20:10:44 +01:00
BuildAssetDistributionData();
2018-05-22 10:11:50 +02:00
BuildProfitChartData();
}
private void BuildMarketTrendChartData()
2024-01-13 20:10:44 +01:00
{
List<string> trendChartData = new List<string>();
if (MarketTrends.Count > 0)
{
2024-01-13 20:10:44 +01:00
int mtIndex = 0;
foreach (MarketTrend mt in MarketTrends)
{
2024-01-13 20:10:44 +01:00
if (mt.DisplayGraph)
{
2024-01-13 20:10:44 +01:00
string lineColor = mtIndex < Constants.ChartLineColors.Length
? Constants.ChartLineColors[mtIndex]
: Constants.ChartLineColors[mtIndex - 20];
if (Summary.MarketTrendChanges.ContainsKey(mt.Name))
2024-01-07 22:53:49 +01:00
{
2024-01-13 20:10:44 +01:00
List<MarketTrendChange> marketTrendChangeSummaries = Summary.MarketTrendChanges[mt.Name];
2024-01-07 22:53:49 +01:00
2024-01-13 20:10:44 +01:00
if (marketTrendChangeSummaries.Count > 0)
2024-01-07 22:53:49 +01:00
{
2024-01-13 20:10:44 +01:00
List<string> trendValues = new List<string>();
// Sort marketTrendChangeSummaries by TrendDateTime
marketTrendChangeSummaries = marketTrendChangeSummaries.OrderBy(m => m.TrendDateTime).ToList();
// Get trend ticks for chart
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
2024-01-10 16:58:09 +01:00
2024-01-13 20:10:44 +01:00
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
2024-01-07 22:53:49 +01:00
{
2024-01-13 20:10:44 +01:00
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;
2024-01-10 16:58:09 +01:00
2024-01-13 20:10:44 +01:00
// Ensure startDateTime doesn't exceed the available data
DateTime earliestTrendDateTime = marketTrendChangeSummaries.Min(mtc => mtc.TrendDateTime);
startDateTime = startDateTime > earliestTrendDateTime ? startDateTime : earliestTrendDateTime;
DataHours = (currentDateTime - earliestTrendDateTime).TotalHours;
2024-01-07 22:53:49 +01:00
2024-01-13 20:10:44 +01:00
// Cache the result of SplitCamelCase(mt.Name)
string splitCamelCaseName = SystemHelper.SplitCamelCase(mt.Name);
2024-01-10 16:58:09 +01:00
2024-01-13 20:10:44 +01:00
for (DateTime tickTime = startDateTime; tickTime <= endDateTime; tickTime = tickTime.AddMinutes(PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes))
{
// Use binary search to find the range of items that match the condition
int index = marketTrendChangeSummaries.BinarySearch(new MarketTrendChange { TrendDateTime = tickTime }, Comparer<MarketTrendChange>.Create((x, y) => x.TrendDateTime.CompareTo(y.TrendDateTime)));
if (index < 0) index = ~index;
if (index < marketTrendChangeSummaries.Count)
2024-01-10 16:58:09 +01:00
{
2024-01-13 20:10:44 +01:00
MarketTrendChange mtc = marketTrendChangeSummaries[index];
if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0;
// 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) + "}");
2024-01-07 22:53:49 +01:00
}
2024-01-13 20:10:44 +01:00
}
2024-01-10 16:58:09 +01:00
2024-01-13 20:10:44 +01:00
// Add most recent tick
MarketTrendChange latestMtc = marketTrendChangeSummaries.Last();
if (Double.IsInfinity(latestMtc.TrendChange)) latestMtc.TrendChange = 0;
2024-01-10 16:58:09 +01:00
2024-01-13 20:10:44 +01:00
// 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) + "] }");
mtIndex++;
2024-01-07 22:53:49 +01:00
}
2018-05-22 10:11:50 +02:00
}
}
}
}
2024-01-13 20:10:44 +01:00
TrendChartDataJSON = "[" + string.Join(",", trendChartData) + "]";
}
2018-05-22 10:11:50 +02:00
private void BuildProfitChartData()
2024-01-13 20:10:44 +01:00
{
List<object> profitPerDayList = new List<object>();
if (PTData.DailyPNL.Count > 0)
{
2024-01-13 20:10:44 +01:00
// Get timezone offset
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
2024-01-07 22:53:49 +01:00
2024-01-13 20:10:44 +01:00
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{
2024-01-13 20:10:44 +01:00
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))
{
// Use the dictionary to find the DailyPNLData for the date
if (dailyPNLByDate.TryGetValue(date, out DailyPNLData dailyPNL))
2024-01-07 22:53:49 +01:00
{
2024-01-13 20:10:44 +01:00
if (isFirstDay)
2024-01-07 22:53:49 +01:00
{
2024-01-13 20:10:44 +01:00
isFirstDay = false;
}
else
{
// Calculate the profit for the current day
double profitFiat = Math.Round(dailyPNL.CumulativeProfitCurrency - previousDayCumulativeProfit, 2);
2024-01-10 16:58:09 +01:00
2024-01-13 20:10:44 +01:00
// Add the data point to the list
profitPerDayList.Add(new { x = new DateTimeOffset(date).ToUnixTimeMilliseconds(), y = profitFiat });
2024-01-07 22:53:49 +01:00
}
2024-01-13 20:10:44 +01:00
previousDayCumulativeProfit = dailyPNL.CumulativeProfitCurrency;
2024-01-07 22:53:49 +01:00
}
2018-05-22 10:11:50 +02:00
}
2024-01-13 20:10:44 +01:00
// 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
}
});
2018-05-22 10:11:50 +02:00
}
2024-01-13 20:10:44 +01:00
}
2024-01-07 22:53:49 +01:00
2019-04-30 17:36:27 +02:00
private void BuildAssetDistributionData()
{
2020-07-17 14:34:07 +02:00
// the per PT-Eelroy, the PT API doesn't provide these values when using leverage, so they are calculated here to cover either case.
2020-07-17 07:02:48 +02:00
double PairsBalance = 0.0;
double DCABalance = 0.0;
double PendingBalance = 0.0;
double AvailableBalance = PTData.GetCurrentBalance();
bool isSellStrategyTrue = false;
bool isTrailingSellActive = false;
2024-01-10 16:58:09 +01:00
foreach (Core.Main.DataObjects.PTMagicData.DCALogData dcaLogEntry in PTData.DCALog)
{
2024-01-13 20:10:44 +01:00
string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive);
2020-07-17 07:02:48 +02:00
// Aggregate totals
2021-02-18 10:02:26 +01:00
double leverage = dcaLogEntry.Leverage;
if (leverage == 0)
2020-07-17 07:02:48 +02:00
{
2021-02-18 10:02:26 +01:00
leverage = 1;
2020-07-17 07:02:48 +02:00
}
2021-02-18 10:06:52 +01:00
if (sellStrategyText.Contains("PENDING"))
{
PendingBalance = PendingBalance + ((dcaLogEntry.Amount * dcaLogEntry.CurrentPrice) / leverage);
}
else if (dcaLogEntry.BuyStrategies.Count > 0)
{
DCABalance = DCABalance + ((dcaLogEntry.Amount * dcaLogEntry.CurrentPrice) / leverage);
}
2020-07-17 07:02:48 +02:00
else
{
2021-02-18 10:06:52 +01:00
PairsBalance = PairsBalance + ((dcaLogEntry.Amount * dcaLogEntry.CurrentPrice) / leverage);
2020-07-17 07:02:48 +02:00
}
}
2020-07-17 13:35:43 +02:00
totalCurrentValue = PendingBalance + DCABalance + PairsBalance + AvailableBalance;
2019-04-30 17:36:27 +02:00
AssetDistributionData = "[";
2019-06-12 02:41:35 +02:00
AssetDistributionData += "{label: 'Pairs',color: '#82E0AA',value: '" + PairsBalance.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "'},";
AssetDistributionData += "{label: 'DCA',color: '#D98880',value: '" + DCABalance.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "'},";
AssetDistributionData += "{label: 'Pending',color: '#F5B041',value: '" + PendingBalance.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "'},";
AssetDistributionData += "{label: 'Balance',color: '#85C1E9',value: '" + AvailableBalance.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "'}]";
2019-04-30 17:36:27 +02:00
}
2018-05-22 10:11:50 +02:00
}
}