Performance optimised with caching and async loads
This commit is contained in:
parent
7141b0d2cd
commit
377e443f62
|
@ -5,6 +5,7 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Diagnostics;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Core.Main.DataObjects.PTMagicData;
|
using Core.Main.DataObjects.PTMagicData;
|
||||||
|
|
||||||
|
@ -21,28 +22,13 @@ namespace Core.Main.DataObjects
|
||||||
private PTMagicConfiguration _systemConfiguration = null;
|
private PTMagicConfiguration _systemConfiguration = null;
|
||||||
private TransactionData _transactionData = null;
|
private TransactionData _transactionData = null;
|
||||||
private DateTimeOffset _dateTimeNow = Constants.confMinDate;
|
private DateTimeOffset _dateTimeNow = Constants.confMinDate;
|
||||||
|
private DateTime _buyLogRefresh = DateTime.UtcNow, _sellLogRefresh = DateTime.UtcNow, _dcaLogRefresh = DateTime.UtcNow, _summaryRefresh = DateTime.UtcNow;
|
||||||
|
private volatile object _buyLock = new object(), _sellLock = new object(), _dcaLock = new object(), _summaryLock = new object();
|
||||||
|
|
||||||
public ProfitTrailerData(PTMagicConfiguration systemConfiguration)
|
public ProfitTrailerData(PTMagicConfiguration systemConfiguration)
|
||||||
{
|
{
|
||||||
_systemConfiguration = systemConfiguration;
|
_systemConfiguration = systemConfiguration;
|
||||||
|
|
||||||
Parallel.Invoke(() =>
|
|
||||||
{
|
|
||||||
_summary = BuildSummaryData(GetDataFromProfitTrailer("api/v2/data/misc"));
|
|
||||||
},
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
this.BuildSellLogData(GetDataFromProfitTrailer("/api/v2/data/sales"));
|
|
||||||
},
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
this.BuildBuyLogData(GetDataFromProfitTrailer("/api/v2/data/pbl", true));
|
|
||||||
},
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
this.BuildDCALogData(GetDataFromProfitTrailer("/api/v2/data/dca", true), GetDataFromProfitTrailer("/api/v2/data/pairs", true), GetDataFromProfitTrailer("/api/v2/data/pending", true), GetDataFromProfitTrailer("/api/v2/data/watchmode", true));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Convert local offset time to UTC
|
// Convert local offset time to UTC
|
||||||
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
|
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
|
||||||
_dateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
|
_dateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
|
||||||
|
@ -52,6 +38,19 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (_summary == null || (DateTime.UtcNow > _summaryRefresh))
|
||||||
|
{
|
||||||
|
lock (_summaryLock)
|
||||||
|
{
|
||||||
|
// Thread double locking
|
||||||
|
if (_summary == null || (DateTime.UtcNow > _summaryRefresh))
|
||||||
|
{
|
||||||
|
_summary = BuildSummaryData(GetDataFromProfitTrailer("api/v2/data/misc"));
|
||||||
|
_summaryRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.RefreshSeconds - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return _summary;
|
return _summary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +58,20 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (_sellLog == null || (DateTime.UtcNow > _sellLogRefresh))
|
||||||
|
{
|
||||||
|
lock (_sellLock)
|
||||||
|
{
|
||||||
|
// Thread double locking
|
||||||
|
if (_sellLog == null || (DateTime.UtcNow > _sellLogRefresh))
|
||||||
|
{
|
||||||
|
_sellLog.Clear();
|
||||||
|
this.BuildSellLogData(GetDataFromProfitTrailer("/api/v2/data/sales"));
|
||||||
|
_sellLogRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.RefreshSeconds - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return _sellLog;
|
return _sellLog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +80,7 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.Date);
|
return SellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.Date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +88,7 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.AddDays(-1).Date);
|
return SellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.AddDays(-1).Date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +96,7 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _sellLog.FindAll(sl => sl.SoldDate.Date >= _dateTimeNow.DateTime.AddDays(-7).Date);
|
return SellLog.FindAll(sl => sl.SoldDate.Date >= _dateTimeNow.DateTime.AddDays(-7).Date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +104,7 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _sellLog.FindAll(sl => sl.SoldDate.Date >= _dateTimeNow.DateTime.AddDays(-30).Date);
|
return SellLog.FindAll(sl => sl.SoldDate.Date >= _dateTimeNow.DateTime.AddDays(-30).Date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +112,40 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (_dcaLog == null || (DateTime.UtcNow > _dcaLogRefresh))
|
||||||
|
{
|
||||||
|
lock (_dcaLock)
|
||||||
|
{
|
||||||
|
// Thread double locking
|
||||||
|
if (_dcaLog == null || (DateTime.UtcNow > _dcaLogRefresh))
|
||||||
|
{
|
||||||
|
dynamic dcaData = null, pairsData = null, pendingData = null, watchData = null;
|
||||||
|
_dcaLog.Clear();
|
||||||
|
|
||||||
|
Parallel.Invoke(() =>
|
||||||
|
{
|
||||||
|
dcaData = GetDataFromProfitTrailer("/api/v2/data/dca", true);
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
pairsData = GetDataFromProfitTrailer("/api/v2/data/pairs", true);
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
pendingData = GetDataFromProfitTrailer("/api/v2/data/pending", true);
|
||||||
|
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
watchData = GetDataFromProfitTrailer("/api/v2/data/watchmode", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.BuildDCALogData(dcaData, pairsData, pendingData, watchData);
|
||||||
|
_dcaLogRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.BagAnalyzerRefreshSeconds - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return _dcaLog;
|
return _dcaLog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +154,20 @@ namespace Core.Main.DataObjects
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (_buyLog == null || (DateTime.UtcNow > _buyLogRefresh))
|
||||||
|
{
|
||||||
|
lock (_buyLock)
|
||||||
|
{
|
||||||
|
// Thread double locking
|
||||||
|
if (_buyLog == null || (DateTime.UtcNow > _buyLogRefresh))
|
||||||
|
{
|
||||||
|
_buyLog.Clear();
|
||||||
|
this.BuildBuyLogData(GetDataFromProfitTrailer("/api/v2/data/pbl", true));
|
||||||
|
_buyLogRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.BuyAnalyzerRefreshSeconds - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return _buyLog;
|
return _buyLog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,17 +190,17 @@ namespace Core.Main.DataObjects
|
||||||
this.Summary.PendingValue +
|
this.Summary.PendingValue +
|
||||||
this.Summary.DustValue);
|
this.Summary.DustValue);
|
||||||
}
|
}
|
||||||
public double GetPairsBalance()
|
public double GetPairsBalance()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
(this.Summary.PairsValue);
|
(this.Summary.PairsValue);
|
||||||
}
|
}
|
||||||
public double GetDCABalance()
|
public double GetDCABalance()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
(this.Summary.DCAValue);
|
(this.Summary.DCAValue);
|
||||||
}
|
}
|
||||||
public double GetPendingBalance()
|
public double GetPendingBalance()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
(this.Summary.PendingValue);
|
(this.Summary.PendingValue);
|
||||||
|
@ -169,6 +230,7 @@ namespace Core.Main.DataObjects
|
||||||
string url = string.Format("{0}{1}?token={2}", _systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL, callPath, _systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken);
|
string url = string.Format("{0}{1}?token={2}", _systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL, callPath, _systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken);
|
||||||
|
|
||||||
// Get the data from PT
|
// Get the data from PT
|
||||||
|
Debug.WriteLine(String.Format("{0} - Calling '{1}'", DateTime.UtcNow, url));
|
||||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||||
request.AutomaticDecompression = DecompressionMethods.GZip;
|
request.AutomaticDecompression = DecompressionMethods.GZip;
|
||||||
request.KeepAlive = true;
|
request.KeepAlive = true;
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Monitor.Pages
|
||||||
|
|
||||||
private void BindData()
|
private void BindData()
|
||||||
{
|
{
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Monitor.Pages
|
||||||
|
|
||||||
private void BindData()
|
private void BindData()
|
||||||
{
|
{
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Monitor.Pages
|
||||||
|
|
||||||
private void BindData()
|
private void BindData()
|
||||||
{
|
{
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Monitor.Pages
|
||||||
|
|
||||||
private void BindData()
|
private void BindData()
|
||||||
{
|
{
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
|
|
||||||
// Convert local offset time to UTC
|
// Convert local offset time to UTC
|
||||||
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
|
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Monitor.Pages {
|
||||||
private void BindData() {
|
private void BindData() {
|
||||||
DCAMarket = GetStringParameter("m", "");
|
DCAMarket = GetStringParameter("m", "");
|
||||||
|
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
|
|
||||||
DCALogData = PTData.DCALog.Find(d => d.Market == DCAMarket);
|
DCALogData = PTData.DCALog.Find(d => d.Market == DCAMarket);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Monitor.Pages {
|
||||||
SortFieldId = GetStringParameter("s", "ProfitPercent");
|
SortFieldId = GetStringParameter("s", "ProfitPercent");
|
||||||
SortDirection = GetStringParameter("d", "DESC");
|
SortDirection = GetStringParameter("d", "DESC");
|
||||||
|
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Monitor.Pages {
|
||||||
SortFieldId = GetStringParameter("s", "ProfitPercent");
|
SortFieldId = GetStringParameter("s", "ProfitPercent");
|
||||||
SortDirection = GetStringParameter("d", "DESC");
|
SortDirection = GetStringParameter("d", "DESC");
|
||||||
|
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Monitor.Pages {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindData() {
|
private void BindData() {
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
|
|
||||||
// Cleanup temp files
|
// Cleanup temp files
|
||||||
FileHelper.CleanupFilesMinutes(PTMagicMonitorBasePath + "wwwroot" + System.IO.Path.DirectorySeparatorChar + "assets" + System.IO.Path.DirectorySeparatorChar + "tmp" + System.IO.Path.DirectorySeparatorChar, 5);
|
FileHelper.CleanupFilesMinutes(PTMagicMonitorBasePath + "wwwroot" + System.IO.Path.DirectorySeparatorChar + "assets" + System.IO.Path.DirectorySeparatorChar + "tmp" + System.IO.Path.DirectorySeparatorChar, 5);
|
||||||
|
|
|
@ -53,15 +53,13 @@
|
||||||
buyDisabled = true;
|
buyDisabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
buyLogEntry.PercChange = @buyLogEntry.PercChange * 100;
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
@if (mps == null || mps.ActiveSingleSettings == null || mps.ActiveSingleSettings.Count == 0) {
|
@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)" target="_blank">@buyLogEntry.Market</a></th>
|
||||||
} else {
|
} 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)" 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>
|
<td class="text-autocolor">@string.Format("{0}%", (buyLogEntry.PercChange * 100).ToString("#,#0.00"))</td>
|
||||||
@if (buyDisabled) {
|
@if (buyDisabled) {
|
||||||
<td>@Html.Raw(buyStrategyText)</td>
|
<td>@Html.Raw(buyStrategyText)</td>
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Monitor.Pages {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindData() {
|
private void BindData() {
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
|
|
||||||
// Convert local offset time to UTC
|
// Convert local offset time to UTC
|
||||||
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
|
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Monitor.Pages {
|
||||||
salesDateString = GetStringParameter("d", "");
|
salesDateString = GetStringParameter("d", "");
|
||||||
salesMonthString = GetStringParameter("m", "");
|
salesMonthString = GetStringParameter("m", "");
|
||||||
|
|
||||||
PTData = new ProfitTrailerData(PTMagicConfiguration);
|
PTData = this.PtDataObject;
|
||||||
|
|
||||||
if (!salesDateString.Equals("")) {
|
if (!salesDateString.Equals("")) {
|
||||||
SalesDate = SystemHelper.TextToDateTime(salesDateString, Constants.confMinDate);
|
SalesDate = SystemHelper.TextToDateTime(salesDateString, Constants.confMinDate);
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Core.Helper;
|
||||||
using Core.Main.DataObjects.PTMagicData;
|
using Core.Main.DataObjects.PTMagicData;
|
||||||
using Core.MarketAnalyzer;
|
using Core.MarketAnalyzer;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Core.Main.DataObjects;
|
||||||
|
|
||||||
namespace Monitor._Internal
|
namespace Monitor._Internal
|
||||||
{
|
{
|
||||||
|
@ -28,6 +29,25 @@ namespace Monitor._Internal
|
||||||
public string NotifyType = "";
|
public string NotifyType = "";
|
||||||
|
|
||||||
public string MainFiatCurrencySymbol = "$";
|
public string MainFiatCurrencySymbol = "$";
|
||||||
|
private volatile object _ptDataLock = new object();
|
||||||
|
private static ProfitTrailerData _ptData = null;
|
||||||
|
|
||||||
|
// Profit Trailer data accessor object
|
||||||
|
public ProfitTrailerData PtDataObject
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_ptData == null)
|
||||||
|
{
|
||||||
|
lock (_ptDataLock)
|
||||||
|
{
|
||||||
|
_ptData = new ProfitTrailerData(PTMagicConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _ptData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void PreInit()
|
public void PreInit()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Core.Main;
|
using Core.Main;
|
||||||
using Core.Helper;
|
using Core.Helper;
|
||||||
using Core.Main.DataObjects.PTMagicData;
|
|
||||||
using Core.MarketAnalyzer;
|
|
||||||
using Core.ProfitTrailer;
|
|
||||||
using Microsoft.Extensions.Primitives;
|
|
||||||
|
|
||||||
namespace Monitor._Internal
|
namespace Monitor._Internal
|
||||||
{
|
{
|
||||||
|
|
||||||
public class BasePageModelSecure : BasePageModel
|
public class BasePageModelSecure : BasePageModel
|
||||||
{
|
{
|
||||||
public void Init()
|
public void Init()
|
||||||
|
|
Loading…
Reference in New Issue