LIVE TCV / TV Layout / Timezone / Cosmetics

This commit is contained in:
HojouFotytu 2024-01-24 03:05:28 +09:00
parent e474033d9c
commit 6aa6928376
25 changed files with 376 additions and 521 deletions

View File

@ -42,7 +42,7 @@ namespace Core.Main.DataObjects.PTMagicData
public int FloodProtectionMinutes { get; set; } = 15;
public string Exchange { get; set; }
public string InstanceName { get; set; } = "PT Magic";
public string TimezoneOffset { get; set; } = "+0:00";
//public string TimezoneOffset { get; set; } = "+0:00";
public string CoinMarketCapAPIKey { get; set; }
//public string FreeCurrencyConverterAPIKey { get; set; }
}
@ -55,13 +55,13 @@ namespace Core.Main.DataObjects.PTMagicData
public bool OpenBrowserOnStart { get; set; } = false;
public int Port { get; set; } = 5000;
public string AnalyzerChart { get; set; } = "";
public int LiveTCVTimeframeMinutes { get; set; } = 60;
public int GraphIntervalMinutes { get; set; } = 60;
public int GraphMaxTimeframeHours { get; set; } = 24;
public int ProfitsMaxTimeframeDays { get; set; } = 60;
public int RefreshSeconds { get; set; } = 30;
public int BagAnalyzerRefreshSeconds { get; set; } = 5;
public int BuyAnalyzerRefreshSeconds { get; set; } = 5;
//public int MaxSalesRecords { get; set; } = 99999;
public int MaxTopMarkets { get; set; } = 20;
public int MaxDailySummaries { get; set; } = 10;
public int MaxMonthlySummaries { get; set; } = 10;
@ -70,6 +70,7 @@ namespace Core.Main.DataObjects.PTMagicData
public int MaxDCAPairs { get; set; } = 24;
public int MaxSettingsLogEntries { get; set; } = 20;
public string LinkPlatform { get; set; } = "TradingView";
public string TVCustomLayout { get; set; } = "";
public string DefaultDCAMode { get; set; } = "Simple";
public string TvStudyA { get; set; } = "";
public string TvStudyB { get; set; } = "";
@ -572,5 +573,7 @@ namespace Core.Main.DataObjects.PTMagicData
public string Market { get; set; }
public string TotalCurrentValue { get; set; }
public string TimeZoneOffset { get; set; }
public string ExchangeURL { get; set; }
public string PTVersion { get; set; }
}
}

View File

@ -82,8 +82,11 @@ namespace Core.Main.DataObjects
{
if (!_offsetTimeSpan.HasValue)
{
// Get offset for settings.
_offsetTimeSpan = TimeSpan.Parse(_systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
// Ensure Misc is populated
var misc = this.Misc;
// Get offset from Misc
_offsetTimeSpan = TimeSpan.Parse(misc.TimeZoneOffset);
}
return _offsetTimeSpan.Value;
@ -133,6 +136,8 @@ namespace Core.Main.DataObjects
StartBalance = PTData.startBalance,
TotalCurrentValue = PTData.totalCurrentValue,
TimeZoneOffset = PTData.timeZoneOffset,
ExchangeURL = PTData.exchangeUrl,
PTVersion = PTData.version,
};
}
public List<DailyStatsData> DailyStats
@ -585,57 +590,6 @@ namespace Core.Main.DataObjects
Order = monthlyStatsDataJson["order"],
};
}
// public List<SellLogData> SellLog
// {
// get
// {
// if (_sellLog == null || (DateTime.UtcNow > _sellLogRefresh))
// {
// lock (_sellLock)
// {
// // Thread double locking
// if (_sellLog == null || (DateTime.UtcNow > _sellLogRefresh))
// {
// _sellLog.Clear();
// // Page through the sales data summarizing it.
// bool exitLoop = false;
// int pageIndex = 1;
// // 1 record per page to allow user to set max records to retrieve
// int maxPages = _systemConfiguration.GeneralSettings.Monitor.MaxSalesRecords;
// int requestedPages = 0;
// while (!exitLoop && requestedPages < maxPages)
// {
// var sellDataPage = GetDataFromProfitTrailer("/api/v2/data/sales?Page=1&perPage=1&sort=SOLDDATE&sortDirection=DESCENDING&page=" + pageIndex);
// if (sellDataPage != null && sellDataPage.data.Count > 0)
// {
// // Add sales data page to collection
// this.BuildSellLogData(sellDataPage);
// pageIndex++;
// requestedPages++;
// Console.WriteLine($"Importing salesLog: {pageIndex}");
// }
// else
// {
// // All data retrieved
// exitLoop = true;
// }
// }
// // Update sell log refresh time
// _sellLogRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.RefreshSeconds -1);
// }
// }
// }
// return _sellLog;
// }
// }
public List<DCALogData> DCALog
{
@ -682,11 +636,15 @@ namespace Core.Main.DataObjects
{
get
{
if (_systemConfiguration.GeneralSettings.Monitor.MaxDashboardBuyEntries == 0)
{
return _buyLog;
}
if (_buyLog == null || (DateTime.UtcNow > _buyLogRefresh))
{
lock (_buyLock)
{
// Thread double locking
if (_buyLog == null || (DateTime.UtcNow > _buyLogRefresh))
{
_buyLog.Clear();

View File

@ -1,6 +1,4 @@
using System;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Net;
@ -535,18 +533,22 @@ namespace Core.Helper
}
}
public static string GetMarketLink(string platform, string exchange, string market, string mainMarket)
public static string GetMarketLink(string platform, string exchange, string market, string mainMarket, string tvCustomLayout)
{
string result = "#";
if (tvCustomLayout.Length > 0)
{
tvCustomLayout += "/";
}
if (platform.Equals("TradingView"))
{
if (exchange.Equals("binancefutures", StringComparison.InvariantCultureIgnoreCase))
{
result = "https://uk.tradingview.com/chart/?symbol=BINANCE:" + market.ToUpper() + "PERP";
result = "https://uk.tradingview.com/chart/"+tvCustomLayout+"?symbol=BINANCE:" + market.ToUpper() + ".P";
}
else
{
result = "https://uk.tradingview.com/chart/?symbol=" + exchange.ToUpper() + ":" + market.ToUpper();
result = "https://uk.tradingview.com/chart/"+tvCustomLayout+"?symbol=" + exchange.ToUpper() + ":" + market.ToUpper();
}
}
else

View File

@ -63,21 +63,8 @@
};
var loadDashboardBottom = function () {
//destroy all d3 svg graph to avoid memory leak
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)
{
// Clear existing interval to stop multiple attempts to load at the same time.
if (intervalDashboardBottom != null) {
clearInterval(intervalDashboardBottom);
}
@ -92,6 +79,17 @@
window.location.replace("@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)Login");
} else {
errCountIndex["DashboardBottom"] = 0;
// Destroy all d3 svg graph to avoid memory leak
setTimeout(function() {
$(".nvtooltip").remove();
$("svg > *").remove();
$("svg").remove();
nv.charts = {};
nv.graphs = [];
nv.logs = {};
nv.tooltip = {};
}, 30 * @Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000); // every 30 refreshes
}
// Reinstate the interval.

View File

@ -69,7 +69,7 @@
<tr>
<th>
@if (!lastMarket.Equals(smsSummary.Market)) {
<a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform, Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, smsSummary.Market, Model.Summary.MainMarket)" target="_blank">@smsSummary.Market</a>
<a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform, Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, smsSummary.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@smsSummary.Market</a>
}
</th>
<td>

View File

@ -271,9 +271,9 @@ else
}
</th>
@if (mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0) {
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket)" target="_blank">@market</a></th>
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@market</a></th>
} else {
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket)" target="_blank">@market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
}
<td class="text-right">@mps.LatestPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")) @Model.Summary.MainMarket</td>
<td class="text-right">@Math.Round(mps.Latest24hVolume, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US")) @Model.Summary.MainMarket</td>
@ -336,9 +336,9 @@ else
}
</th>
@if (mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0) {
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket)" target="_blank">@market</a></th>
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@market</a></th>
} else {
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket)" target="_blank">@market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
<th><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
}
<td class="text-right">@mps.LatestPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td class="text-right">@Math.Round(mps.Latest24hVolume, 0).ToString("#,#0", new System.Globalization.CultureInfo("en-US"))</td>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Core.Main;
using Core.Helper;
using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData;
using System.Globalization;
@ -11,6 +12,8 @@ namespace Monitor.Pages
public class MarketAnalyzerModel : _Internal.BasePageModelSecure
{
public List<MarketTrend> MarketTrends { get; set; } = new List<MarketTrend>();
public ProfitTrailerData PTData = null;
public MiscData MiscData { get; set; }
public string TrendChartDataJSON = "";
public double DataHours { get; set; }
@ -22,7 +25,8 @@ namespace Monitor.Pages
private void BindData()
{
// Get market trends
PTData = this.PtDataObject;
MiscData = this.PTData.Misc;
MarketTrends = PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends.OrderBy(mt => mt.TrendMinutes).ThenByDescending(mt => mt.Platform).ToList();
BuildMarketTrendChartData();
@ -56,8 +60,8 @@ namespace Monitor.Pages
// Get trend ticks for chart
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{

View File

@ -329,7 +329,7 @@
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)" target="_blank">@coin</a></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>

View File

@ -54,7 +54,7 @@ namespace Monitor.Pages
DailyStats = this.PTData.DailyStats;
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(MiscData.TimeZoneOffset.Replace("+", ""));
DateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
BuildSalesChartData();
@ -71,8 +71,8 @@ namespace Monitor.Pages
{
// Get timezone offset
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{
@ -129,8 +129,8 @@ namespace Monitor.Pages
{
// Get timezone offset
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{
@ -190,8 +190,8 @@ namespace Monitor.Pages
{
// Get timezone offset
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{
@ -301,8 +301,8 @@ namespace Monitor.Pages
{
// Get timezone offset
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{

View File

@ -117,12 +117,12 @@
</div>
</div>
<div class="form-group row">
@* <div class="form-group row">
<label class="col-md-4 col-form-label">Timezone Offset <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The time difference between your current location and UTC time. Examples: +7:00, -3:00"></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Application_TimezoneOffset" value="@Model.PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset">
</div>
</div>
</div> *@
@* <div class="form-group row">
<label class="col-md-4 col-form-label">Main Fiat Currency <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="This is the local currency you want PTM to use when showing your sales and account value in fiat."></i></label>
@ -196,42 +196,48 @@
</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 (Dashboard and Sales Analyzer) between data points. Very small intervals on large timeframe graphs can significantly impact performance."></i></label>
<label class="col-md-4 col-form-label">Live TCV Timeframe (Minutes) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The total timeframe for the Live TCV chart on the Dashboard. Very large timeframes can significantly impact performance."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_LiveTCVTimeframeMinutes" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.LiveTCVTimeframeMinutes.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Market Trend Chart 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 (Dashboard and Sales Analyzer) in hours. Large timeframe graphs can significantly impact performance."></i></label>
<label class="col-md-4 col-form-label">Market Trend Chart Max Timeframe (Hours) <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. Large timeframes can significantly impact performance."></i></label>
<label class="col-md-4 col-form-label">Daily Profit Graph Max Timeframe (Days) <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>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Dashboard Bottom Refresh <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval in seconds, of the charts and graphs on then main page."></i></label>
<label class="col-md-4 col-form-label">Dashboard Bottom Refresh (Seconds) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval in seconds, of the charts and graphs on then main page."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_RefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Bag AnalyzerRefresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor bag analyzer page."></i></label>
<label class="col-md-4 col-form-label">Bag AnalyzerRefresh (Seconds) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor bag analyzer page."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_BagAnalyzerRefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.BagAnalyzerRefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Buy AnalyzerRefresh Seconds <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor buy analyzer page."></i></label>
<label class="col-md-4 col-form-label">Buy AnalyzerRefresh (Seconds) <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The refresh interval of your monitor buy analyzer page."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_BuyAnalyzerRefreshSeconds" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.BuyAnalyzerRefreshSeconds.ToString(new System.Globalization.CultureInfo("en-US"))">
</div>
@ -247,12 +253,12 @@
</div>
</div>
@* <div class="form-group row">
<label class="col-md-4 col-form-label">Max Sales Records<i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The number of sales records PTMagic pulls from Profit Trailer. Changes require a Monitor Restart."></i></label>
<div class="form-group row">
<label class="col-md-4 col-form-label">TV Custom Chart <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="If TradingView is selected above, you can use the custom layout code found in your TV URL - ex. AGrfHNiI."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Monitor_MaxSalesRecords" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxSalesRecords.ToString(new System.Globalization.CultureInfo("en-US"))">
<input type="text" class="form-control" name="Monitor_TVCustomLayout" value="@Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout">
</div>
</div>
</div> *@
<div class="form-group row">
<label class="col-md-4 col-form-label">Max Top Markets <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of top markets being show in your Sales Analyzer."></i></label>

View File

@ -27,30 +27,6 @@ namespace Monitor.Pages
return result;
}
public string GetTimezoneSelection()
{
string result = "";
List<string> tzOffsetList = new List<string>();
foreach (TimeZoneInfo tzi in TimeZoneInfo.GetSystemTimeZones())
{
string offsetString = this.GetTimezoneOffsetString(tzi);
if (!tzOffsetList.Contains(offsetString))
{
string selected = "";
if (PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Equals(offsetString, StringComparison.InvariantCultureIgnoreCase))
{
selected = " selected=\"selected\"";
}
result += "<option" + selected + ">" + offsetString + "</option>\n";
tzOffsetList.Add(offsetString);
}
}
return result;
}
public void OnGet()
{
base.Init();
@ -78,7 +54,7 @@ namespace Monitor.Pages
PTMagicConfiguration.GeneralSettings.Application.Exchange = HttpContext.Request.Form["Application_Exchange"];
PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL = HttpContext.Request.Form["Application_ProfitTrailerMonitorURL"];
PTMagicConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken = HttpContext.Request.Form["Application_ProfitTrailerServerAPIToken"];
PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset = HttpContext.Request.Form["Application_TimezoneOffset"];
//PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset = HttpContext.Request.Form["Application_TimezoneOffset"];
//PTMagicConfiguration.GeneralSettings.Application.MainFiatCurrency = HttpContext.Request.Form["Application_MainFiatCurrency"];
PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes = SystemHelper.TextToInteger(HttpContext.Request.Form["Application_FloodProtectionMinutes"], PTMagicConfiguration.GeneralSettings.Application.FloodProtectionMinutes);
PTMagicConfiguration.GeneralSettings.Application.InstanceName = HttpContext.Request.Form["Application_InstanceName"];
@ -88,6 +64,7 @@ namespace Monitor.Pages
PTMagicConfiguration.GeneralSettings.Monitor.OpenBrowserOnStart = HttpContext.Request.Form["Monitor_OpenBrowserOnStart"].Equals("on");
PTMagicConfiguration.GeneralSettings.Monitor.AnalyzerChart = HttpContext.Request.Form["Monitor_AnalyzerChart"];
PTMagicConfiguration.GeneralSettings.Monitor.Port = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_Port"], PTMagicConfiguration.GeneralSettings.Monitor.Port);
PTMagicConfiguration.GeneralSettings.Monitor.LiveTCVTimeframeMinutes = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_LiveTCVTimeframeMinutes"], PTMagicConfiguration.GeneralSettings.Monitor.LiveTCVTimeframeMinutes);
PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_GraphIntervalMinutes"], PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes);
PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_GraphMaxTimeframeHours"], PTMagicConfiguration.GeneralSettings.Monitor.GraphMaxTimeframeHours);
PTMagicConfiguration.GeneralSettings.Monitor.ProfitsMaxTimeframeDays = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_ProfitsMaxTimeframeDays"], PTMagicConfiguration.GeneralSettings.Monitor.ProfitsMaxTimeframeDays);
@ -95,7 +72,7 @@ namespace Monitor.Pages
PTMagicConfiguration.GeneralSettings.Monitor.BagAnalyzerRefreshSeconds = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_BagAnalyzerRefreshSeconds"], PTMagicConfiguration.GeneralSettings.Monitor.BagAnalyzerRefreshSeconds);
PTMagicConfiguration.GeneralSettings.Monitor.BuyAnalyzerRefreshSeconds = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_BuyAnalyzerRefreshSeconds"], PTMagicConfiguration.GeneralSettings.Monitor.BuyAnalyzerRefreshSeconds);
PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform = HttpContext.Request.Form["Monitor_LinkPlatform"];
//PTMagicConfiguration.GeneralSettings.Monitor.MaxSalesRecords = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_MaxSalesRecords"], PTMagicConfiguration.GeneralSettings.Monitor.MaxSalesRecords);
PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout = HttpContext.Request.Form["Monitor_TVCustomLayout"];
PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_MaxTopMarkets"], PTMagicConfiguration.GeneralSettings.Monitor.MaxTopMarkets);
PTMagicConfiguration.GeneralSettings.Monitor.MaxDailySummaries = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_MaxDailySummaries"], PTMagicConfiguration.GeneralSettings.Monitor.MaxDailySummaries);
PTMagicConfiguration.GeneralSettings.Monitor.MaxMonthlySummaries = SystemHelper.TextToInteger(HttpContext.Request.Form["Monitor_MaxMonthlySummaries"], PTMagicConfiguration.GeneralSettings.Monitor.MaxMonthlySummaries);

View File

@ -116,13 +116,8 @@
</div>
</div>
</div>
</div>
<div class="card-box">
<h4 class="m-t-0 header-title">Global Settings Log</h4>
<table class="table table-striped table-sm">
@ -136,7 +131,7 @@
</thead>
<tbody>
@foreach (Core.Main.DataObjects.PTMagicData.GlobalSettingSummary gss in Model.Summary.GlobalSettingSummary.OrderByDescending(g => g.SwitchDateTime).Take(Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxSettingsLogEntries)) {
TimeSpan offsetTimeSpan = TimeSpan.Parse(Model.PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(Model.MiscData.TimeZoneOffset.Replace("+", ""));
DateTimeOffset settingActivationTime = gss.SwitchDateTime;
settingActivationTime = settingActivationTime.ToOffset(offsetTimeSpan);

View File

@ -4,6 +4,7 @@ using System.Linq;
using Microsoft.AspNetCore.Http;
using Core.Main;
using Core.Helper;
using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages
@ -14,6 +15,8 @@ namespace Monitor.Pages
public string SettingsDistribution24hChartDataJSON = "";
public string SettingsDistribution3dChartDataJSON = "";
private Dictionary<string, string> settingsChartColors = new Dictionary<string, string>();
public ProfitTrailerData PTData = null;
public MiscData MiscData { get; set; }
public void OnGet()
{
@ -24,6 +27,8 @@ namespace Monitor.Pages
private void BindData()
{
PTData = this.PtDataObject;
MiscData = this.PTData.Misc;
BuildMarketsWithSingleSettings();
BuildChartColors();
Build24hChartData();

View File

@ -1,174 +0,0 @@
@page
@model TransactionsModel
@{
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/bootstrap-datepicker/css/bootstrap-datepicker.min.css" rel="stylesheet">
<link href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/clockpicker/css/bootstrap-clockpicker.min.css" rel="stylesheet">
}
<div class="row">
<div class="col-md-12">
<div class="card-box">
<h4 class="m-t-0 header-title">Transactions</h4>
<p>
In this area you may add manual transactions (like deposits and withdrawals) to your PT Magic data. Adding this kind of information will help PT Magic calculating your percentage gains and your balance more accurately.
</p>
</div>
</div>
</div>
<form class="form-horizontal m-t-20" method="post">
<div class="row">
<div class="col-md-12">
<div class="card-box">
<h4 class="m-t-0 header-title">New Transaction</h4>
<div class="form-group row">
<label class="col-md-4 col-form-label">Amount <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The amount of your transaction. Positive numbers for deposits and negative numbers for withdrawals."></i></label>
<div class="col-md-8">
<input type="text" class="form-control" name="Transaction_Amount">
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Date <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The date of your transaction."></i></label>
<div class="col-md-8">
<div class="input-group">
<input type="text" class="form-control" placeholder="mm/dd/yyyy" id="datepicker-autoclose" name="Transaction_Date">
<span class="input-group-addon bg-custom b-0"><i class="md md-event-note text-dark"></i></span>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label">Time <i class="fa fa-info-circle text-muted" data-toggle="tooltip" data-placement="top" title="The time of your transaction."></i></label>
<div class="col-md-8">
<div class="input-group clockpicker m-b-20" data-placement="top" data-align="top" data-autoclose="true">
<input type="text" class="form-control" name="Transaction_Time">
<span class="input-group-addon"> <span class="md md-access-time"></span> </span>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-md-4 col-form-label"></label>
<div class="col-md-8">
<button class="btn btn-ptmagic btn-block text-uppercase waves-effect waves-light" type="submit">
Save Transaction
</button>
</div>
</div>
</div>
</div>
</div>
@if (!Model.ValidationMessage.Equals("")) {
<div class="row">
<div class="col-md-12">
<div class="card-box text-danger">
@Model.ValidationMessage
</div>
</div>
</div>
}
</form>
<div class="row">
<div class="col-md-12">
<div class="card-box">
<h4 class="m-t-0 header-title">Your Transactions</h4>
@if (Model.TransactionData.Transactions.Count > 0) {
<table class="tablesaw table m-b-0" data-tablesaw-sortable data-tablesaw-sortable-switch>
<thead>
<tr>
<th></th>
<th scope="col" data-tablesaw-sortable-col data-tablesaw-sortable-default-col>Time</th>
<th scope="col" data-tablesaw-sortable-col class="text-right">Amount</th>
<th scope="col" data-tablesaw-sortable-col>Type</th>
</tr>
</thead>
<tbody>
@foreach (Core.Main.DataObjects.PTMagicData.Transaction transaction in Model.TransactionData.Transactions) {
<tr>
<td style="width:20px;"><a href="#" class="btn-remove" data-transactionguid="@transaction.GUID"><i class="fa fa-remove text-danger"></i></a></td>
<td>@transaction.GetLocalDateTime(Model.PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset).ToShortDateString() @transaction.GetLocalDateTime(Model.PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset).ToShortTimeString()</td>
<td class="text-right text-autocolor">@transaction.Amount.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
@if (transaction.Amount > 0) {
<td class="text-success">Deposit</td>
} else {
<td class="text-danger">Withdrawal</td>
}
</tr>
}
</tbody>
</table>
} else {
<p>No transactions found.</p>
}
</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/tablesaw/js/tablesaw-init.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>
<script src="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)assets/plugins/clockpicker/js/bootstrap-clockpicker.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
jQuery('#datepicker-autoclose').datepicker({
weekStart: 1,
autoclose: true,
todayHighlight: true
});
$('.clockpicker').clockpicker({
donetext: 'Done'
});
@if (!Model.NotifyType.Equals("") && !Model.NotifyHeadline.Equals("") && !Model.NotifyMessage.Equals("")) {
<text>
$.Notification.notify('@Model.NotifyType', 'top left', '@Model.NotifyHeadline', '@Model.NotifyMessage');
</text>
}
$('.btn-remove').click(function () {
var tGuid = $(this).data('transactionguid');
var postData = { Transaction_GUID: tGuid };
$.ajax({
type: 'POST',
url: "@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_post/RemoveTransaction",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(postData),
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function (data) {
$.Notification.notify('success', 'top left', 'Transaction removed!', 'Transaction "' + tGuid + '" was successfully removed.');
window.location = window.location.href;
},
error: function (jqxhr, errorText, thrownError) {
$.Notification.notify('error', 'top left', 'Error removing transaction "' + tGuid + '"!', 'Error message: ' + errorText);
}
});
return false;
});
});
</script>
}

View File

@ -1,78 +0,0 @@
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;
using System.Globalization;
namespace Monitor.Pages
{
public class TransactionsModel : _Internal.BasePageModelSecure
{
public TransactionData TransactionData = null;
public string ValidationMessage = "";
public void OnGet()
{
base.Init();
BindData();
}
private void BindData()
{
TransactionData = new TransactionData(PTMagicBasePath);
}
public void OnPost()
{
base.Init();
BindData();
SaveTransaction();
}
private void SaveTransaction()
{
double transactionAmount = 0;
DateTimeOffset transactionDateTime = Constants.confMinDate;
try
{
transactionAmount = SystemHelper.TextToDouble(HttpContext.Request.Form["Transaction_Amount"], transactionAmount, "en-US");
//transactionDateTime = DateTimeOffset.Parse(HttpContext.Request.Form["Transaction_Date"] + " " + HttpContext.Request.Form["Transaction_Time"], CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
DateTime tmp = DateTime.Parse(HttpContext.Request.Form["Transaction_Date"] + " " + HttpContext.Request.Form["Transaction_Time"], CultureInfo.InvariantCulture, DateTimeStyles.None);
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
transactionDateTime = new DateTimeOffset(tmp, offsetTimeSpan);
}
catch { }
if (transactionAmount == 0)
{
ValidationMessage = "Please enter a valid amount in the format 123.45!";
}
else
{
if (transactionDateTime == Constants.confMinDate)
{
ValidationMessage = "Please select a valid date and time!";
}
else
{
TransactionData.Transactions.Add(new Transaction() { GUID = Guid.NewGuid().ToString(), Amount = transactionAmount, UTCDateTime = transactionDateTime.UtcDateTime });
TransactionData.SaveTransactions(PTMagicBasePath);
NotifyHeadline = "Transaction saved!";
NotifyMessage = "Transaction saved successfully to _data/Transactions.json.";
NotifyType = "success";
}
}
}
}
}

View File

@ -103,7 +103,7 @@
<div class="tradingview-widget-container">
<div id="tradingview_6aa22" style="height:600px;"></div>
<div class="tradingview-widget-copyright">
<a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform, Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, Model.DCAMarket, Model.Summary.MainMarket)" rel="noopener" target="_blank">
<a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform, Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, Model.DCAMarket, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" rel="noopener" target="_blank">
<span class="blue-text">@Model.DCAMarket</span> <span class="blue-text">chart</span> by TradingView</a>
</div>
</div>

View File

@ -10,6 +10,7 @@ using Core.MarketAnalyzer;
namespace Monitor.Pages {
public class BagDetailsModel : _Internal.BasePageModelSecure {
public ProfitTrailerData PTData = null;
public MiscData MiscData = null;
public string DCAMarket = "";
public DCALogData DCALogData = null;
public DateTimeOffset DateTimeNow = Constants.confMinDate;
@ -23,13 +24,12 @@ namespace Monitor.Pages {
private void BindData() {
DCAMarket = GetStringParameter("m", "");
PTData = this.PtDataObject;
MiscData = this.PTData.Misc;
DCALogData = PTData.DCALog.Find(d => d.Market == DCAMarket);
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(MiscData.TimeZoneOffset.Replace("+", ""));
DateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
}
}

View File

@ -84,9 +84,9 @@
<tr @(lostValue ? "class=errorRow" : "" ) >
// Market
@if (mps != null && (mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0)) {
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a></th>
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@dcaLogEntry.Market</a></th>
} else {
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a>
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@dcaLogEntry.Market</a>
<i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>">
</i>
</th>

View File

@ -37,9 +37,9 @@
string triggerValueText = Core.ProfitTrailer.StrategyHelper.GetTriggerValueText(Model.Summary, buyLogEntry.BuyStrategies, buyLogEntry.BuyStrategy, buyLogEntry.BBTrigger, buyLogEntry.TriggerValue, 0, true);
<tr>
@if (mps != null && (mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0)) {
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@buyLogEntry.Market</a></th>
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@buyLogEntry.Market</a></th>
} else {
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@buyLogEntry.Market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@buyLogEntry.Market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
}
<td class="text-autocolor">@buyLogEntry.PercChange.ToString("#,#0.00")%</td>
@if (buyDisabled) {

View File

@ -10,7 +10,48 @@
}
<div class="row">
<div class="col-md-5 px-1">
<div class="col-md-3 px-1">
<div class="card-box px-1" style="height:240px;">
<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"
title="All charts set to refresh every @Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds seconds in your general settings."></div>
@{
string totalCurrentValueString = Model.totalCurrentValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"));
if (Model.totalCurrentValue > 100) {
totalCurrentValueString = Math.Round(Model.totalCurrentValue, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"));
}
}
<div id="AssetDistribution" class="container" style="height: 100%; width: 100%;">
<div class="text-center">
<span data-toggle="tooltip" data-placement="top" title="Total current account value">TCV: <text class="text-autocolor">@totalCurrentValueString @Model.Summary.MainMarket </text> </span>
</div>
<div class="text-center">
<small>
<span data-toggle="tooltip" data-placement="top" title="Starting balance from PTM settings">Start: <text class="text-autocolor">@Model.MiscData.StartBalance </text></span>
<span data-toggle="tooltip" data-placement="top" title="TCV gain on starting balance">&emsp; Gain: <text class="text-autocolor">@Math.Round(((Model.totalCurrentValue - Model.MiscData.StartBalance) / Model.MiscData.StartBalance) * 100, 2)%</text></span>
</small>
</div>
<svg style="height:100%;width:100%"></svg>
</div>
</div>
</div>
<div class="col-md-9">
<div class="card-box px-2" style="height:240px;">
<h4 class="m-t-0 header-title"><b>Live TCV Trend </b><i class="fa fa-info-circle text-muted" style="font-size x-small" data-toggle="tooltip" data-placement="top" title="Data is added while the monitor is running. Currently set to show the past @Model.PTMagicConfiguration.GeneralSettings.Monitor.LiveTCVTimeframeMinutes minutes in your monitor settings."></i>
@if (!Model.TotalCurrentValueLiveChartDataJSON.Equals("")) {
<div class="TCVLive-chart">
<svg style="height:220px;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:340px;">
<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" style="font-size x-small" 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 at @Model.PTMagicConfiguration.GeneralSettings.Monitor.GraphIntervalMinutes intervals, in general settings."></i></h4>
@if (!Model.TrendChartDataJSON.Equals("")) {
@ -23,37 +64,12 @@
</div>
</div>
<div class="col-md-3 px-1">
<div class="card-box px-3" style="height:340px;">
<div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds * 1000)" data-color="#aaa,#414d59"
title="All charts set to refresh every @Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds seconds in your general settings."></div>
@{
string totalCurrentValueString = Model.totalCurrentValue.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"));
if (Model.totalCurrentValue > 100) {
totalCurrentValueString = Math.Round(Model.totalCurrentValue, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"));
}
}
<div id="AssetDistribution" class="container">
<div class="text-center">
<small>
<span data-toggle="tooltip" data-placement="top" title="Starting balance from PTM settings">Start: &nbsp; <text class="text-autocolor"> @Model.MiscData.StartBalance @Model.Summary.MainMarket </text></span>
<span data-toggle="tooltip" data-placement="top" title="TCV gain on starting balance"> &emsp; &emsp; Gain:&nbsp;<text class="text-autocolor">@Math.Round(((Model.totalCurrentValue - Model.MiscData.StartBalance) / Model.MiscData.StartBalance) * 100, 2)%</text></span>
</small>
</div>
<div class="text-center">
<span data-toggle="tooltip" data-placement="top" title="Total current account value">TCV: &nbsp; <text class="text-autocolor"> @totalCurrentValueString @Model.Summary.MainMarket </text> </span>
</div>
<div class="row px1">
<svg style="height:260px;width:100%"></svg>
</div>
</div>
</div>
</div>
<div class="col-md-4 px-1">
<div class="col-md-6 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:340px;">
<h4 class="m-t-0 m-b-20 header-title" style="display: inline;">Daily Profit <i class="fa fa-info-circle text-muted" style="font-size x-small" 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>
<h4 class="m-t-0 m-b-20 header-title" style="display: inline;">Daily Profit <i class="fa fa-info-circle text-muted" style="font-size x-small" data-toggle="tooltip" data-placement="top" title="@Model.PTData.DailyPNL.Count 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>
@ -70,9 +86,9 @@
<div class="card-box px-3">
@* <div class="cdev" data-percent="100" data-duration="@Html.Raw(@Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeco;nds * 1000)" data-color="#aaa,#414d59"></div>
<br> *@
<h4 class="m-t-0 m-b-20 header-title">Live Trends
<h4 class="m-t-0 m-b-20 header-title">Live Market Trends
<i class="fa fa-info-circle text-muted" style="font-size small" data-toggle="tooltip" data-placement="top" title="Set to refresh every @Model.PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds seconds in general settings."></i>
<small class="pull-right" style="font-size: x-small"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)MarketAnalyzer">ANALYZER</a></small>
<small class="pull-right" style="font-size: small"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)MarketAnalyzer">ANALYZER</a></small>
</h4>
<table class="table table-sm">
<thead>
@ -302,15 +318,20 @@
.labelThreshold(.1)
.labelType("percent")
.donut(true)
.donutRatio(0.3);
.donutRatio(0.3)
.margin({top: 10, bottom: 10})
.showLegend(false); // Hide the legend
assetDistributionData = @Html.Raw(Model.AssetDistributionData);
d3.select("#AssetDistribution svg")
.style('height', '90%')
.style('width', '100%')
.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);
@ -455,3 +476,50 @@
$('[data-toggle="tooltip"]').tooltip();
});
</script>
<script type="text/javascript">
(function ($) {
'use strict';
$('[role="tooltip"]').remove();
$('[data-toggle="tooltip"]').tooltip();
$('.text-autocolor').autocolor(false);
var TCVLiveChart; // Keep a reference to the chart
var TCVLiveData; // Keep a reference to the data
@if (!Model.TotalCurrentValueLiveChartDataJSON.Equals("")) {
<text>
nv.addGraph(function () {
TCVLiveChart = nv.models.lineChart();
TCVLiveChart.useInteractiveGuideline(true);
TCVLiveChart.xAxis.tickFormat(function (d) { return d3.time.format('%H:%M:%S')(new Date(d)); });
TCVLiveChart.yAxis.axisLabel('').tickFormat(d3.format(',.2f'));
TCVLiveData = @Html.Raw(Model.TotalCurrentValueLiveChartDataJSON);
d3.select('.TCVLive-chart svg')
.style('width', '100%')
.datum(TCVLiveData)
.transition().duration(0)
.call(TCVLiveChart);
// Add mouseleave, and mousemove event listeners to hide tooltip
d3.select('.TCVLive-chart').on('mouseleave', function() {
d3.select('.nvtooltip').style('opacity', 0);
});
d3.select('body').on('mousemove', function() {
var chartBounds = d3.select('.TCVLive-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);
}
});
nv.utils.windowResize(TCVLiveChart.update);
return TCVLiveChart;
});
</text>
}
})(jQuery);
</script>

View File

@ -26,6 +26,7 @@ namespace Monitor.Pages
public DateTimeOffset DateTimeNow = Constants.confMinDate;
public string AssetDistributionData = "";
public double totalCurrentValue = 0;
public string TotalCurrentValueLiveChartDataJSON { get; set; }
public void OnGet()
{
// Initialize Config
@ -49,7 +50,7 @@ namespace Monitor.Pages
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("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(MiscData.TimeZoneOffset.Replace("+", ""));
DateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
// Get last and current active setting
@ -65,7 +66,108 @@ namespace Monitor.Pages
BuildMarketTrendChartData();
BuildAssetDistributionData();
BuildProfitChartData();
StartUpdatingTotalCurrentValueLive();
UpdateTotalCurrentValueLive();
BuildTotalCurrentValueLiveChartData();
}
private static System.Timers.Timer timer;
private static List<(DateTime Timestamp, double TotalCurrentValue)> totalCurrentValueLiveList;
public void StartUpdatingTotalCurrentValueLive()
{
int liveTCVInterval = PTMagicConfiguration.GeneralSettings.Monitor.RefreshSeconds;
if (timer != null)
{
// Timer is already running
return;
}
totalCurrentValueLiveList = new List<(DateTime Timestamp, double TotalCurrentValueLive)>();
timer = new System.Timers.Timer(liveTCVInterval * 1000); // Set interval to liveTCVTimer seconds
timer.Elapsed += (sender, e) => UpdateTotalCurrentValueLive();
timer.Start();
}
private void UpdateTotalCurrentValueLive()
{
double PairsBalance = 0.0;
double DCABalance = 0.0;
double PendingBalance = 0.0;
double AvailableBalance = PTData.GetCurrentBalance();
bool isSellStrategyTrue = false;
bool isTrailingSellActive = false;
foreach (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)
{
leverage = 1;
}
if (sellStrategyText.Contains("PENDING"))
{
PendingBalance = PendingBalance + (dcaLogEntry.Amount * dcaLogEntry.CurrentPrice / leverage);
}
else if (dcaLogEntry.BuyStrategies.Count > 0)
{
DCABalance = DCABalance + (dcaLogEntry.Amount * dcaLogEntry.CurrentPrice / leverage);
}
else
{
PairsBalance = PairsBalance + (dcaLogEntry.Amount * dcaLogEntry.CurrentPrice / leverage);
}
}
double totalCurrentValueLive = PendingBalance + DCABalance + PairsBalance + AvailableBalance;
// Get the current time
DateTime now = DateTime.UtcNow;
totalCurrentValueLiveList.Add((now, totalCurrentValueLive));
// Get liveTCVTimeframe from PTMagicConfiguration.GeneralSettings.Monitor
int liveTCVTimeframe = PTMagicConfiguration.GeneralSettings.Monitor.LiveTCVTimeframeMinutes;
// Calculate the timestamp that is liveTCVTimeframe minutes ago
DateTime threshold = now.AddMinutes(-liveTCVTimeframe);
// Remove all data points that are older than the threshold
while (totalCurrentValueLiveList.Count > 0 && totalCurrentValueLiveList[0].Item1 < threshold)
{
totalCurrentValueLiveList.RemoveAt(0);
}
}
private void BuildTotalCurrentValueLiveChartData()
{
List<object> TotalCurrentValueLivePerIntervalList = new List<object>();
if (totalCurrentValueLiveList.Count > 0)
{
foreach (var dataPoint in totalCurrentValueLiveList)
{
DateTime timestamp = dataPoint.Timestamp;
double totalCurrentValueLive = dataPoint.TotalCurrentValue;
// Convert the timestamp to a Unix timestamp
long unixTimestamp = new DateTimeOffset(timestamp).ToUnixTimeMilliseconds();
// Add the data point to the list
TotalCurrentValueLivePerIntervalList.Add(new { x = unixTimestamp, y = totalCurrentValueLive });
}
// Convert the list to a JSON string using Newtonsoft.Json
TotalCurrentValueLiveChartDataJSON = Newtonsoft.Json.JsonConvert.SerializeObject(new[] {
new {
key = "Total Current Value",
color = Constants.ChartLineColors[1],
values = TotalCurrentValueLivePerIntervalList
}
});
}
}
private void BuildMarketTrendChartData()
{
@ -95,8 +197,8 @@ namespace Monitor.Pages
// Get trend ticks for chart
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{
@ -158,8 +260,8 @@ namespace Monitor.Pages
{
// Get timezone offset
TimeSpan offset;
bool isNegative = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.StartsWith("-");
string offsetWithoutSign = PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.TrimStart('+', '-');
bool isNegative = MiscData.TimeZoneOffset.StartsWith("-");
string offsetWithoutSign = MiscData.TimeZoneOffset.TrimStart('+', '-');
if (!TimeSpan.TryParse(offsetWithoutSign, out offset))
{

View File

@ -3,13 +3,15 @@
@{
Layout = null;
}
<div class="row">
@{
bool sideBySide = true;
}
<div class="@(sideBySide ? "row" : "col-md-12")">
@if (Model.PTMagicConfiguration.GeneralSettings.Monitor.MaxDashboardBuyEntries>0)
{
<div class="col-md-6 px-1">
<div class="col-md px-1">
<div class="card-box px-2">
<h4 class="m-t-0 m-b-20 header-title"><b>Possible Buys (@Model.PTData.BuyLog.Count)</b><small id="buylist-refresh-icon"></small><small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)BuyAnalyzer">more</a></small></h4>
<h4 class="m-t-0 m-b-20 header-title"><b>Possible Buys (@Model.PTData.BuyLog.Count)</b><small id="buylist-refresh-icon"><i class="fa fa-info-circle text-muted" style="font-size x-small" data-toggle="tooltip" data-placement="top" title="Set 'Max Dashboard Buy Entries' to zero in Monitor Settings, to hide this table."></i></small><small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)BuyAnalyzer">more</a></small></h4>
@if (Model.PTData.BuyLog.Count == 0)
{
<p>Your Profit Trailer did not find anything worth buying so far.</p>
@ -19,11 +21,10 @@
<table class="table table-sm m-b-0">
<thead>
<tr>
<th>Market</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="24 Hour price trend">24H</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="24 Hour trading volume">Volume</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="Current ask price for this market">Ask</th>
<th>Buy Strategies</th>
<th><strong>Market </strong><i class="fa fa-info-circle text-muted" style="font-size: x-small" data-toggle="tooltip" data-placement="top" title="Market and 24h CHANGE"></i></th>
<th><strong>Volume </strong><i class="fa fa-info-circle text-muted" style="font-size: x-small" data-toggle="tooltip" data-placement="top" title="24h VOLUME"></i></th>
<th><strong>Ask </strong></th>
<th><strong>Buy Strategies </strong></th>
</tr>
</thead>
<tbody>
@ -57,13 +58,21 @@
<tr>
@if (mps == null || mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0) {
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@buyLogEntry.Market</a></th>
<th>
<span style="font-size: 1.3em;"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@buyLogEntry.Market</span>
<br><span class="text-autocolor">@Html.Raw((buyLogEntry.PercChange * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))) % </span>
</th>
} else {
<th class="align-top; text-nowrap"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@buyLogEntry.Market &nbsp;</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
<th>
<div style="white-space: nowrap;">
<span style="font-size: 1.3em;"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, buyLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@buyLogEntry.Market</a></span>
&nbsp;<i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i>
</div>
<span class="text-autocolor">@Html.Raw((buyLogEntry.PercChange * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))) % </span>
</th>
}
<td class="text-autocolor">@string.Format("{0}%", (buyLogEntry.PercChange * 100).ToString("#,#0.00"))</td>
<td class="text">@string.Format("{0}", (buyLogEntry.Volume24h).ToString())</td>
<td class="text-left">@buyLogEntry.CurrentPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
<td >@string.Format("{0}", (buyLogEntry.Volume24h).ToString())</td>
<td >@buyLogEntry.CurrentPrice.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US"))</td>
@if (buyDisabled) {
<td>@Html.Raw(buyStrategyText)</td>
@ -85,7 +94,7 @@
<div class="col-md px-1">
<div class="card-box px-2">
<h4 class="m-t-0 m-b-20 header-title"><b>Pairs / DCA / Pending (@Model.PTData.DCALog.Count)</b><small id="baglist-refresh-icon"></small><small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)BagAnalyzer">more</a></small></h4>
<h4 class="m-t-0 m-b-20 header-title"><b>Positions (@Model.PTData.DCALog.Count)</b><small id="baglist-refresh-icon"></small><small class="pull-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)BagAnalyzer">more</a></small></h4>
@if (Model.PTData.DCALog.Count == 0)
{
@ -94,16 +103,15 @@
else
{
<div class="table-responsive">
<table class="table table-sm m-b-0">
<table class="table table-sm m-b-0 table-auto-width">
<thead>
<tr>
<th>Market</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="24 Hour Trend">24H</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="Total Buy Cost">Cost</th>
<th><strong>Market </strong><i class="fa fa-info-circle text-muted" style="font-size: x-small" data-toggle="tooltip" data-placement="top" title="Market and 24h CHANGE"></i></th>
<th><strong>Cost </strong><i class="fa fa-info-circle text-muted" style="font-size: x-small" data-toggle="tooltip" data-placement="top" title="Total COST and TIME HELD"></i></th>
<th></th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="Active Buy Strategies">DCA</th>
<th class="text-left" data-toggle="tooltip" data-placement="top" title="Active Sell Strategies">Sell</th>
<th class="text-left" data-toggle="tooltip" data-html="true" data-placement="top" title="Profit Target <br> Current Profit">Profit</th>
<th><strong>DCA </strong></th>
<th><strong>Sell </strong></th>
<th><strong>Profit </strong><i class="fa fa-info-circle text-muted" style="font-size: x-small" data-toggle="tooltip" data-placement="top" title="Proft TARGET and CURRENT Profit"></i></th>
<th></th>
</tr>
</thead>
@ -142,7 +150,6 @@
if (dcaLogEntry.SellStrategies.Count > 0) {
isSellStrategyTrue = (dcaLogEntry.SellStrategies.FindAll(ss => !ss.IsTrue).Count == 0);
}
string leverage = "";
double leverageValue = 1;
string buyStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.BuyStrategies, dcaLogEntry.BuyStrategy, isBuyStrategyTrue, isTrailingBuyActive);
@ -155,54 +162,37 @@
// Profit percentage
var profitPercentage = dcaLogEntry.ProfitPercent;
// if (dcaLogEntry.SellStrategies != null)
// {
// var gainStrategy = dcaLogEntry.SellStrategies.FirstOrDefault(x => x.Name.Contains(" GAIN", StringComparison.InvariantCultureIgnoreCase));
// if (gainStrategy != null)
// {
// // Use the gain percentage value as it is accurate to what can be achieved with the order book!
// profitPercentage = gainStrategy.CurrentValue;
// }
// }
// Render the row
if (!sellStrategyText.Contains("PENDING-BUY"))
{
<tr @(lostValue ? "class=errorRow" : "") >
<!-- Market -->
<td class="align-top; text-nowrap">
<b>
@if (mps == null || mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0)
{
<a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a>
<span style="font-size: 1.3em;"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@dcaLogEntry.Market</a></span>
} else
{
<a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market &nbsp;</a><i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i>
<span style="font-size: 1.3em;"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket, Model.PTMagicConfiguration.GeneralSettings.Monitor.TVCustomLayout)" target="_blank">@dcaLogEntry.Market &nbsp;</a></span><i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i>
}
</b>
<br>
@bagAgeText
</td>
<br><span class="text-autocolor">@Html.Raw((dcaLogEntry.PercChange * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))) %</span>
<!-- 24hr change -->
<td class="text-autocolor">@Html.Raw((dcaLogEntry.PercChange * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")))%</td>
</td>
<!-- Cost -->
<td class="text-left">@Html.Raw(dcaLogEntry.TotalCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")))</td>
<td class="text-left">@Html.Raw(dcaLogEntry.TotalCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")))<br><span class="text-highlight">@bagAgeText</span></td>
<!-- DCA Count -->
<td class="text-right">
@if (dcaEnabled)
{
@if (dcaLogEntry.BoughtTimes > 0)
if (dcaLogEntry.BoughtTimes > 0)
{
@dcaLogEntry.BoughtTimes;
}
} else
{
<span data-toggle="tooltip" data-placement="top" title="DCA is disabled"><i class="fa fa-ban text-highlight"></i></span>
<span data-toggle="tooltip" data-placement="top" title="DCA disabled"><i class="fa fa-ban text-highlight"></i></span>
}
</td>
<!-- DCA Strategy -->
@ -234,7 +224,7 @@
double TargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value;
<td>@TargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%
<br>
<div class="text-autocolor">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%</div>
<div class="text-autocolor">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</div>
</td>
}
else
@ -242,7 +232,7 @@
<td>
<div class="text-left">None</div>
<br>
<div class="text-autocolor">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%</div>
<div class="text-autocolor">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) %</div>
</td>
}
@ -262,17 +252,15 @@
Model.TotalBagCost = Model.TotalBagCost + dcaLogEntry.TotalCost;
Model.TotalBagGain = Model.TotalBagGain + bagGain;
}
}
}
<td>Totals:</td>
<td></td>
<td>@Html.Raw(Model.TotalBagCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")))</td>
<td style="font-size: 1.2em;"><strong>Totals:</strong></td>
<td style="font-size: 1.2em;"><strong>@Html.Raw(Model.TotalBagCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")))</strong></td>
<td></td>
<td></td>
<td></td>
<td class="text-autocolor">@Html.Raw((((Model.TotalBagGain) / Model.TotalBagCost) * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")))%</td>
<td class="text-autocolor; font-size: 1.2em;"><strong>@Html.Raw((((Model.TotalBagGain) / Model.TotalBagCost) * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))) %</strong></td>
<td></td>
</tbody>
</table>
</div>

View File

@ -1,15 +1,16 @@
using System;
using Core.Main;
using Core.Main.DataObjects;
using Core.Main.DataObjects.PTMagicData;
namespace Monitor.Pages {
public class DashboardTopModel : _Internal.BasePageModelSecureAJAX {
public ProfitTrailerData PTData = null;
public MiscData MiscData = null;
public DateTimeOffset DateTimeNow = Constants.confMinDate;
public void OnGet() {
// Initialize Config
base.Init();
BindData();
}
public double TotalBagCost = 0;
@ -17,9 +18,9 @@ namespace Monitor.Pages {
public double TotalBagGain = 0;
private void BindData() {
PTData = this.PtDataObject;
MiscData = this.PTData.Misc;
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(MiscData.TimeZoneOffset.Replace("+", ""));
DateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
}
}

View File

@ -10,7 +10,7 @@
"ProfitTrailerMonitorURLXtra": "", // URLs for additional bots you want PTM to update (optional - comma separated list)
"ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings)
"Exchange": "Bittrex", // The exchange your are running Profit Trailer on
"TimezoneOffset": "+0:00", // Your timezone offset from UTC time
//"TimezoneOffset": "+0:00", // Your timezone offset from UTC time
"FloodProtectionMinutes": 0, // If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute
"InstanceName": "PT Magic", // The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them
//"FreeCurrencyConverterAPIKey": "" // If "MainFiatCurrency" above is anything other than USD, you must obtain an API key from https://free.currencyconverterapi.com/free-api-key

View File

@ -10,7 +10,7 @@
"ProfitTrailerMonitorURLXtra": "", // URLs for additional bots you want PTM to update (optional - comma separated list)
"ProfitTrailerDefaultSettingName": "default", // Your Profit Trailer default setting name (needed to change your settings)
"Exchange": "Bittrex", // The exchange your are running Profit Trailer on
"TimezoneOffset": "+0:00", // Your timezone offset from UTC time
//"TimezoneOffset": "+0:00", // Your timezone offset from UTC time
"FloodProtectionMinutes": 0, // If a price trend is just zig-zagging around its trigger, you may want to protect your settings from getting switched back and forth every minute
"InstanceName": "PT Magic", // The name of the instance of this bot. This will be used in your monitor and your Telegram messages. In case you are running more than one bot, you may set different names to separate them
"CoinMarketCapAPIKey": "", //CoinMarketCap Api