diff --git a/Core/DataObjects/PTMagicData.cs b/Core/DataObjects/PTMagicData.cs index 4e3cad5..c05e084 100644 --- a/Core/DataObjects/PTMagicData.cs +++ b/Core/DataObjects/PTMagicData.cs @@ -361,6 +361,19 @@ namespace Core.Main.DataObjects.PTMagicData } #endregion + #region Properties Objects + public class Properties + { + public string Currency { get; set; } = ""; + public bool Shorting { get; set; } = false; + public bool Margin { get; set; } = false; + public string UpTime { get; set; } = ""; + public int Port { get; set; } = 0; + public bool IsLeverageExchange { get; set; } = false; + public string BaseUrl { get; set; } = ""; + } + #endregion + #region Transaction Objects public class Transaction { @@ -456,6 +469,7 @@ namespace Core.Main.DataObjects.PTMagicData public double AverageBuyPrice { get; set; } public double TotalCost { get; set; } public double CurrentValue { get; set; } + public double? TargetGainValue { get; set; } public double Amount { get; set; } public double CurrentPrice { get; set; } public double SellTrigger { get; set; } @@ -463,6 +477,7 @@ namespace Core.Main.DataObjects.PTMagicData public DateTime FirstBoughtDate { get; set; } public string SellStrategy { get; set; } public string BuyStrategy { get; set; } + public double Leverage { get; set; } public List BuyStrategies { get; set; } = new List(); public List SellStrategies { get; set; } = new List(); } @@ -484,6 +499,7 @@ namespace Core.Main.DataObjects.PTMagicData public double CurrentPrice { get; set; } public int BoughtTimes { get; set; } public double PercChange { get; set; } + public double Volume24h { get; set; } public List BuyStrategies { get; set; } = new List(); } @@ -497,5 +513,6 @@ namespace Core.Main.DataObjects.PTMagicData public double DustValue { get; set; } public string Market { get; set; } } + #endregion } diff --git a/Core/DataObjects/ProfitTrailerData.cs b/Core/DataObjects/ProfitTrailerData.cs index 07d146f..1beedc4 100644 --- a/Core/DataObjects/ProfitTrailerData.cs +++ b/Core/DataObjects/ProfitTrailerData.cs @@ -15,14 +15,15 @@ namespace Core.Main.DataObjects public class ProfitTrailerData { private SummaryData _summary = null; + private Properties _properties = null; private List _sellLog = new List(); private List _dcaLog = new List(); private List _buyLog = new List(); private string _ptmBasePath = ""; private PTMagicConfiguration _systemConfiguration = null; private TransactionData _transactionData = null; - 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(); + private DateTime _buyLogRefresh = DateTime.UtcNow, _sellLogRefresh = DateTime.UtcNow, _dcaLogRefresh = DateTime.UtcNow, _summaryRefresh = DateTime.UtcNow, _propertiesRefresh = DateTime.UtcNow; + private volatile object _buyLock = new object(), _sellLock = new object(), _dcaLock = new object(), _summaryLock = new object(), _propertiesLock = new object(); private TimeSpan? _offsetTimeSpan = null; // Constructor @@ -75,6 +76,26 @@ namespace Core.Main.DataObjects return _summary; } } + public Properties Properties + { + get + { + if (_properties == null || (DateTime.UtcNow > _propertiesRefresh)) + { + lock (_propertiesLock) + { + // Thread double locking + if (_properties == null || (DateTime.UtcNow > _propertiesRefresh)) + { + _properties = BuildProptertiesData(GetDataFromProfitTrailer("api/v2/data/properties")); + _propertiesRefresh = DateTime.UtcNow.AddSeconds(_systemConfiguration.GeneralSettings.Monitor.RefreshSeconds - 1); + } + } + } + + return _properties; + } + } public List SellLog { get @@ -205,11 +226,7 @@ namespace Core.Main.DataObjects public double GetCurrentBalance() { return - (this.Summary.Balance + - this.Summary.PairsValue + - this.Summary.DCAValue + - this.Summary.PendingValue + - this.Summary.DustValue); + (this.Summary.Balance); } public double GetPairsBalance() { @@ -290,7 +307,19 @@ namespace Core.Main.DataObjects DustValue = PTData.totalDustCurrentValue }; } - + private Properties BuildProptertiesData(dynamic PTProperties) + { + return new Properties() + { + Currency = PTProperties.currency, + Shorting = PTProperties.shorting, + Margin = PTProperties.margin, + UpTime = PTProperties.upTime, + Port = PTProperties.port, + IsLeverageExchange = PTProperties.isLeverageExchange, + BaseUrl = PTProperties.baseUrl + }; + } private void BuildSellLogData(dynamic rawSellLogData) { foreach (var rsld in rawSellLogData.data) @@ -304,21 +333,13 @@ namespace Core.Main.DataObjects sellLogData.AverageBuyPrice = rsld.avgPrice; sellLogData.TotalCost = sellLogData.SoldAmount * sellLogData.AverageBuyPrice; - // check if sale was a short position - if ((sellLogData.ProfitPercent > 0) && (sellLogData.AverageBuyPrice > sellLogData.SoldPrice)) - { - double soldValueRaw = (sellLogData.SoldAmount * sellLogData.SoldPrice); - double soldValueAfterFees = soldValueRaw + (soldValueRaw * ((double)rsld.fee / 100)); - sellLogData.SoldValue = soldValueAfterFees; - sellLogData.Profit = Math.Abs(Math.Round(sellLogData.SoldValue - sellLogData.TotalCost, 8)); - } - else - { - double soldValueRaw = (sellLogData.SoldAmount * sellLogData.SoldPrice); - double soldValueAfterFees = soldValueRaw - (soldValueRaw * ((double)rsld.fee / 100)); - sellLogData.SoldValue = soldValueAfterFees; - sellLogData.Profit = Math.Round(sellLogData.SoldValue - sellLogData.TotalCost, 8); - } + // check if bot is a shortbot via PT API. Losses on short bot currently showing as gains. Issue #195 + // code removed + + double soldValueRaw = (sellLogData.SoldAmount * sellLogData.SoldPrice); + double soldValueAfterFees = soldValueRaw - (soldValueRaw * ((double)rsld.fee / 100)); + sellLogData.SoldValue = soldValueAfterFees; + sellLogData.Profit = Math.Round(sellLogData.SoldValue - sellLogData.TotalCost, 8); //Convert Unix Timestamp to Datetime System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); @@ -338,69 +359,92 @@ namespace Core.Main.DataObjects private void BuildDCALogData(dynamic rawDCALogData, dynamic rawPairsLogData, dynamic rawPendingLogData, dynamic rawWatchModeLogData) { - foreach (var rdld in rawDCALogData) + // Parse DCA data + _dcaLog.AddRange(ParsePairsData(rawDCALogData, true)); + + // Parse Pairs data + _dcaLog.AddRange(ParsePairsData(rawPairsLogData, false)); + + // Parse pending pairs data + _dcaLog.AddRange(ParsePairsData(rawPendingLogData, false)); + + // Parse watch only pairs data + _dcaLog.AddRange(ParsePairsData(rawWatchModeLogData, false)); + + } + + // Parse the pairs data from PT to our own common data structure. + private List ParsePairsData(dynamic pairsData, bool processBuyStrategies) + { + List pairs = new List(); + + foreach (var pair in pairsData) { DCALogData dcaLogData = new DCALogData(); - dcaLogData.Amount = rdld.totalAmount; - dcaLogData.BoughtTimes = rdld.boughtTimes; - dcaLogData.Market = rdld.market; - dcaLogData.ProfitPercent = rdld.profit; - dcaLogData.AverageBuyPrice = rdld.avgPrice; - dcaLogData.TotalCost = rdld.totalCost; - dcaLogData.BuyTriggerPercent = rdld.buyProfit; - dcaLogData.CurrentLowBBValue = rdld.bbLow == null ? 0 : rdld.bbLow; - dcaLogData.CurrentHighBBValue = rdld.highBb == null ? 0 : rdld.highBb; - dcaLogData.BBTrigger = rdld.bbTrigger == null ? 0 : rdld.bbTrigger; - dcaLogData.CurrentPrice = rdld.currentPrice; - dcaLogData.SellTrigger = rdld.triggerValue == null ? 0 : rdld.triggerValue; - dcaLogData.PercChange = rdld.percChange; - dcaLogData.BuyStrategy = rdld.buyStrategy == null ? "" : rdld.buyStrategy; - dcaLogData.SellStrategy = rdld.sellStrategy == null ? "" : rdld.sellStrategy; + dcaLogData.Amount = pair.totalAmount; + dcaLogData.BoughtTimes = pair.boughtTimes; + dcaLogData.Market = pair.market; + dcaLogData.ProfitPercent = pair.profit; + dcaLogData.AverageBuyPrice = pair.avgPrice; + dcaLogData.TotalCost = pair.totalCost; + dcaLogData.BuyTriggerPercent = pair.buyProfit; + dcaLogData.CurrentLowBBValue = pair.bbLow == null ? 0 : pair.bbLow; + dcaLogData.CurrentHighBBValue = pair.highBb == null ? 0 : pair.highBb; + dcaLogData.BBTrigger = pair.bbTrigger == null ? 0 : pair.bbTrigger; + dcaLogData.CurrentPrice = pair.currentPrice; + dcaLogData.SellTrigger = pair.triggerValue == null ? 0 : pair.triggerValue; + dcaLogData.PercChange = pair.percChange; + dcaLogData.Leverage = pair.leverage == null ? 0 : pair.leverage; + dcaLogData.BuyStrategy = pair.buyStrategy == null ? "" : pair.buyStrategy; + dcaLogData.SellStrategy = pair.sellStrategy == null ? "" : pair.sellStrategy; + dcaLogData.IsTrailing = false; - if (rdld.positive != null) + if (pair.buyStrategies != null && processBuyStrategies) { - dcaLogData.IsTrailing = ((string)rdld.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; - dcaLogData.IsTrue = ((string)rdld.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; - } - else - { - if (rdld.buyStrategies != null) + foreach (var bs in pair.buyStrategies) { - foreach (var bs in rdld.buyStrategies) - { - Strategy buyStrategy = new Strategy(); - buyStrategy.Type = bs.type; - buyStrategy.Name = bs.name; - buyStrategy.EntryValue = bs.entryValue; - buyStrategy.EntryValueLimit = bs.entryValueLimit; - buyStrategy.TriggerValue = bs.triggerValue; - buyStrategy.CurrentValue = bs.currentValue; - buyStrategy.CurrentValuePercentage = bs.currentValuePercentage; - buyStrategy.Decimals = bs.decimals; - buyStrategy.IsTrailing = ((string)bs.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; - buyStrategy.IsTrue = ((string)bs.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; + Strategy buyStrategy = new Strategy(); + buyStrategy.Type = bs.type; + buyStrategy.Name = bs.name; + buyStrategy.EntryValue = bs.entryValue; + buyStrategy.EntryValueLimit = bs.entryValueLimit; + buyStrategy.TriggerValue = bs.triggerValue; + buyStrategy.CurrentValue = bs.currentValue; + buyStrategy.CurrentValuePercentage = bs.currentValuePercentage; + buyStrategy.Decimals = bs.decimals; + buyStrategy.IsTrailing = ((string)bs.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; + buyStrategy.IsTrue = ((string)bs.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; - dcaLogData.BuyStrategies.Add(buyStrategy); - } + dcaLogData.BuyStrategies.Add(buyStrategy); } + } - if (rdld.sellStrategies != null) + if (pair.sellStrategies != null) + { + foreach (var ss in pair.sellStrategies) { - foreach (var ss in rdld.sellStrategies) - { - Strategy sellStrategy = new Strategy(); - sellStrategy.Type = ss.type; - sellStrategy.Name = ss.name; - sellStrategy.EntryValue = ss.entryValue; - sellStrategy.EntryValueLimit = ss.entryValueLimit; - sellStrategy.TriggerValue = ss.triggerValue; - sellStrategy.CurrentValue = ss.currentValue; - sellStrategy.CurrentValuePercentage = ss.currentValuePercentage; - sellStrategy.Decimals = ss.decimals; - sellStrategy.IsTrailing = ((string)ss.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; - sellStrategy.IsTrue = ((string)ss.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; + Strategy sellStrategy = new Strategy(); + sellStrategy.Type = ss.type; + sellStrategy.Name = ss.name; + sellStrategy.EntryValue = ss.entryValue; + sellStrategy.EntryValueLimit = ss.entryValueLimit; + sellStrategy.TriggerValue = ss.triggerValue; + sellStrategy.CurrentValue = ss.currentValue; + sellStrategy.CurrentValuePercentage = ss.currentValuePercentage; + sellStrategy.Decimals = ss.decimals; + sellStrategy.IsTrailing = ((string)ss.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; + sellStrategy.IsTrue = ((string)ss.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; - dcaLogData.SellStrategies.Add(sellStrategy); + dcaLogData.SellStrategies.Add(sellStrategy); + + // Find the target percentage gain to sell. + if (sellStrategy.Name.Contains("GAIN", StringComparison.InvariantCultureIgnoreCase)) + { + if (!dcaLogData.TargetGainValue.HasValue || dcaLogData.TargetGainValue.Value > sellStrategy.EntryValue) + { + // Set the target sell percentage + dcaLogData.TargetGainValue = sellStrategy.EntryValue; + } } } } @@ -408,12 +452,12 @@ namespace Core.Main.DataObjects // Calculate current value dcaLogData.CurrentValue = dcaLogData.CurrentPrice * dcaLogData.Amount; - //Convert Unix Timestamp to Datetime + // Convert Unix Timestamp to Datetime System.DateTime rdldDateTime = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); - rdldDateTime = rdldDateTime.AddSeconds((double)rdld.firstBoughtDate).ToUniversalTime(); + rdldDateTime = rdldDateTime.AddSeconds((double)pair.firstBoughtDate).ToUniversalTime(); // Profit Trailer bought times are saved in UTC - if (rdld.firstBoughtDate > 0) + if (pair.firstBoughtDate > 0) { 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); @@ -430,182 +474,7 @@ namespace Core.Main.DataObjects _dcaLog.Add(dcaLogData); } - foreach (var rpld in rawPairsLogData) - { - DCALogData dcaLogData = new DCALogData(); - dcaLogData.Amount = rpld.totalAmount; - dcaLogData.BoughtTimes = 0; - dcaLogData.Market = rpld.market; - dcaLogData.ProfitPercent = rpld.profit; - dcaLogData.AverageBuyPrice = rpld.avgPrice; - dcaLogData.TotalCost = rpld.totalCost; - dcaLogData.BuyTriggerPercent = rpld.buyProfit; - dcaLogData.CurrentPrice = rpld.currentPrice; - dcaLogData.SellTrigger = rpld.triggerValue == null ? 0 : rpld.triggerValue; - dcaLogData.PercChange = rpld.percChange; - dcaLogData.BuyStrategy = rpld.buyStrategy == null ? "" : rpld.buyStrategy; - dcaLogData.SellStrategy = rpld.sellStrategy == null ? "" : rpld.sellStrategy; - dcaLogData.IsTrailing = false; - - if (rpld.sellStrategies != null) - { - foreach (var ss in rpld.sellStrategies) - { - Strategy sellStrategy = new Strategy(); - sellStrategy.Type = ss.type; - sellStrategy.Name = ss.name; - sellStrategy.EntryValue = ss.entryValue; - sellStrategy.EntryValueLimit = ss.entryValueLimit; - sellStrategy.TriggerValue = ss.triggerValue; - sellStrategy.CurrentValue = ss.currentValue; - sellStrategy.CurrentValuePercentage = ss.currentValuePercentage; - sellStrategy.Decimals = ss.decimals; - sellStrategy.IsTrailing = ((string)ss.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; - sellStrategy.IsTrue = ((string)ss.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; - - dcaLogData.SellStrategies.Add(sellStrategy); - } - } - - //Convert Unix Timestamp to Datetime - System.DateTime rpldDateTime = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); - rpldDateTime = rpldDateTime.AddSeconds((double)rpld.firstBoughtDate).ToUniversalTime(); - - // Profit Trailer bought times are saved in UTC - if (rpld.firstBoughtDate > 0) - { - 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 - ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(OffsetTimeSpan); - - dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime; - } - else - { - dcaLogData.FirstBoughtDate = Constants.confMinDate; - } - - _dcaLog.Add(dcaLogData); - } - - foreach (var rpld in rawPendingLogData) - { - DCALogData dcaLogData = new DCALogData(); - dcaLogData.Amount = rpld.totalAmount; - dcaLogData.BoughtTimes = 0; - dcaLogData.Market = rpld.market; - dcaLogData.ProfitPercent = rpld.profit; - dcaLogData.AverageBuyPrice = rpld.avgPrice; - dcaLogData.TotalCost = rpld.totalCost; - dcaLogData.BuyTriggerPercent = rpld.buyProfit; - dcaLogData.CurrentPrice = rpld.currentPrice; - dcaLogData.SellTrigger = rpld.triggerValue == null ? 0 : rpld.triggerValue; - dcaLogData.PercChange = rpld.percChange; - dcaLogData.BuyStrategy = rpld.buyStrategy == null ? "" : rpld.buyStrategy; - dcaLogData.SellStrategy = rpld.sellStrategy == null ? "" : rpld.sellStrategy; - dcaLogData.IsTrailing = false; - - if (rpld.sellStrategies != null) - { - foreach (var ss in rpld.sellStrategies) - { - Strategy sellStrategy = new Strategy(); - sellStrategy.Type = ss.type; - sellStrategy.Name = ss.name; - sellStrategy.EntryValue = ss.entryValue; - sellStrategy.EntryValueLimit = ss.entryValueLimit; - sellStrategy.TriggerValue = ss.triggerValue; - sellStrategy.CurrentValue = ss.currentValue; - sellStrategy.CurrentValuePercentage = ss.currentValuePercentage; - sellStrategy.Decimals = ss.decimals; - sellStrategy.IsTrailing = ((string)ss.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; - sellStrategy.IsTrue = ((string)ss.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; - - dcaLogData.SellStrategies.Add(sellStrategy); - } - } - - //Convert Unix Timestamp to Datetime - System.DateTime rpldDateTime = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); - rpldDateTime = rpldDateTime.AddSeconds((double)rpld.firstBoughtDate).ToUniversalTime(); - - // Profit Trailer bought times are saved in UTC - if (rpld.firstBoughtDate > 0) - { - 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 - ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(OffsetTimeSpan); - - dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime; - } - else - { - dcaLogData.FirstBoughtDate = Constants.confMinDate; - } - - _dcaLog.Add(dcaLogData); - } - - foreach (var rpld in rawWatchModeLogData) - { - DCALogData dcaLogData = new DCALogData(); - dcaLogData.Amount = rpld.totalAmount; - dcaLogData.BoughtTimes = 0; - dcaLogData.Market = rpld.market; - dcaLogData.ProfitPercent = rpld.profit; - dcaLogData.AverageBuyPrice = rpld.avgPrice; - dcaLogData.TotalCost = rpld.totalCost; - dcaLogData.BuyTriggerPercent = rpld.buyProfit; - dcaLogData.CurrentPrice = rpld.currentPrice; - dcaLogData.SellTrigger = rpld.triggerValue == null ? 0 : rpld.triggerValue; - dcaLogData.PercChange = rpld.percChange; - dcaLogData.BuyStrategy = rpld.buyStrategy == null ? "" : rpld.buyStrategy; - dcaLogData.SellStrategy = rpld.sellStrategy == null ? "" : rpld.sellStrategy; - dcaLogData.IsTrailing = false; - - if (rpld.sellStrategies != null) - { - foreach (var ss in rpld.sellStrategies) - { - Strategy sellStrategy = new Strategy(); - sellStrategy.Type = ss.type; - sellStrategy.Name = ss.name; - sellStrategy.EntryValue = ss.entryValue; - sellStrategy.EntryValueLimit = ss.entryValueLimit; - sellStrategy.TriggerValue = ss.triggerValue; - sellStrategy.CurrentValue = ss.currentValue; - sellStrategy.CurrentValuePercentage = ss.currentValuePercentage; - sellStrategy.Decimals = ss.decimals; - sellStrategy.IsTrailing = ((string)ss.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; - sellStrategy.IsTrue = ((string)ss.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; - - dcaLogData.SellStrategies.Add(sellStrategy); - } - } - - //Convert Unix Timestamp to Datetime - System.DateTime rpldDateTime = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); - rpldDateTime = rpldDateTime.AddSeconds((double)rpld.firstBoughtDate).ToUniversalTime(); - - // Profit Trailer bought times are saved in UTC - if (rpld.firstBoughtDate > 0) - { - 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 - ptFirstBoughtDate = ptFirstBoughtDate.ToOffset(OffsetTimeSpan); - - dcaLogData.FirstBoughtDate = ptFirstBoughtDate.DateTime; - } - else - { - dcaLogData.FirstBoughtDate = Constants.confMinDate; - } - - _dcaLog.Add(dcaLogData); - } + return pairs; } private void BuildBuyLogData(dynamic rawBuyLogData) @@ -617,6 +486,7 @@ namespace Core.Main.DataObjects buyLogData.ProfitPercent = rbld.profit; buyLogData.CurrentPrice = rbld.currentPrice; buyLogData.PercChange = rbld.percChange; + buyLogData.Volume24h = rbld.volume; if (rbld.positive != null) { diff --git a/Core/Helper/SystemHelper.cs b/Core/Helper/SystemHelper.cs index 398b403..73cd7d6 100644 --- a/Core/Helper/SystemHelper.cs +++ b/Core/Helper/SystemHelper.cs @@ -547,6 +547,19 @@ namespace Core.Helper result += pairName; } + else if (platform.Equals("TradingViewFutures")) + { + result = "https://www.tradingview.com/chart/?symbol="; + + string pairName = SystemHelper.StripBadCode(market, Constants.WhiteListMinimal); + + if (pairName.StartsWith(mainMarket)) + { + pairName = pairName.Replace(mainMarket, "") + mainMarket; + } + + result += pairName + "PERP"; + } else { switch (exchange) diff --git a/Core/Main/PTMagic.cs b/Core/Main/PTMagic.cs index 305b49c..7bdf293 100644 --- a/Core/Main/PTMagic.cs +++ b/Core/Main/PTMagic.cs @@ -2564,7 +2564,7 @@ namespace Core.Main } } - this.LastRuntimeSummary.MarketSummary.Add(marketPair, mpSummary); + this.LastRuntimeSummary.MarketSummary.TryAdd(marketPair, mpSummary); } this.Log.DoLogInfo("Summary: Current single market properties saved."); diff --git a/Core/MarketAnalyzer/BinanceUS.cs b/Core/MarketAnalyzer/BinanceUS.cs index 070fe77..63b1318 100644 --- a/Core/MarketAnalyzer/BinanceUS.cs +++ b/Core/MarketAnalyzer/BinanceUS.cs @@ -20,27 +20,32 @@ namespace Core.MarketAnalyzer public static double GetMainCurrencyPrice(string mainMarket, PTMagicConfiguration systemConfiguration, LogHelper log) { double result = 0; - - try + if (mainMarket != "USD") { - string baseUrl = "https://api.binance.us/api/v1/ticker/24hr?symbol=" + mainMarket + "USDT"; - - log.DoLogInfo("BinanceUS - Getting main market price..."); - Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, null); - if (jsonObject != null) + try { - log.DoLogInfo("BinanceUS - Market data received for " + mainMarket + "USDT"); + string baseUrl = "https://api.binance.us/api/v1/ticker/24hr?symbol=" + mainMarket + "USDT"; - result = (double)jsonObject.GetValue("lastPrice"); - log.DoLogInfo("BinanceUS - Current price for " + mainMarket + "USDT: " + result.ToString("#,#0.00") + " USD"); + log.DoLogInfo("BinanceUS - Getting main market price..."); + Newtonsoft.Json.Linq.JObject jsonObject = GetSimpleJsonObjectFromURL(baseUrl, log, null); + if (jsonObject != null) + { + log.DoLogInfo("BinanceUS - Market data received for " + mainMarket + "USDT"); + + result = (double)jsonObject.GetValue("lastPrice"); + log.DoLogInfo("BinanceUS - Current price for " + mainMarket + "USDT: " + result.ToString("#,#0.00") + " USD"); + } } - } - catch (Exception ex) + catch (Exception ex) + { + log.DoLogCritical(ex.Message, ex); + } + return result; + } + else { - log.DoLogCritical(ex.Message, ex); + return 1.0; } - - return result; } public static List GetMarketData(string mainMarket, Dictionary marketInfos, PTMagicConfiguration systemConfiguration, LogHelper log) @@ -58,7 +63,7 @@ namespace Core.MarketAnalyzer if (jsonArray.Count > 0) { double mainCurrencyPrice = 1; - if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase)) + if (!mainMarket.Equals("USDT", StringComparison.InvariantCultureIgnoreCase) && !mainMarket.Equals("USD", StringComparison.InvariantCultureIgnoreCase)) { mainCurrencyPrice = BinanceUS.GetMainCurrencyPrice(mainMarket, systemConfiguration, log); } @@ -238,40 +243,45 @@ namespace Core.MarketAnalyzer } bool go = true; - while (ticksFetched < ticksNeeded && go) + if (!(marketName == "USDUSDT")) { - baseUrl = "https://api.binance.us/api/v1/klines?interval=1m&symbol=" + marketName + "&endTime=" + endTime.ToString() + "&limit=" + ticksLimit.ToString(); - - log.DoLogDebug("BinanceUS - Getting " + ticksLimit.ToString() + " ticks for '" + marketName + "'..."); - Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log); - if (jsonArray.Count > 0) + while (ticksFetched < ticksNeeded && go) { - log.DoLogDebug("BinanceUS - " + jsonArray.Count.ToString() + " ticks received."); + + baseUrl = "https://api.binance.us/api/v1/klines?interval=1m&symbol=" + marketName + "&endTime=" + endTime.ToString() + "&limit=" + ticksLimit.ToString(); - foreach (Newtonsoft.Json.Linq.JArray marketTick in jsonArray) + log.DoLogDebug("BinanceUS - Getting " + ticksLimit.ToString() + " ticks for '" + marketName + "'..."); + Newtonsoft.Json.Linq.JArray jsonArray = GetSimpleJsonArrayFromURL(baseUrl, log); + if (jsonArray.Count > 0) { + log.DoLogDebug("BinanceUS - " + jsonArray.Count.ToString() + " ticks received."); - MarketTick tick = new MarketTick(); - tick.Price = (double)marketTick[4]; - tick.Volume24h = (double)marketTick[7]; - tick.Time = Constants.Epoch.AddMilliseconds((Int64)marketTick[0]); + foreach (Newtonsoft.Json.Linq.JArray marketTick in jsonArray) + { - result.Add(tick); + MarketTick tick = new MarketTick(); + tick.Price = (double)marketTick[4]; + tick.Volume24h = (double)marketTick[7]; + tick.Time = Constants.Epoch.AddMilliseconds((Int64)marketTick[0]); + + result.Add(tick); + } + + ticksFetched = ticksFetched + jsonArray.Count; + endTime = endTime - ticksLimit * 60 * 1000; + if (ticksNeeded - ticksFetched < ticksLimit) + { + ticksLimit = ticksNeeded - ticksFetched; + } } - - ticksFetched = ticksFetched + jsonArray.Count; - endTime = endTime - ticksLimit * 60 * 1000; - if (ticksNeeded - ticksFetched < ticksLimit) + else { - ticksLimit = ticksNeeded - ticksFetched; + log.DoLogDebug("BinanceUS - No ticks received."); + go = false; } } - else - { - log.DoLogDebug("BinanceUS - No ticks received."); - go = false; - } } + } catch (WebException ex) { diff --git a/Core/ProfitTrailer/StrategyHelper.cs b/Core/ProfitTrailer/StrategyHelper.cs index 0b205ba..4b7a363 100644 --- a/Core/ProfitTrailer/StrategyHelper.cs +++ b/Core/ProfitTrailer/StrategyHelper.cs @@ -1,222 +1,212 @@ 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; using System.Text.RegularExpressions; namespace Core.ProfitTrailer { public class OperandToken : Token + { + } + public class OrToken : OperandToken + { + } + + public class AndToken : OperandToken + { + } + + public class BooleanValueToken : Token + { + } + + public class FalseToken : BooleanValueToken + { + } + + public class TrueToken : BooleanValueToken + { + } + + public class ParenthesisToken : Token + { + } + + public class ClosedParenthesisToken : ParenthesisToken + { + } + + public class OpenParenthesisToken : ParenthesisToken + { + } + + public class NegationToken : Token + { + } + + public abstract class Token + { + } + + public class Tokenizer + { + private readonly StringReader _reader; + private string _text; + + public Tokenizer(string text) { - } - public class OrToken : OperandToken - { + _text = text; + _reader = new StringReader(text); } - public class AndToken : OperandToken + public IEnumerable Tokenize() { - } - - public class BooleanValueToken : Token - { - } - - public class FalseToken : BooleanValueToken - { - } - - public class TrueToken : BooleanValueToken - { - } - - public class ParenthesisToken : Token - { - } - - public class ClosedParenthesisToken : ParenthesisToken - { - } - - public class OpenParenthesisToken : ParenthesisToken - { - } - - public class NegationToken : Token - { - } - - public abstract class Token - { - } - - public class Tokenizer - { - private readonly StringReader _reader; - private string _text; - - public Tokenizer(string text) + var tokens = new List(); + while (_reader.Peek() != -1) + { + while (Char.IsWhiteSpace((char)_reader.Peek())) { - _text = text; - _reader = new StringReader(text); + _reader.Read(); } - public IEnumerable Tokenize() + if (_reader.Peek() == -1) + break; + + var c = (char)_reader.Peek(); + switch (c) { - var tokens = new List(); - while (_reader.Peek() != -1) + case '!': + tokens.Add(new NegationToken()); + _reader.Read(); + break; + case '(': + tokens.Add(new OpenParenthesisToken()); + _reader.Read(); + break; + case ')': + tokens.Add(new ClosedParenthesisToken()); + _reader.Read(); + break; + default: + if (Char.IsLetter(c)) { - while (Char.IsWhiteSpace((char) _reader.Peek())) - { - _reader.Read(); - } - - if (_reader.Peek() == -1) - break; - - var c = (char) _reader.Peek(); - switch (c) - { - case '!': - tokens.Add(new NegationToken()); - _reader.Read(); - break; - case '(': - tokens.Add(new OpenParenthesisToken()); - _reader.Read(); - break; - case ')': - tokens.Add(new ClosedParenthesisToken()); - _reader.Read(); - break; - default: - if (Char.IsLetter(c)) - { - var token = ParseKeyword(); - tokens.Add(token); - } - else - { - var remainingText = _reader.ReadToEnd() ?? string.Empty; - throw new Exception(string.Format("Unknown grammar found at position {0} : '{1}'", _text.Length - remainingText.Length, remainingText)); - } - break; - } - } - return tokens; - } - - private Token ParseKeyword() - { - var text = new StringBuilder(); - while (Char.IsLetter((char) _reader.Peek())) - { - text.Append((char) _reader.Read()); - } - - var potentialKeyword = text.ToString().ToLower(); - - switch (potentialKeyword) - { - case "true": - return new TrueToken(); - case "false": - return new FalseToken(); - case "and": - return new AndToken(); - case "or": - return new OrToken(); - default: - throw new Exception("Expected keyword (True, False, and, or) but found "+ potentialKeyword); + var token = ParseKeyword(); + tokens.Add(token); } + else + { + var remainingText = _reader.ReadToEnd() ?? string.Empty; + throw new Exception(string.Format("Unknown grammar found at position {0} : '{1}'", _text.Length - remainingText.Length, remainingText)); + } + break; } + } + return tokens; } - public class Parser + + private Token ParseKeyword() { - private readonly IEnumerator _tokens; + var text = new StringBuilder(); + while (Char.IsLetter((char)_reader.Peek())) + { + text.Append((char)_reader.Read()); + } - public Parser(IEnumerable tokens) - { - _tokens = tokens.GetEnumerator(); - _tokens.MoveNext(); - } + var potentialKeyword = text.ToString().ToLower(); - public bool Parse() - { - while (_tokens.Current != null) - { - var isNegated = _tokens.Current is NegationToken; - if (isNegated) - _tokens.MoveNext(); - - var boolean = ParseBoolean(); - if (isNegated) - boolean = !boolean; - - while (_tokens.Current is OperandToken) - { - var operand = _tokens.Current; - if (!_tokens.MoveNext()) - { - throw new Exception("Missing expression after operand"); - } - var nextBoolean = ParseBoolean(); - - if (operand is AndToken) - boolean = boolean && nextBoolean; - else - boolean = boolean || nextBoolean; - - } - - return boolean; - } - - throw new Exception("Empty expression"); - } - - private bool ParseBoolean() - { - if (_tokens.Current is BooleanValueToken) - { - var current = _tokens.Current; - _tokens.MoveNext(); - - if (current is TrueToken) - return true; - - return false; - } - if (_tokens.Current is OpenParenthesisToken) - { - _tokens.MoveNext(); - - var expInPars = Parse(); - - if (!(_tokens.Current is ClosedParenthesisToken)) - throw new Exception("Expecting Closing Parenthesis"); - - _tokens.MoveNext(); - - return expInPars; - } - if (_tokens.Current is ClosedParenthesisToken) - throw new Exception("Unexpected Closed Parenthesis"); - - // since its not a BooleanConstant or Expression in parenthesis, it must be a expression again - var val = Parse(); - return val; - } + switch (potentialKeyword) + { + case "true": + return new TrueToken(); + case "false": + return new FalseToken(); + case "and": + return new AndToken(); + case "or": + return new OrToken(); + default: + throw new Exception("Expected keyword (True, False, and, or) but found " + potentialKeyword); + } } + } + public class Parser + { + private readonly IEnumerator _tokens; + + public Parser(IEnumerable tokens) + { + _tokens = tokens.GetEnumerator(); + _tokens.MoveNext(); + } + + public bool Parse() + { + while (_tokens.Current != null) + { + var isNegated = _tokens.Current is NegationToken; + if (isNegated) + _tokens.MoveNext(); + + var boolean = ParseBoolean(); + if (isNegated) + boolean = !boolean; + + while (_tokens.Current is OperandToken) + { + var operand = _tokens.Current; + if (!_tokens.MoveNext()) + { + throw new Exception("Missing expression after operand"); + } + var nextBoolean = ParseBoolean(); + + if (operand is AndToken) + boolean = boolean && nextBoolean; + else + boolean = boolean || nextBoolean; + } + return boolean; + } + throw new Exception("Empty expression"); + } + + private bool ParseBoolean() + { + if (_tokens.Current is BooleanValueToken) + { + var current = _tokens.Current; + _tokens.MoveNext(); + + if (current is TrueToken) + return true; + + return false; + } + if (_tokens.Current is OpenParenthesisToken) + { + _tokens.MoveNext(); + + var expInPars = Parse(); + + if (!(_tokens.Current is ClosedParenthesisToken)) + throw new Exception("Expecting Closing Parenthesis"); + + _tokens.MoveNext(); + + return expInPars; + } + if (_tokens.Current is ClosedParenthesisToken) + throw new Exception("Unexpected Closed Parenthesis"); + + // since its not a BooleanConstant or Expression in parenthesis, it must be a expression again + var val = Parse(); + return val; + } + } public static class StrategyHelper { @@ -234,29 +224,33 @@ namespace Core.ProfitTrailer { result = ""; } - - // strategy labels that are variable, so can't be caught by the switch statement + // strategy labels that are variable value if (result.Contains("REBUY")) { - time = strategyName.Remove(0,14); + time = strategyName.Remove(0, 14); result = "REBUY " + time; } if (result.Contains("CHANGE PERC")) { result = "CHANGE"; } - if (result.Contains("LEVERAGE")) + if (result.Contains("CROSSED")) { - leverage = strategyName.Remove(0,10); - leverage = leverage.Remove(leverage.Length -1, 1); - result = leverage + " X"; + leverage = strategyName.Remove(0, 9); + leverage = leverage.Remove(leverage.Length - 1, 1); + result = "CROSS " + leverage + "X"; } - - // buy/sell strategies beginning with PT 2.3.3 contain the stragegy designation letter followed by a colon and space. + if (result.Contains("ISOLATED")) + { + leverage = strategyName.Remove(0, 10); + leverage = leverage.Remove(leverage.Length - 1, 1); + result = "ISOL " + leverage + "X"; + } + // buy/sell strategies beginning with PT 2.3.3 contain the strategy designation letter followed by a colon and space. // remove the letter and colon, change to shortcut, then reapply the letter and colon if (strategyName.Contains(":")) { - int strategyLength = strategyName.Length-3; + int strategyLength = strategyName.Length - 3; strategyLetter = strategyName.Remove(3, strategyLength); strategyNameOnly = strategyName.Remove(0, 3); } @@ -275,40 +269,40 @@ namespace Core.ProfitTrailer result = String.Concat(strategyLetter, "LOSS"); break; case "smagain": - result = String.Concat(strategyLetter, "SMAG"); + result = String.Concat(strategyLetter, "SMA-G"); break; case "emagain": - result = String.Concat(strategyLetter, "EMAG"); + result = String.Concat(strategyLetter, "EMA-G"); break; case "hmagain": - result = String.Concat(strategyLetter, "HMAG"); + result = String.Concat(strategyLetter, "HMA-G"); break; case "dmagain": - result = String.Concat(strategyLetter, "DMAG"); + result = String.Concat(strategyLetter, "DMA-G"); break; case "smaspread": - result = String.Concat(strategyLetter, "SMAS"); + result = String.Concat(strategyLetter, "SMA-S"); break; case "emaspread": - result = String.Concat(strategyLetter, "EMAS"); + result = String.Concat(strategyLetter, "EMA-S"); break; case "hmaspread": - result = String.Concat(strategyLetter, "HMAS"); + result = String.Concat(strategyLetter, "HMA-S"); break; case "dmaspread": - result = String.Concat(strategyLetter, "DMAS"); + result = String.Concat(strategyLetter, "DMA-S"); break; case "smacross": - result = String.Concat(strategyLetter, "SMAC"); + result = String.Concat(strategyLetter, "SMA-C"); break; case "emacross": - result = String.Concat(strategyLetter, "EMAC"); + result = String.Concat(strategyLetter, "EMA-C"); break; case "hmacross": - result = String.Concat(strategyLetter, "HMAC"); + result = String.Concat(strategyLetter, "HMA-C"); break; case "dmacross": - result = String.Concat(strategyLetter, "DMAC"); + result = String.Concat(strategyLetter, "DMA-C"); break; case "rsi": result = String.Concat(strategyLetter, "RSI"); @@ -320,13 +314,13 @@ namespace Core.ProfitTrailer result = String.Concat(strategyLetter, "SRSI"); break; case "stochrsik": - result = String.Concat(strategyLetter, "SRSIK"); + result = String.Concat(strategyLetter, "SRSI-K"); break; case "stochrsid": - result = String.Concat(strategyLetter, "SRSID"); + result = String.Concat(strategyLetter, "SRSI-D"); break; case "stochrsicross": - result = String.Concat(strategyLetter, "SRSIC"); + result = String.Concat(strategyLetter, "SRSI-C"); break; case "macd": result = String.Concat(strategyLetter, "MACD"); @@ -365,19 +359,19 @@ namespace Core.ProfitTrailer result = String.Concat(strategyLetter, "FIXED"); break; case "lowatrband": - result = String.Concat(strategyLetter, "LATR"); + result = String.Concat(strategyLetter, "L-ATR"); break; case "highatrband": - result = String.Concat(strategyLetter, "HATR"); + result = String.Concat(strategyLetter, "H-ATR"); break; case "atrpercentage": - result = String.Concat(strategyLetter, "ATRPCT"); + result = String.Concat(strategyLetter, "ATR-PCT"); break; case "vwappercentage": result = String.Concat(strategyLetter, "VWAP"); break; case "mvwappercentage": - result = String.Concat(strategyLetter, "MVWAP"); + result = String.Concat(strategyLetter, "M-VWAP"); break; case "btcdominance": result = String.Concat(strategyLetter, "BTCDOM"); @@ -430,10 +424,21 @@ namespace Core.ProfitTrailer case "no dca buy logic": result = String.Concat(strategyLetter, "NODCA"); break; + case "combimagain": + result = String.Concat(strategyLetter, "COMBI-G"); + break; + case "combimaspread": + result = String.Concat(strategyLetter, "COMBI-S"); + break; + case "combimacross": + result = String.Concat(strategyLetter, "COMBI-C"); + break; + case "macdpercentage": + result = String.Concat(strategyLetter, "MACDPERC"); + break; default: break; } - if (onlyValidStrategies) { if (strategyName.IndexOf("SOM") > -1 || strategyName.IndexOf("MAX") > -1 || strategyName.IndexOf("MIN") > -1 || strategyName.IndexOf("PRICE") > -1 || strategyName.IndexOf("BLACK") > -1 || strategyName.IndexOf("INSUFFICIENT") > -1 || strategyName.IndexOf("COST") > -1) @@ -441,7 +446,6 @@ namespace Core.ProfitTrailer result = ""; } } - return result; } @@ -453,14 +457,11 @@ namespace Core.ProfitTrailer public static bool IsValidStrategy(string strategyName, bool checkForAnyInvalid) { bool result = false; - // buy/sell strategies beginning with PT 2.3.3 contain the letter followed by a colon and space. if (strategyName.Contains(":")) { result = true; } - - // Prior to PT 2.3.3 if (!checkForAnyInvalid) { switch (strategyName.ToLower()) @@ -507,6 +508,10 @@ namespace Core.ProfitTrailer case "vwappercentage": case "mvwappercentage": case "btcdominance": + case "combimagain": + case "combimaspread": + case "combimacross": + case "macdpercentage": result = true; break; default: @@ -529,14 +534,11 @@ namespace Core.ProfitTrailer result = true; } } - return result; } - public static int GetStrategyValueDecimals(string strategyName) { int result = 0; - switch (strategyName.ToLower()) { case "lowbb": @@ -575,45 +577,76 @@ namespace Core.ProfitTrailer default: break; } - return result; } - public static string GetStrategyText(Summary summary, List strategies, string strategyText, bool isTrue, bool isTrailingBuyActive) - { + { bool isValidStrategy = false; + Regex regx = new Regex(@"[ABCDEFGHIJKLMNOPQRSTUVWXYZ]", RegexOptions.Compiled); if (strategies.Count > 0) { foreach (Strategy strategy in strategies) { string textClass = (strategy.IsTrue) ? "label-success" : "label-danger"; - isValidStrategy = StrategyHelper.IsValidStrategy(strategy.Name); - - if (!isValidStrategy ) + if (!isValidStrategy) { - // Parse Formulas - if (strategy.Name.Contains("FORMULA") && !strategy.Name.Contains("STATS")) + + if (strategy.Name.Contains("TRIGGERED")) + // remove levels already triggered, to show only currently waiting trigger { - string expression = strategy.Name.Remove(0, 10); - expression = expression.Replace("","true").Replace("","false").Replace("","").Replace("&&","and").Replace("||","or"); - expression = Regex.Replace(expression, @"[ABCDEFGHIJKLMNOPQRSTUVWXYZ]", String.Empty); - var tokens = new Tokenizer(expression).Tokenize(); - var parser = new Parser(tokens); - if (parser.Parse()) { - strategyText += "(FORM) "; + strategyText += ""; + } + else if (strategy.Name.Contains("STATS")) + // avoid parsing advanced buy stats + { + strategy.Name = ""; + } + else if (strategy.Name.Contains("FORMULA")) + // Parse Various PT Formulas + { + if (strategy.Name.Contains("LEVEL")) + // level X + { + string level = strategy.Name.Substring(5, 2); + string expression = strategy.Name.Remove(0, 17); + expression = expression.Replace("", "true").Replace("", "false").Replace("", "").Replace("&&", "and").Replace("||", "or"); + expression = regx.Replace(expression, String.Empty); + var tokens = new Tokenizer(expression).Tokenize(); + var parser = new Parser(tokens); + if (parser.Parse()) + { + strategyText += "L " + level + " "; + } + else + { + strategyText += "L " + level + " "; + } } else + // standard formula { - strategyText += "(FORM) "; + string expression = strategy.Name.Remove(0, 10); + expression = expression.Replace("", "true").Replace("", "false").Replace("", "").Replace("&&", "and").Replace("||", "or"); + expression = regx.Replace(expression, String.Empty); + var tokens = new Tokenizer(expression).Tokenize(); + var parser = new Parser(tokens); + if (parser.Parse()) + { + strategyText += "FORM "; + } + else + { + strategyText += "FORM "; + } } - } else { strategyText += "" + StrategyHelper.GetStrategyShortcut(strategy.Name, false) + " "; } + } else { @@ -639,14 +672,11 @@ namespace Core.ProfitTrailer } else { - isValidStrategy = StrategyHelper.IsValidStrategy(strategyText); - if (isValidStrategy) { strategyText = "" + StrategyHelper.GetStrategyShortcut(strategyText, true) + ""; } - else if (strategyText.Equals("") && isValidStrategy == false) { strategyText = ""; @@ -657,10 +687,8 @@ namespace Core.ProfitTrailer } } } - return strategyText; } - public static string GetCurrentValueText(List strategies, string strategyText, double bbValue, double simpleValue, bool includeShortcut) { string result = ""; @@ -721,14 +749,12 @@ namespace Core.ProfitTrailer result = simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%"; } } - return result; } public static string GetTriggerValueText(Summary summary, List strategies, string strategyText, double bbValue, double simpleValue, int buyLevel, bool includeShortcut) { string result = ""; - if (strategies.Count > 0) { foreach (Strategy strategy in strategies) @@ -743,12 +769,10 @@ namespace Core.ProfitTrailer { decimalFormat += "0"; } - if (includeShortcut) { result += "" + StrategyHelper.GetStrategyShortcut(strategy.Name, true) + " "; } - if (StrategyHelper.GetStrategyShortcut(strategy.Name, true).IndexOf("and", StringComparison.InvariantCultureIgnoreCase) > -1) { result += strategy.TriggerValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")); @@ -792,7 +816,6 @@ namespace Core.ProfitTrailer result = simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%"; } } - return result; } } diff --git a/Monitor/Monitor.csproj b/Monitor/Monitor.csproj index 6213b2b..ce2658c 100644 --- a/Monitor/Monitor.csproj +++ b/Monitor/Monitor.csproj @@ -10,16 +10,12 @@ - - - - - - - - Always - - + + + + + + diff --git a/Monitor/Pages/PresetFiles.cshtml b/Monitor/Pages/PresetFiles.cshtml index 37e7f02..949120c 100644 --- a/Monitor/Pages/PresetFiles.cshtml +++ b/Monitor/Pages/PresetFiles.cshtml @@ -8,8 +8,20 @@