Merge pull request #148 from djbadders/develop

Made compatible with PT 2.4 using API v2
This commit is contained in:
HojouFotytu 2019-10-14 09:46:26 +09:00 committed by GitHub
commit 69b902b6f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 165 additions and 229 deletions

View File

@ -4,12 +4,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
using Core.Main.DataObjects.PTMagicData;
@ -26,55 +22,13 @@ namespace Core.Main.DataObjects
private PTMagicConfiguration _systemConfiguration = null;
private TransactionData _transactionData = null;
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)
{
_systemConfiguration = systemConfiguration;
string html = "";
string url = systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL + "api/data?token=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken;
// Get the data from PT
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;
request.KeepAlive = true;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
html = reader.ReadToEnd();
reader.Close();
response.Close();
// Parse the JSON and build the data sets
dynamic rawPTData = JObject.Parse(html);
Parallel.Invoke(() =>
{
_summary = BuildSummaryData(rawPTData);
},
() =>
{
if (rawPTData.sellLogData != null)
{
this.BuildSellLogData(rawPTData.sellLogData, _systemConfiguration);
}
},
() =>
{
if (rawPTData.bbBuyLogData != null)
{
this.BuildBuyLogData(rawPTData.bbBuyLogData);
}
},
() =>
{
if (rawPTData.dcaLogData != null)
{
this.BuildDCALogData(rawPTData.dcaLogData, rawPTData.gainLogData, rawPTData.pendingLogData, rawPTData.watchModeLogData, _systemConfiguration);
}
});
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
_dateTimeNow = DateTimeOffset.UtcNow.ToOffset(offsetTimeSpan);
@ -84,6 +38,19 @@ namespace Core.Main.DataObjects
{
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;
}
}
@ -91,6 +58,20 @@ namespace Core.Main.DataObjects
{
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;
}
}
@ -99,7 +80,7 @@ namespace Core.Main.DataObjects
{
get
{
return _sellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.Date);
return SellLog.FindAll(sl => sl.SoldDate.Date == _dateTimeNow.DateTime.Date);
}
}
@ -107,7 +88,7 @@ namespace Core.Main.DataObjects
{
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);
}
}
@ -115,7 +96,7 @@ namespace Core.Main.DataObjects
{
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);
}
}
@ -123,7 +104,7 @@ namespace Core.Main.DataObjects
{
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);
}
}
@ -131,6 +112,40 @@ namespace Core.Main.DataObjects
{
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;
}
}
@ -139,6 +154,20 @@ namespace Core.Main.DataObjects
{
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;
}
}
@ -182,8 +211,6 @@ namespace Core.Main.DataObjects
(this.Summary.DustValue);
}
public double GetSnapshotBalance(DateTime snapshotDateTime)
{
double result = _systemConfiguration.GeneralSettings.Application.StartBalance;
@ -197,6 +224,39 @@ namespace Core.Main.DataObjects
return result;
}
private dynamic GetDataFromProfitTrailer(string callPath, bool arrayReturned = false)
{
string rawBody = "";
string url = string.Format("{0}{1}?token={2}", _systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL, callPath, _systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken);
// Get the data from PT
Debug.WriteLine(String.Format("{0} - Calling '{1}'", DateTime.UtcNow, url));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;
request.KeepAlive = true;
WebResponse response = request.GetResponse();
using (Stream dataStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(dataStream);
rawBody = reader.ReadToEnd();
reader.Close();
}
response.Close();
// Parse the JSON and build the data sets
if (!arrayReturned)
{
return JObject.Parse(rawBody);
}
else
{
return JArray.Parse(rawBody);
}
}
private SummaryData BuildSummaryData(dynamic PTData)
{
return new SummaryData()
@ -210,9 +270,9 @@ namespace Core.Main.DataObjects
};
}
private void BuildSellLogData(dynamic rawSellLogData, PTMagicConfiguration systemConfiguration)
private void BuildSellLogData(dynamic rawSellLogData)
{
foreach (var rsld in rawSellLogData)
foreach (var rsld in rawSellLogData.data)
{
SellLogData sellLogData = new SellLogData();
sellLogData.SoldAmount = rsld.soldAmount;
@ -236,7 +296,7 @@ namespace Core.Main.DataObjects
DateTimeOffset ptSoldDate = DateTimeOffset.Parse(dtDateTime.Year.ToString() + "-" + dtDateTime.Month.ToString("00") + "-" + dtDateTime.Day.ToString("00") + "T" + dtDateTime.Hour.ToString("00") + ":" + dtDateTime.Minute.ToString("00") + ":" + dtDateTime.Second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC sales time to local offset time
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(_systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
ptSoldDate = ptSoldDate.ToOffset(offsetTimeSpan);
sellLogData.SoldDate = ptSoldDate.DateTime;
@ -245,7 +305,7 @@ namespace Core.Main.DataObjects
}
}
private void BuildDCALogData(dynamic rawDCALogData, dynamic rawPairsLogData, dynamic rawPendingLogData, dynamic rawWatchModeLogData, PTMagicConfiguration systemConfiguration)
private void BuildDCALogData(dynamic rawDCALogData, dynamic rawPairsLogData, dynamic rawPendingLogData, dynamic rawWatchModeLogData)
{
foreach (var rdld in rawDCALogData)
{
@ -327,7 +387,7 @@ namespace Core.Main.DataObjects
DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rdldDateTime.Year.ToString() + "-" + rdldDateTime.Month.ToString("00") + "-" + rdldDateTime.Day.ToString("00") + "T" + rdldDateTime.Hour.ToString("00") + ":" + rdldDateTime.Minute.ToString("00") + ":" + rdldDateTime.Second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC bought time to local offset time
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(_systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan);
dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime;
@ -387,7 +447,7 @@ namespace Core.Main.DataObjects
DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rpldDateTime.Year.ToString() + "-" + rpldDateTime.Month.ToString("00") + "-" + rpldDateTime.Day.ToString("00") + "T" + rpldDateTime.Hour.ToString("00") + ":" + rpldDateTime.Minute.ToString("00") + ":" + rpldDateTime.Second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC bought time to local offset time
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(_systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan);
dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime;
@ -447,7 +507,7 @@ namespace Core.Main.DataObjects
DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rpldDateTime.Year.ToString() + "-" + rpldDateTime.Month.ToString("00") + "-" + rpldDateTime.Day.ToString("00") + "T" + rpldDateTime.Hour.ToString("00") + ":" + rpldDateTime.Minute.ToString("00") + ":" + rpldDateTime.Second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC bought time to local offset time
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(_systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan);
dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime;
@ -507,7 +567,7 @@ namespace Core.Main.DataObjects
DateTimeOffset ptFirstBoughtDate = DateTimeOffset.Parse(rpldDateTime.Year.ToString() + "-" + rpldDateTime.Month.ToString("00") + "-" + rpldDateTime.Day.ToString("00") + "T" + rpldDateTime.Hour.ToString("00") + ":" + rpldDateTime.Minute.ToString("00") + ":" + rpldDateTime.Second.ToString("00"), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
// Convert UTC bought time to local offset time
TimeSpan offsetTimeSpan = TimeSpan.Parse(systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
TimeSpan offsetTimeSpan = TimeSpan.Parse(_systemConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));
ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(offsetTimeSpan);
dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime;
@ -519,9 +579,6 @@ namespace Core.Main.DataObjects
_dcaLog.Add(dcaLogData);
}
}
private void BuildBuyLogData(dynamic rawBuyLogData)

View File

@ -1,115 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Core.Main;
using Core.Helper;
using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json;
namespace Core.ProfitTrailer
{
public static class SettingsAPI
{
public static void GetInitialProfitTrailerSettings(PTMagicConfiguration systemConfiguration)
{
string html = "";
string url = systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL + "api/data?token=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerServerAPIToken;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
html = reader.ReadToEnd();
reader.Close();
response.Close();
}
catch (System.Exception)
{
throw;
}
dynamic json = JsonConvert.DeserializeObject(html);
systemConfiguration.GeneralSettings.Application.Exchange = json.exchange;
systemConfiguration.GeneralSettings.Application.TimezoneOffset = json.timeZoneOffset;
systemConfiguration.GeneralSettings.Application.StartBalance = json.startBalance;
systemConfiguration.GeneralSettings.Application.MainFiatCurrency = json.settings.currency;
}
public static List<string> GetPropertyLinesFromAPI(string ptFileName, PTMagicConfiguration systemConfiguration, LogHelper log)
{
List<string> result = null;
try
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(CertificateHelper.AllwaysGoodCertificate);
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(systemConfiguration.GeneralSettings.Application.ProfitTrailerMonitorURL + "settingsapi/settings/load");
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
// PT is using ordinary POST data, not JSON
string query = "fileName=" + ptFileName + "&configName=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "&license=" + systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense;
byte[] formData = Encoding.ASCII.GetBytes(query);
httpWebRequest.ContentLength = formData.Length;
using (Stream stream = httpWebRequest.GetRequestStream())
{
stream.Write(formData, 0, formData.Length);
}
//using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) {
// string json = JsonConvert.SerializeObject(new {
// fileName = ptFileName,
// configName = systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName,
// license = systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense
// });
// streamWriter.Write(json);
//}
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string jsonResult = streamReader.ReadToEnd();
result = JsonConvert.DeserializeObject<List<string>>(jsonResult);
}
}
catch (WebException ex)
{
// Manual error handling as PT doesn't seem to provide a proper error response...
if (ex.Message.IndexOf("401") > -1)
{
log.DoLogError("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': Unauthorized! The specified Profit Trailer license key '" + systemConfiguration.GetProfitTrailerLicenseKeyMasked() + "' is invalid!");
}
else
{
log.DoLogCritical("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
}
}
catch (Exception ex)
{
log.DoLogCritical("Loading " + ptFileName + ".properties failed for setting '" + systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName + "': " + ex.Message, ex);
}
return result;
}
// Save config back to Profit Trailer
public static void SendPropertyLinesToAPI(List<string> pairsLines, List<string> dcaLines, List<string> indicatorsLines, PTMagicConfiguration systemConfiguration, LogHelper log)
{
int retryCount = 0;
@ -148,17 +50,6 @@ namespace Core.ProfitTrailer
}
log.DoLogDebug("Built POST request for Properties");
//using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) {
// string json = JsonConvert.SerializeObject(new {
// fileName = ptFileName,
// configName = systemConfiguration.GeneralSettings.Application.ProfitTrailerDefaultSettingName,
// license = systemConfiguration.GeneralSettings.Application.ProfitTrailerLicense,
// saveData = propertiesString
// });
// streamWriter.Write(json);
//}
log.DoLogInfo("Sending Properties...");
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
log.DoLogInfo("Properties sent!");

View File

@ -2,17 +2,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Security.Permissions;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Core.Main;
using Core.Helper;
using Core.Main.DataObjects.PTMagicData;
using Newtonsoft.Json;
namespace Core.ProfitTrailer
{

View File

@ -21,7 +21,7 @@ namespace Monitor.Pages
private void BindData()
{
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
}
}
}

View File

@ -21,7 +21,7 @@ namespace Monitor.Pages
private void BindData()
{
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
}
}
}

View File

@ -19,7 +19,7 @@ namespace Monitor.Pages
private void BindData()
{
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
}
}
}

View File

@ -30,7 +30,7 @@ namespace Monitor.Pages
private void BindData()
{
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));

View File

@ -24,7 +24,7 @@ namespace Monitor.Pages {
private void BindData() {
DCAMarket = GetStringParameter("m", "");
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
DCALogData = PTData.DCALog.Find(d => d.Market == DCAMarket);

View File

@ -23,7 +23,7 @@ namespace Monitor.Pages {
SortFieldId = GetStringParameter("s", "ProfitPercent");
SortDirection = GetStringParameter("d", "DESC");
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
}
}
}

View File

@ -23,7 +23,7 @@ namespace Monitor.Pages {
SortFieldId = GetStringParameter("s", "ProfitPercent");
SortDirection = GetStringParameter("d", "DESC");
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
}
}
}

View File

@ -28,7 +28,7 @@ namespace Monitor.Pages {
}
private void BindData() {
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
// Cleanup temp files
FileHelper.CleanupFilesMinutes(PTMagicMonitorBasePath + "wwwroot" + System.IO.Path.DirectorySeparatorChar + "assets" + System.IO.Path.DirectorySeparatorChar + "tmp" + System.IO.Path.DirectorySeparatorChar, 5);

View File

@ -53,15 +53,13 @@
buyDisabled = true;
}
buyLogEntry.PercChange = @buyLogEntry.PercChange * 100;
<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>
} 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>
}
<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) {
<td>@Html.Raw(buyStrategyText)</td>
} else {

View File

@ -20,7 +20,7 @@ namespace Monitor.Pages {
}
private void BindData() {
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
// Convert local offset time to UTC
TimeSpan offsetTimeSpan = TimeSpan.Parse(PTMagicConfiguration.GeneralSettings.Application.TimezoneOffset.Replace("+", ""));

View File

@ -29,7 +29,7 @@ namespace Monitor.Pages {
salesDateString = GetStringParameter("d", "");
salesMonthString = GetStringParameter("m", "");
PTData = new ProfitTrailerData(PTMagicConfiguration);
PTData = this.PtDataObject;
if (!salesDateString.Equals("")) {
SalesDate = SystemHelper.TextToDateTime(salesDateString, Constants.confMinDate);

View File

@ -1,7 +1,6 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -10,9 +9,8 @@ using Core.Main;
using Core.Helper;
using Core.Main.DataObjects.PTMagicData;
using Core.MarketAnalyzer;
using Core.ProfitTrailer;
using Microsoft.Extensions.Primitives;
using System.Diagnostics;
using Core.Main.DataObjects;
namespace Monitor._Internal
{
@ -22,7 +20,6 @@ namespace Monitor._Internal
public string PTMagicBasePath = "";
public string PTMagicMonitorBasePath = "";
public PTMagicConfiguration PTMagicConfiguration = null;
public Summary Summary { get; set; } = new Summary();
public LogHelper Log = null;
public string LatestVersion = "";
@ -32,6 +29,25 @@ namespace Monitor._Internal
public string NotifyType = "";
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()
{
@ -58,14 +74,7 @@ namespace Monitor._Internal
PTMagicBasePath += Path.DirectorySeparatorChar;
}
try
{
PTMagicConfiguration = new PTMagicConfiguration(PTMagicBasePath);
}
catch (Exception ex)
{
throw ex;
}
IServiceProvider logProvider = ServiceHelper.BuildLoggerService(PTMagicBasePath);
Log = logProvider.GetRequiredService<LogHelper>();

View File

@ -1,21 +1,10 @@
using System;
using System.IO;
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.Helper;
using Core.Main.DataObjects.PTMagicData;
using Core.MarketAnalyzer;
using Core.ProfitTrailer;
using Microsoft.Extensions.Primitives;
namespace Monitor._Internal
{
public class BasePageModelSecure : BasePageModel
{
public void Init()