diff --git a/Core/DataObjects/PTMagicData.cs b/Core/DataObjects/PTMagicData.cs index d0a0c8c..b847c6c 100644 --- a/Core/DataObjects/PTMagicData.cs +++ b/Core/DataObjects/PTMagicData.cs @@ -464,6 +464,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(); } diff --git a/Core/DataObjects/ProfitTrailerData.cs b/Core/DataObjects/ProfitTrailerData.cs index 631d812..0e86115 100644 --- a/Core/DataObjects/ProfitTrailerData.cs +++ b/Core/DataObjects/ProfitTrailerData.cs @@ -205,11 +205,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() { @@ -304,21 +300,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); @@ -373,6 +361,7 @@ namespace Core.Main.DataObjects 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; diff --git a/Core/ProfitTrailer/StrategyHelper.cs b/Core/ProfitTrailer/StrategyHelper.cs index 2a902be..68e7508 100644 --- a/Core/ProfitTrailer/StrategyHelper.cs +++ b/Core/ProfitTrailer/StrategyHelper.cs @@ -168,12 +168,9 @@ namespace Core.ProfitTrailer boolean = boolean && nextBoolean; else boolean = boolean || nextBoolean; - } - return boolean; } - throw new Exception("Empty expression"); } @@ -227,8 +224,7 @@ 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); @@ -238,13 +234,18 @@ namespace Core.ProfitTrailer { result = "CHANGE"; } - if (result.Contains("LEVERAGE")) + if (result.Contains("CROSSED")) + { + leverage = strategyName.Remove(0, 9); + leverage = leverage.Remove(leverage.Length - 1, 1); + result = "CROSS " + leverage + "X"; + } + if (result.Contains("ISOLATED")) { leverage = strategyName.Remove(0, 10); leverage = leverage.Remove(leverage.Length - 1, 1); - result = leverage + " X"; + 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(":")) @@ -423,10 +424,21 @@ namespace Core.ProfitTrailer case "no dca buy logic": result = String.Concat(strategyLetter, "NODCA"); break; + case "combimagain": + result = String.Concat(strategyLetter, "COMBIG"); + break; + case "combimaspread": + result = String.Concat(strategyLetter, "COMBIS"); + break; + case "combimacross": + result = String.Concat(strategyLetter, "COMBIC"); + 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) @@ -434,7 +446,6 @@ namespace Core.ProfitTrailer result = ""; } } - return result; } @@ -446,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()) @@ -500,6 +508,10 @@ namespace Core.ProfitTrailer case "vwappercentage": case "mvwappercentage": case "btcdominance": + case "combimagain": + case "combimaspread": + case "combimacross": + case "macdpercentage": result = true; break; default: @@ -522,14 +534,11 @@ namespace Core.ProfitTrailer result = true; } } - return result; } - public static int GetStrategyValueDecimals(string strategyName) { int result = 0; - switch (strategyName.ToLower()) { case "lowbb": @@ -568,10 +577,8 @@ namespace Core.ProfitTrailer default: break; } - return result; } - public static string GetStrategyText(Summary summary, List strategies, string strategyText, bool isTrue, bool isTrailingBuyActive) { bool isValidStrategy = false; @@ -582,33 +589,64 @@ namespace Core.ProfitTrailer foreach (Strategy strategy in strategies) { string textClass = (strategy.IsTrue) ? "label-success" : "label-danger"; - isValidStrategy = StrategyHelper.IsValidStrategy(strategy.Name); - 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 = regx.Replace(expression, String.Empty); - var tokens = new Tokenizer(expression).Tokenize(); - var parser = new Parser(tokens); - if (parser.Parse()) + 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 { - strategyText += "(FORM) "; + 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 { @@ -634,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 = ""; @@ -652,10 +687,8 @@ namespace Core.ProfitTrailer } } } - return strategyText; } - public static string GetCurrentValueText(List strategies, string strategyText, double bbValue, double simpleValue, bool includeShortcut) { string result = ""; @@ -716,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) @@ -738,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")); @@ -787,7 +816,6 @@ namespace Core.ProfitTrailer result = simpleValue.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%"; } } - return result; } } diff --git a/Monitor/Pages/_get/DashboardBottom.cshtml b/Monitor/Pages/_get/DashboardBottom.cshtml index 2e0bd56..1051b58 100644 --- a/Monitor/Pages/_get/DashboardBottom.cshtml +++ b/Monitor/Pages/_get/DashboardBottom.cshtml @@ -10,10 +10,9 @@ }
-
+
- @if (!Model.TrendChartDataJSON.Equals("")) {
@@ -23,33 +22,27 @@ }
-
-
+
+
@{ - double currentBalance = Model.PTData.GetCurrentBalance(); - string currentBalanceString = currentBalance.ToString("#,#0.00000000", new System.Globalization.CultureInfo("en-US")); - if (currentBalance > 100) { - currentBalanceString = Math.Round(currentBalance, 2).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")); + 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")); } } -
- - Start balence:   @Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance @Model.Summary.MainMarket -
- Current value:   @currentBalanceString @Model.Summary.MainMarket -
- Gain:   @Math.Round(((currentBalance - Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance) / Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance) * 100, 2) % -
-
+
TCV:   @totalCurrentValueString   @Model.Summary.MainMarket  
+
+ Start:   @Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance @Model.Summary.MainMarket + Gain:   @Math.Round(((Model.totalCurrentValue - Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance) / Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance) * 100, 2) % +
-
@if (!Model.ProfitChartDataJSON.Equals("")) {
@@ -61,16 +54,13 @@
- -
-
-
-
-

Market Trends at @Model.PTMagicConfiguration.GeneralSettings.Application.Exchangemore

- +
+
+

Market Trends at @Model.PTMagicConfiguration.GeneralSettings.Application.Exchange + more

@@ -108,17 +98,17 @@
-
-
-
+
+

Sales Overviewmore

- @{ + @{ double totalProfit = Model.PTData.SellLog.Sum(s => s.Profit); double totalProfitFiat = Math.Round(totalProfit * Model.Summary.MainMarketPrice, 2); double percentGain = Math.Round(totalProfit / Model.PTMagicConfiguration.GeneralSettings.Application.StartBalance * 100, 2); string percentGainText = percentGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%"; - if (Model.PTData.TransactionData.Transactions.Count > 0) { + if (Model.PTData.TransactionData.Transactions.Count > 0) + { percentGainText = ""; } @@ -211,17 +201,15 @@ .x(function(d) { return d.label }) .y(function(d) { return d.value }) .showLabels(true) //Display pie labels - .labelThreshold(.1) //Configure the minimum slice size for labels to show up + .labelThreshold(.1) //Configure the minimum slice size for labels to show up .labelType("percent") //Configure what type of data to show in the label. Can be "key", "value" or "percent" .donut(true) //Turn on Donut mode. Makes pie chart look tasty! .donutRatio(0.3) //Configure how big you want the donut hole size to be. ; - d3.select("#AssetDistribution svg") .datum(@Html.Raw(Model.AssetDistributionData)) .transition().duration(350) .call(chart); - return chart; }); @@ -239,7 +227,6 @@ $.Notification.notify('success', 'top left', '@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName) now active!', 'PTMagic switched Profit Trailer settings to "@Core.Helper.SystemHelper.SplitCamelCase(Model.Summary.CurrentGlobalSetting.SettingName)".'); } - @if (!Model.TrendChartDataJSON.Equals("")) { nv.addGraph(function () { @@ -255,7 +242,6 @@ }); } - @if (!Model.ProfitChartDataJSON.Equals("")) { nv.addGraph(function () { @@ -267,7 +253,6 @@ lineChart.yAxis.axisLabel('Daily Profit').tickFormat(d3.format(',.2f')); d3.select('.profit-chart svg').attr('perserveAspectRatio', 'xMinYMid').datum(chartData).transition().duration(500).call(lineChart); //nv.utils.windowResize(lineChart.update); v1.3.0 => Removed this line to prevent memory leak - return lineChart; }); diff --git a/Monitor/Pages/_get/DashboardBottom.cshtml.cs b/Monitor/Pages/_get/DashboardBottom.cshtml.cs index 56c8386..c291295 100644 --- a/Monitor/Pages/_get/DashboardBottom.cshtml.cs +++ b/Monitor/Pages/_get/DashboardBottom.cshtml.cs @@ -19,6 +19,9 @@ namespace Monitor.Pages { public string AssetDistributionData = ""; public double currentBalance = 0; public string currentBalanceString = ""; + public double TotalBagCost = 0; + public double TotalBagValue = 0; + public double totalCurrentValue = 0; public void OnGet() { // Initialize Config base.Init(); @@ -49,7 +52,6 @@ namespace Monitor.Pages { BuildMarketTrendChartData(); BuildProfitChartData(); } - private void BuildMarketTrendChartData() { if (MarketTrends.Count > 0) { TrendChartDataJSON = "["; @@ -96,13 +98,10 @@ namespace Monitor.Pages { MarketTrendChange mtc = latestTickRange.First(); if (trendChartTicks > 0) TrendChartDataJSON += ",\n"; if (Double.IsInfinity(mtc.TrendChange)) mtc.TrendChange = 0; - TrendChartDataJSON += "{ x: new Date('" + mtc.TrendDateTime.ToString("yyyy-MM-ddTHH:mm:ss").Replace(".", ":") + "'), y: " + mtc.TrendChange.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "}"; } - TrendChartDataJSON += "]"; TrendChartDataJSON += "}"; - mtIndex++; } } @@ -140,13 +139,52 @@ namespace Monitor.Pages { } private void BuildAssetDistributionData() { - double PairsBalance = PTData.GetPairsBalance(); - double DCABalance = PTData.GetDCABalance(); - double PendingBalance = PTData.GetPendingBalance(); - double DustBalance = PTData.GetDustBalance(); - double TotalValue = PTData.GetCurrentBalance(); - double AvailableBalance = (TotalValue - PairsBalance - DCABalance - PendingBalance - DustBalance); - + // the per PT-Eelroy, the PT API doesn't provide these values when using leverage, so they are calculated here to cover either case. + double PairsBalance = 0.0; + double DCABalance = 0.0; + double PendingBalance = 0.0; + double AvailableBalance = PTData.GetCurrentBalance(); + bool isSellStrategyTrue =false; + bool isTrailingSellActive =false; + + foreach (Core.Main.DataObjects.PTMagicData.DCALogData dcaLogEntry in PTData.DCALog) + { + Core.Main.DataObjects.PTMagicData.MarketPairSummary mps = null; + string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive); + + // Aggregate totals + if (dcaLogEntry.Leverage == 0) + { + if (sellStrategyText.Contains("PENDING")) + { + PendingBalance = PendingBalance + (dcaLogEntry.Amount * dcaLogEntry.CurrentPrice); + } + else if (dcaLogEntry.BuyStrategies.Count > 0) + { + DCABalance = DCABalance + (dcaLogEntry.Amount * dcaLogEntry.CurrentPrice); + } + else + { + PairsBalance = PairsBalance + (dcaLogEntry.Amount * dcaLogEntry.CurrentPrice); + } + } + else + { + if (sellStrategyText.Contains("PENDING")) + { + PendingBalance = PendingBalance + ((dcaLogEntry.Amount * dcaLogEntry.CurrentPrice) / dcaLogEntry.Leverage); + } + else if (dcaLogEntry.BuyStrategies.Count > 0) + { + DCABalance = DCABalance + ((dcaLogEntry.Amount * dcaLogEntry.CurrentPrice) / dcaLogEntry.Leverage); + } + else + { + PairsBalance = PairsBalance + ((dcaLogEntry.Amount * dcaLogEntry.CurrentPrice) / dcaLogEntry.Leverage); + } + } + } + totalCurrentValue = PendingBalance + DCABalance + PairsBalance + AvailableBalance; AssetDistributionData = "["; AssetDistributionData += "{label: 'Pairs',color: '#82E0AA',value: '" + PairsBalance.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "'},"; AssetDistributionData += "{label: 'DCA',color: '#D98880',value: '" + DCABalance.ToString("0.00", new System.Globalization.CultureInfo("en-US")) + "'},"; diff --git a/Monitor/Pages/_get/DashboardTop.cshtml b/Monitor/Pages/_get/DashboardTop.cshtml index b417b9a..c93a6e6 100644 --- a/Monitor/Pages/_get/DashboardTop.cshtml +++ b/Monitor/Pages/_get/DashboardTop.cshtml @@ -93,12 +93,12 @@
- + - - - + + + @@ -137,11 +137,30 @@ } bool buyDisabled = false; + string leverage = ""; + double leverageValue = 0; + string buyStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.BuyStrategies, dcaLogEntry.BuyStrategy, isBuyStrategyTrue, isTrailingBuyActive); - if (!Core.ProfitTrailer.StrategyHelper.IsValidStrategy(buyStrategyText, true)) { + + if (!Core.ProfitTrailer.StrategyHelper.IsValidStrategy(buyStrategyText, true)) + { buyDisabled = true; } + // if leverage, recalculate profit target + if (buyStrategyText.Contains("CROSSED")) + { + string leverageText = buyStrategyText.Remove(0, buyStrategyText.IndexOf("CROSSED")+9); + leverage = leverageText.Remove(leverageText.IndexOf(".0)"), leverageText.Length - leverageText.IndexOf(".0)")); + leverageValue = double.Parse(leverage); + } + if (buyStrategyText.Contains("ISOLATED")) + { + string leverageText = buyStrategyText.Remove(0, buyStrategyText.IndexOf("ISOLATED")+10); + leverage = leverageText.Remove(leverageText.IndexOf(".0)"), leverageText.Length - leverageText.IndexOf(".0)")); + leverageValue = double.Parse(leverage); + } + string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive); // Check for when PT loses the value of a pair @@ -197,13 +216,20 @@ } - - - - + + @if (leverageValue == 0) + { + + } + else + { + double leverageTargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value; + + } + @if(!@lostValue) { @@ -224,8 +250,9 @@ - + +
Market24H Trend24H Cost DCA Buy StratsSell StratsTarget ProfitDCASellTarget Profit
@Html.Raw(buyStrategyText)@Html.Raw(sellStrategyText)@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? dcaLogEntry.TargetGainValue.Value.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : " ")@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? dcaLogEntry.TargetGainValue.Value.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : " ")@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? leverageTargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : " ")@dcaLogEntry.ProfitPercent.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))% @Html.Raw((((Model.TotalBagValue - Model.TotalBagCost) / Model.TotalBagCost) * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")))%@Html.Raw( (((Model.TotalBagValue - Model.TotalBagCost) / Model.TotalBagCost) * 100).ToString("#0.00", new System.Globalization.CultureInfo("en-US")))%