Merge pull request #248 from djbadders/develop

Small enhancements including order book percentage, trend thresholds for SMS and fix for issues with PT 2.5 beta UI
This commit is contained in:
HojouFotytu 2021-02-09 09:24:23 +09:00 committed by GitHub
commit 24a1c97cdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 232 additions and 151 deletions

View File

@ -335,7 +335,7 @@ namespace Core.Main.DataObjects
// check if bot is a shortbot via PT API. Losses on short bot currently showing as gains. Issue #195 // check if bot is a shortbot via PT API. Losses on short bot currently showing as gains. Issue #195
// code removed // code removed
double soldValueRaw = (sellLogData.SoldAmount * sellLogData.SoldPrice); double soldValueRaw = (sellLogData.SoldAmount * sellLogData.SoldPrice);
double soldValueAfterFees = soldValueRaw - (soldValueRaw * ((double)rsld.fee / 100)); double soldValueAfterFees = soldValueRaw - (soldValueRaw * ((double)rsld.fee / 100));
sellLogData.SoldValue = soldValueAfterFees; sellLogData.SoldValue = soldValueAfterFees;
@ -399,9 +399,11 @@ namespace Core.Main.DataObjects
dcaLogData.SellStrategy = pair.sellStrategy == null ? "" : pair.sellStrategy; dcaLogData.SellStrategy = pair.sellStrategy == null ? "" : pair.sellStrategy;
dcaLogData.IsTrailing = false; dcaLogData.IsTrailing = false;
if (pair.buyStrategies != null && processBuyStrategies) // See if they are using PT 2.5 (buyStrategiesData) or 2.4 (buyStrategies)
var buyStrats = pair.buyStrategies != null ? pair.buyStrategies : pair.buyStrategiesData.data;
if (buyStrats != null && processBuyStrategies)
{ {
foreach (var bs in pair.buyStrategies) foreach (var bs in buyStrats)
{ {
Strategy buyStrategy = new Strategy(); Strategy buyStrategy = new Strategy();
buyStrategy.Type = bs.type; buyStrategy.Type = bs.type;
@ -412,16 +414,18 @@ namespace Core.Main.DataObjects
buyStrategy.CurrentValue = bs.currentValue; buyStrategy.CurrentValue = bs.currentValue;
buyStrategy.CurrentValuePercentage = bs.currentValuePercentage; buyStrategy.CurrentValuePercentage = bs.currentValuePercentage;
buyStrategy.Decimals = bs.decimals; buyStrategy.Decimals = bs.decimals;
buyStrategy.IsTrailing = ((string)bs.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; buyStrategy.IsTrailing = bs.trailing;
buyStrategy.IsTrue = ((string)bs.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; buyStrategy.IsTrue = bs.strategyResult;
dcaLogData.BuyStrategies.Add(buyStrategy); dcaLogData.BuyStrategies.Add(buyStrategy);
} }
} }
if (pair.sellStrategies != null) // See if they are using PT 2.5 (sellStrategiesData) or 2.4 (sellStrategies)
var sellStrats = pair.sellStrategies != null ? pair.sellStrategies : pair.sellStrategiesData.data;
if (sellStrats != null)
{ {
foreach (var ss in pair.sellStrategies) foreach (var ss in sellStrats)
{ {
Strategy sellStrategy = new Strategy(); Strategy sellStrategy = new Strategy();
sellStrategy.Type = ss.type; sellStrategy.Type = ss.type;
@ -432,8 +436,8 @@ namespace Core.Main.DataObjects
sellStrategy.CurrentValue = ss.currentValue; sellStrategy.CurrentValue = ss.currentValue;
sellStrategy.CurrentValuePercentage = ss.currentValuePercentage; sellStrategy.CurrentValuePercentage = ss.currentValuePercentage;
sellStrategy.Decimals = ss.decimals; sellStrategy.Decimals = ss.decimals;
sellStrategy.IsTrailing = ((string)ss.positive).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; sellStrategy.IsTrailing = ss.trailing;
sellStrategy.IsTrue = ((string)ss.positive).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; sellStrategy.IsTrue = ss.strategyResult;
dcaLogData.SellStrategies.Add(sellStrategy); dcaLogData.SellStrategies.Add(sellStrategy);
@ -495,9 +499,14 @@ namespace Core.Main.DataObjects
} }
else else
{ {
if (rbld.buyStrategies != null) // Parse buy strategies
// See if they are using PT 2.5 (buyStrategiesData) or 2.4 (buyStrategies)
var buyStrats = rbld.buyStrategies != null ? rbld.buyStrategies : rbld.buyStrategiesData.data;
if (buyStrats != null)
{ {
foreach (var bs in rbld.buyStrategies) foreach (var bs in buyStrats)
{ {
Strategy buyStrategy = new Strategy(); Strategy buyStrategy = new Strategy();
buyStrategy.Type = bs.type; buyStrategy.Type = bs.type;
@ -508,8 +517,8 @@ namespace Core.Main.DataObjects
buyStrategy.CurrentValue = bs.currentValue; buyStrategy.CurrentValue = bs.currentValue;
buyStrategy.CurrentValuePercentage = bs.currentValuePercentage; buyStrategy.CurrentValuePercentage = bs.currentValuePercentage;
buyStrategy.Decimals = bs.decimals; buyStrategy.Decimals = bs.decimals;
buyStrategy.IsTrailing = ((string)(bs.positive)).IndexOf("trailing", StringComparison.InvariantCultureIgnoreCase) > -1; buyStrategy.IsTrailing = bs.trailing;
buyStrategy.IsTrue = ((string)(bs.positive)).IndexOf("true", StringComparison.InvariantCultureIgnoreCase) > -1; buyStrategy.IsTrue = bs.strategyResult;
// Is SOM? // Is SOM?
buyLogData.IsSom = buyLogData.IsSom || buyStrategy.Name.Contains("som enabled", StringComparison.OrdinalIgnoreCase); buyLogData.IsSom = buyLogData.IsSom || buyStrategy.Name.Contains("som enabled", StringComparison.OrdinalIgnoreCase);

View File

@ -532,7 +532,7 @@ namespace Core.Main
public bool StartProcess() public bool StartProcess()
{ {
bool result = true; bool result = true;
this.Log.DoLogInfo(""); this.Log.DoLogInfo("");
this.Log.DoLogInfo(" ██████╗ ████████╗ ███╗ ███╗ █████╗ ██████╗ ██╗ ██████╗"); this.Log.DoLogInfo(" ██████╗ ████████╗ ███╗ ███╗ █████╗ ██████╗ ██╗ ██████╗");
this.Log.DoLogInfo(" ██╔══██╗╚══██╔══╝ ████╗ ████║██╔══██╗██╔════╝ ██║██╔════╝"); this.Log.DoLogInfo(" ██╔══██╗╚══██╔══╝ ████╗ ████║██╔══██╗██╔════╝ ██║██╔════╝");
@ -1519,11 +1519,15 @@ namespace Core.Main
int marketPairProcess = 1; int marketPairProcess = 1;
Dictionary<string, List<string>> matchedMarketTriggers = new Dictionary<string, List<string>>(); Dictionary<string, List<string>> matchedMarketTriggers = new Dictionary<string, List<string>>();
// Loop through markets
foreach (string marketPair in this.MarketList) foreach (string marketPair in this.MarketList)
{ {
this.Log.DoLogDebug("'" + marketPair + "' - Checking triggers (" + marketPairProcess.ToString() + "/" + this.MarketList.Count.ToString() + ")..."); this.Log.DoLogDebug("'" + marketPair + "' - Checking triggers (" + marketPairProcess.ToString() + "/" + this.MarketList.Count.ToString() + ")...");
bool stopTriggers = false; bool stopTriggers = false;
// Loop through single market settings
foreach (SingleMarketSetting marketSetting in this.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings) foreach (SingleMarketSetting marketSetting in this.PTMagicConfiguration.AnalyzerSettings.SingleMarketSettings)
{ {
List<string> matchedSingleMarketTriggers = new List<string>(); List<string> matchedSingleMarketTriggers = new List<string>();
@ -1560,7 +1564,7 @@ namespace Core.Main
continue; continue;
} }
#region Checking Off Triggers // Trigger checking
SingleMarketSettingSummary smss = this.SingleMarketSettingSummaries.Find(s => s.Market.Equals(marketPair, StringComparison.InvariantCultureIgnoreCase) && s.SingleMarketSetting.SettingName.Equals(marketSetting.SettingName, StringComparison.InvariantCultureIgnoreCase)); SingleMarketSettingSummary smss = this.SingleMarketSettingSummaries.Find(s => s.Market.Equals(marketPair, StringComparison.InvariantCultureIgnoreCase) && s.SingleMarketSetting.SettingName.Equals(marketSetting.SettingName, StringComparison.InvariantCultureIgnoreCase));
if (smss != null) if (smss != null)
{ {
@ -1576,7 +1580,7 @@ namespace Core.Main
{ {
if (offTrigger.HoursSinceTriggered > 0) if (offTrigger.HoursSinceTriggered > 0)
{ {
#region Check for Activation time period trigger // Check for Activation time period trigger
int smsActiveHours = (int)Math.Floor(DateTime.UtcNow.Subtract(smss.ActivationDateTimeUTC).TotalHours); int smsActiveHours = (int)Math.Floor(DateTime.UtcNow.Subtract(smss.ActivationDateTimeUTC).TotalHours);
if (smsActiveHours >= offTrigger.HoursSinceTriggered) if (smsActiveHours >= offTrigger.HoursSinceTriggered)
{ {
@ -1588,17 +1592,15 @@ namespace Core.Main
} }
else else
{ {
// Trigger not met! // Trigger not met!
this.Log.DoLogDebug("'" + marketPair + "' - SMS only active for " + smsActiveHours.ToString() + " hours. Trigger not matched!"); this.Log.DoLogDebug("'" + marketPair + "' - SMS only active for " + smsActiveHours.ToString() + " hours. Trigger not matched!");
offTriggerResults.Add(false); offTriggerResults.Add(false);
} }
#endregion
} }
else if (offTrigger.Min24hVolume > 0 || offTrigger.Max24hVolume < Constants.Max24hVolume) else if (offTrigger.Min24hVolume > 0 || offTrigger.Max24hVolume < Constants.Max24hVolume)
{ {
#region Check for 24h volume trigger // Check for 24h volume trigger
List<MarketTrendChange> marketTrendChanges = this.SingleMarketTrendChanges[this.SingleMarketTrendChanges.Keys.Last()]; List<MarketTrendChange> marketTrendChanges = this.SingleMarketTrendChanges[this.SingleMarketTrendChanges.Keys.Last()];
if (marketTrendChanges.Count > 0) if (marketTrendChanges.Count > 0)
{ {
@ -1607,7 +1609,6 @@ namespace Core.Main
{ {
if (mtc.Volume24h >= offTrigger.Min24hVolume && mtc.Volume24h <= offTrigger.Max24hVolume) if (mtc.Volume24h >= offTrigger.Min24hVolume && mtc.Volume24h <= offTrigger.Max24hVolume)
{ {
// Trigger met! // Trigger met!
this.Log.DoLogDebug("'" + marketPair + "' - 24h volume off trigger matched! 24h volume = " + mtc.Volume24h.ToString(new System.Globalization.CultureInfo("en-US")) + " " + this.LastRuntimeSummary.MainMarket); this.Log.DoLogDebug("'" + marketPair + "' - 24h volume off trigger matched! 24h volume = " + mtc.Volume24h.ToString(new System.Globalization.CultureInfo("en-US")) + " " + this.LastRuntimeSummary.MainMarket);
@ -1615,7 +1616,6 @@ namespace Core.Main
} }
else else
{ {
// Trigger not met! // Trigger not met!
this.Log.DoLogDebug("'" + marketPair + "' - 24h volume off trigger not matched! 24h volume = " + mtc.Volume24h.ToString(new System.Globalization.CultureInfo("en-US")) + " " + this.LastRuntimeSummary.MainMarket); this.Log.DoLogDebug("'" + marketPair + "' - 24h volume off trigger not matched! 24h volume = " + mtc.Volume24h.ToString(new System.Globalization.CultureInfo("en-US")) + " " + this.LastRuntimeSummary.MainMarket);
@ -1623,19 +1623,48 @@ namespace Core.Main
} }
} }
} }
#endregion
} }
else else
{ {
#region Check for market trend triggers // Check for market trend Off triggers
if (this.SingleMarketTrendChanges.ContainsKey(offTrigger.MarketTrendName)) if (this.SingleMarketTrendChanges.ContainsKey(offTrigger.MarketTrendName))
{ {
List<MarketTrendChange> marketTrendChanges = this.SingleMarketTrendChanges[offTrigger.MarketTrendName]; List<MarketTrendChange> marketTrendChanges = this.SingleMarketTrendChanges[offTrigger.MarketTrendName];
List<MarketTrend> marketTrends = this.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends;
if (marketTrendChanges.Count > 0) if (marketTrendChanges.Count > 0)
{ {
double averageMarketTrendChange = marketTrendChanges.Average(m => m.TrendChange); double averageMarketTrendChange = 0;
var trendThreshold = (from mt in this.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends
where mt.Name == offTrigger.MarketTrendName
select new { mt.TrendThreshold }).Single();
// Calculate average market change, skip any that are outside the threshold if enabled
if (trendThreshold.TrendThreshold != 0)
{
// Exclude trends outside the threshhold.
var excludedMarkets = from m in marketTrendChanges
where m.TrendChange > trendThreshold.TrendThreshold || m.TrendChange < (trendThreshold.TrendThreshold * -1.0)
orderby m.Market
select m;
foreach (var marketTrend in excludedMarkets)
{
this.Log.DoLogInfo(String.Format("SMS Off Trigger for '{0}' is ignoring {1} for exceeding TrendThreshold {2}% with {3}% on {4}", marketSetting.SettingName, marketTrend.Market, (double)trendThreshold.TrendThreshold, Math.Round(marketTrend.TrendChange, 3, MidpointRounding.ToEven), offTrigger.MarketTrendName));
}
var includedMarkets = from m in marketTrendChanges
where m.TrendChange <= trendThreshold.TrendThreshold && m.TrendChange >= (trendThreshold.TrendThreshold * -1.0)
orderby m.Market
select m;
averageMarketTrendChange = includedMarkets.Average(m => m.TrendChange);
}
else
{
// Calculate for whole market
averageMarketTrendChange = marketTrendChanges.Average(m => m.TrendChange);
}
MarketTrendChange mtc = marketTrendChanges.Find(m => m.Market.Equals(marketPair, StringComparison.InvariantCultureIgnoreCase)); MarketTrendChange mtc = marketTrendChanges.Find(m => m.Market.Equals(marketPair, StringComparison.InvariantCultureIgnoreCase));
if (mtc != null) if (mtc != null)
@ -1645,7 +1674,6 @@ namespace Core.Main
if (offTrigger.MarketTrendRelation.Equals(Constants.MarketTrendRelationRelative)) if (offTrigger.MarketTrendRelation.Equals(Constants.MarketTrendRelationRelative))
{ {
// Build pair trend change relative to the global market trend // Build pair trend change relative to the global market trend
trendChange = trendChange - averageMarketTrendChange; trendChange = trendChange - averageMarketTrendChange;
} }
@ -1684,7 +1712,6 @@ namespace Core.Main
offTriggerResults.Add(false); offTriggerResults.Add(false);
} }
} }
#endregion
} }
} }
@ -1720,8 +1747,8 @@ namespace Core.Main
} }
} }
} }
#endregion
// Do we have triggers
if (marketSetting.Triggers.Count > 0 && !stopTriggers) if (marketSetting.Triggers.Count > 0 && !stopTriggers)
{ {
#region Checking Triggers #region Checking Triggers
@ -1730,6 +1757,8 @@ namespace Core.Main
List<bool> triggerResults = new List<bool>(); List<bool> triggerResults = new List<bool>();
Dictionary<int, double> relevantTriggers = new Dictionary<int, double>(); Dictionary<int, double> relevantTriggers = new Dictionary<int, double>();
int triggerIndex = 0; int triggerIndex = 0;
// Loop through SMS triggers
foreach (Trigger trigger in marketSetting.Triggers) foreach (Trigger trigger in marketSetting.Triggers)
{ {
@ -1819,7 +1848,37 @@ namespace Core.Main
List<MarketTrendChange> marketTrendChanges = this.SingleMarketTrendChanges[trigger.MarketTrendName]; List<MarketTrendChange> marketTrendChanges = this.SingleMarketTrendChanges[trigger.MarketTrendName];
if (marketTrendChanges.Count > 0) if (marketTrendChanges.Count > 0)
{ {
double averageMarketTrendChange = marketTrendChanges.Average(m => m.TrendChange); double averageMarketTrendChange = 0;
var trendThreshold = (from mt in this.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.MarketTrends
where mt.Name == trigger.MarketTrendName
select new { mt.TrendThreshold }).Single();
// Calculate average market change, skip any that are outside the threshold if enabled
if (trendThreshold.TrendThreshold != 0)
{
// Exclude trends outside the threshhold.
var excludedMarkets = from m in marketTrendChanges
where m.TrendChange > trendThreshold.TrendThreshold || m.TrendChange < (trendThreshold.TrendThreshold * -1.0)
orderby m.Market
select m;
foreach (var marketTrend in excludedMarkets)
{
this.Log.DoLogInfo(String.Format("SMS Trigger for '{0}' is ignoring {1} for exceeding TrendThreshold {2}% with {3}% on {4}", marketSetting.SettingName, marketTrend.Market, (double)trendThreshold.TrendThreshold, Math.Round(marketTrend.TrendChange, 3, MidpointRounding.ToEven), trigger.MarketTrendName));
}
var includedMarkets = from m in marketTrendChanges
where m.TrendChange <= trendThreshold.TrendThreshold && m.TrendChange >= (trendThreshold.TrendThreshold * -1.0)
orderby m.Market
select m;
averageMarketTrendChange = includedMarkets.Average(m => m.TrendChange);
}
else
{
// Calculate for whole market
averageMarketTrendChange = marketTrendChanges.Average(m => m.TrendChange);
}
MarketTrendChange mtc = marketTrendChanges.Find(m => m.Market.Equals(marketPair, StringComparison.InvariantCultureIgnoreCase)); MarketTrendChange mtc = marketTrendChanges.Find(m => m.Market.Equals(marketPair, StringComparison.InvariantCultureIgnoreCase));
if (mtc != null) if (mtc != null)
@ -1895,7 +1954,7 @@ namespace Core.Main
#endregion #endregion
} }
triggerIndex++; triggerIndex++;
} } // End loop SMS triggers
// Check if all triggers have to get triggered or just one // Check if all triggers have to get triggered or just one
bool settingTriggered = false; bool settingTriggered = false;
@ -2041,7 +2100,7 @@ namespace Core.Main
this.Log.DoLogDebug("'" + marketPair + "' - '" + marketSetting.SettingName + "' not triggered!"); this.Log.DoLogDebug("'" + marketPair + "' - '" + marketSetting.SettingName + "' not triggered!");
} }
} }
} } // End loop single market settings
if ((marketPairProcess % 10) == 0) if ((marketPairProcess % 10) == 0)
{ {
@ -2049,8 +2108,9 @@ namespace Core.Main
} }
marketPairProcess++; marketPairProcess++;
} } // End loop through markets
// Did we trigger any SMS?
if (this.TriggeredSingleMarketSettings.Count > 0) if (this.TriggeredSingleMarketSettings.Count > 0)
{ {
this.Log.DoLogInfo("Building single market settings for '" + this.TriggeredSingleMarketSettings.Count.ToString() + "' markets..."); this.Log.DoLogInfo("Building single market settings for '" + this.TriggeredSingleMarketSettings.Count.ToString() + "' markets...");
@ -2319,11 +2379,11 @@ namespace Core.Main
string ProfitPercentageLabel = ""; string ProfitPercentageLabel = "";
for (char c = 'A'; c <= 'Z'; c++) for (char c = 'A'; c <= 'Z'; c++)
{ {
string buyStrategyName = SettingsHandler.GetCurrentPropertyValue(dcaProperties, "DEFAULT_DCA_" + c + "_buy_strategy", ""); string buyStrategyName = SettingsHandler.GetCurrentPropertyValue(dcaProperties, "DEFAULT_DCA_" + c + "_buy_strategy", "");
if (buyStrategyName.Contains("PROFITPERCENTAGE")) if (buyStrategyName.Contains("PROFITPERCENTAGE"))
{ {
ProfitPercentageLabel = "" + c; ProfitPercentageLabel = "" + c;
} }
} }
@ -2626,4 +2686,4 @@ namespace Core.Main
} }
#endregion #endregion
} }
} }

View File

@ -261,85 +261,92 @@ namespace Core.ProfitTrailer
public static bool IsValidStrategy(string strategyName, bool checkForAnyInvalid) public static bool IsValidStrategy(string strategyName, bool checkForAnyInvalid)
{ {
bool result = false; bool result = false;
// buy/sell strategies beginning with PT 2.3.3 contain the letter followed by a colon and space.
if (strategyName.Contains(":")) if (!string.IsNullOrEmpty(strategyName))
{ {
result = true; // buy/sell strategies beginning with PT 2.3.3 contain the letter followed by a colon and space.
} if (strategyName.Contains(":"))
if (!checkForAnyInvalid)
{
switch (strategyName.ToLower())
{
case "lowbb":
case "highbb":
case "gain":
case "loss":
case "smagain":
case "emagain":
case "hmagain":
case "dmagain":
case "smaspread":
case "emaspread":
case "hmaspread":
case "dmaspread":
case "smacross":
case "emacross":
case "hmacross":
case "dmacross":
case "rsi":
case "stoch":
case "stochrsi":
case "stochrsik":
case "stochrsid":
case "stochrsicross":
case "macd":
case "obv":
case "bbwidth":
case "anderson":
case "dema":
case "hma":
case "pdhigh":
case "pdlow":
case "pdclose":
case "signal":
case "changepercentage":
case "profitpercentage":
case "lastdcabuy":
case "fixedprice":
case "lowatrband":
case "highatrband":
case "atrpercentage":
case "vwappercentage":
case "mvwappercentage":
case "btcdominance":
case "combimagain":
case "combimaspread":
case "combimacross":
case "macdpercentage":
result = true;
break;
default:
break;
}
}
else
{
if (strategyName.IndexOf("max", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("min", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("som", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("price", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("black", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("new", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("insufficient", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("timeout", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("spread", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("pairs", StringComparison.InvariantCultureIgnoreCase) == -1)
{ {
result = true; result = true;
} }
if (!checkForAnyInvalid)
{
switch (strategyName.ToLower())
{
case "lowbb":
case "highbb":
case "gain":
case "loss":
case "smagain":
case "emagain":
case "hmagain":
case "dmagain":
case "smaspread":
case "emaspread":
case "hmaspread":
case "dmaspread":
case "smacross":
case "emacross":
case "hmacross":
case "dmacross":
case "rsi":
case "stoch":
case "stochrsi":
case "stochrsik":
case "stochrsid":
case "stochrsicross":
case "macd":
case "obv":
case "bbwidth":
case "anderson":
case "dema":
case "hma":
case "pdhigh":
case "pdlow":
case "pdclose":
case "signal":
case "changepercentage":
case "profitpercentage":
case "lastdcabuy":
case "fixedprice":
case "lowatrband":
case "highatrband":
case "atrpercentage":
case "vwappercentage":
case "mvwappercentage":
case "btcdominance":
case "combimagain":
case "combimaspread":
case "combimacross":
case "macdpercentage":
result = true;
break;
default:
break;
}
}
else
{
if (strategyName.IndexOf("max", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("min", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("som", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("price", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("black", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("new", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("insufficient", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("timeout", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("spread", StringComparison.InvariantCultureIgnoreCase) == -1
&& strategyName.IndexOf("pairs", StringComparison.InvariantCultureIgnoreCase) == -1)
{
result = true;
}
}
} }
return result; return result;
} }
public static int GetStrategyValueDecimals(string strategyName) public static int GetStrategyValueDecimals(string strategyName)
{ {
int result = 0; int result = 0;
@ -397,7 +404,7 @@ namespace Core.ProfitTrailer
if (!isValidStrategy) if (!isValidStrategy)
{ {
if (strategy.Name.Contains("TRIGGERED")) if (strategy.Name.Contains("TRIGGERED"))
// remove levels already triggered, to show only currently waiting trigger // remove levels already triggered, to show only currently waiting trigger
{ {
strategyText += ""; strategyText += "";
} }

View File

@ -196,7 +196,7 @@
<th class="text-right">Sales</th> <th class="text-right">Sales</th>
<th class="text-right">Profit @Model.Summary.MainMarket</th> <th class="text-right">Profit @Model.Summary.MainMarket</th>
<th class="text-right">Profit @Model.Summary.MainFiatCurrency</th> <th class="text-right">Profit @Model.Summary.MainFiatCurrency</th>
<th class="text-right">% Gain</th> <th class="text-right">Gain</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@ -138,50 +138,36 @@
isSellStrategyTrue = (dcaLogEntry.SellStrategies.FindAll(ss => !ss.IsTrue).Count == 0); isSellStrategyTrue = (dcaLogEntry.SellStrategies.FindAll(ss => !ss.IsTrue).Count == 0);
} }
bool buyDisabled = false;
string leverage = ""; string leverage = "";
double leverageValue = 1; double leverageValue = 1;
string buyStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.BuyStrategies, dcaLogEntry.BuyStrategy, isBuyStrategyTrue, isTrailingBuyActive); string buyStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.BuyStrategies, dcaLogEntry.BuyStrategy, isBuyStrategyTrue, isTrailingBuyActive);
if (!Core.ProfitTrailer.StrategyHelper.IsValidStrategy(buyStrategyText, true))
{
buyDisabled = true;
}
string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive); string sellStrategyText = Core.ProfitTrailer.StrategyHelper.GetStrategyText(Model.Summary, dcaLogEntry.SellStrategies, dcaLogEntry.SellStrategy, isSellStrategyTrue, isTrailingSellActive);
// Check for when PT loses the value of a pair // Check for when PT loses the value of a pair
bool lostValue = false; bool lostValue = false;
lostValue = (dcaLogEntry.TotalCost == 0.0) || (dcaLogEntry.AverageBuyPrice == 0.0); lostValue = (dcaLogEntry.TotalCost == 0.0) || (dcaLogEntry.AverageBuyPrice == 0.0);
double exchangeFee = 0; // Profit percentage
switch (Model.PTMagicConfiguration.GeneralSettings.Application.Exchange.ToLower()) var profitPercentage = dcaLogEntry.ProfitPercent;
if (dcaLogEntry.SellStrategies != null)
{ {
case "binance": var gainStrategy = dcaLogEntry.SellStrategies.FirstOrDefault(x => x.Name.Contains(" GAIN", StringComparison.InvariantCultureIgnoreCase));
exchangeFee = 0.002; if (gainStrategy != null)
break; {
case "binanceus": // Use the gain percentage value as it is accurate to what can be achieved with the order book!
exchangeFee = 0.002; profitPercentage = gainStrategy.CurrentValue;
break; }
case "binancefutures":
exchangeFee = 0.002;
break;
case "bittrex":
exchangeFee = 0.0025;
break;
case "poloniex":
exchangeFee = 0.0025;
break;
default:
break;
} }
// Aggregate totals // Aggregate totals
double tradingFee = (exchangeFee * dcaLogEntry.TotalCost) * 2; double bagGain = (profitPercentage / 100) * dcaLogEntry.TotalCost * leverageValue;
double bagGain = (dcaLogEntry.ProfitPercent / 100) * dcaLogEntry.TotalCost * leverageValue;
Model.TotalBagCost = Model.TotalBagCost + dcaLogEntry.TotalCost; Model.TotalBagCost = Model.TotalBagCost + dcaLogEntry.TotalCost;
Model.TotalBagGain = Model.TotalBagGain + bagGain; Model.TotalBagGain = Model.TotalBagGain + bagGain;
// Render the row // Render the row
<tr @(lostValue ? "class=errorRow" : "") > <tr @(lostValue ? "class=errorRow" : "") >
<!-- Market -->
@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, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a></th> <th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a></th>
@ -189,8 +175,11 @@
{ {
<th class="align-top"><a href="@Core.Helper.SystemHelper.GetMarketLink(Model.PTMagicConfiguration.GeneralSettings.Monitor.LinkPlatform,Model.PTMagicConfiguration.GeneralSettings.Application.Exchange, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a> <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, dcaLogEntry.Market, Model.Summary.MainMarket)" target="_blank">@dcaLogEntry.Market</a> <i class="fa fa-exclamation-triangle text-highlight" data-toggle="tooltip" data-placement="top" data-html="true" title="@await Component.InvokeAsync("PairIcon", mps)" data-template="<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner pair-tooltip'></div></div>"></i></th>
} }
<!-- 24hr change -->
<td class="text-autocolor">@Html.Raw((dcaLogEntry.PercChange * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")))%</td> <td class="text-autocolor">@Html.Raw((dcaLogEntry.PercChange * 100).ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")))%</td>
<!-- Cost -->
<td class="text-left">@Html.Raw(dcaLogEntry.TotalCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")))</td> <td class="text-left">@Html.Raw(dcaLogEntry.TotalCost.ToString("#,#0.000000", new System.Globalization.CultureInfo("en-US")))</td>
<!-- DCA Count -->
<td class="text-right"> <td class="text-right">
@if (dcaEnabled) @if (dcaEnabled)
{ {
@ -203,9 +192,11 @@
<span data-toggle="tooltip" data-placement="top" title="DCA is disabled"><i class="fa fa-ban text-highlight"></i></span> <span data-toggle="tooltip" data-placement="top" title="DCA is disabled"><i class="fa fa-ban text-highlight"></i></span>
} }
</td> </td>
<!-- DCA Strategy -->
<td>@Html.Raw(buyStrategyText)</td> <td>@Html.Raw(buyStrategyText)</td>
<!-- Sell Strategy -->
<td>@Html.Raw(sellStrategyText)</td> <td>@Html.Raw(sellStrategyText)</td>
<!-- Target -->
@if (!sellStrategyText.Contains("WATCHMODE")) @if (!sellStrategyText.Contains("WATCHMODE"))
{ {
@if (sellStrategyText.Contains("CROSSED")) @if (sellStrategyText.Contains("CROSSED"))
@ -223,12 +214,12 @@
} }
@if (leverageValue == 1) @if (leverageValue == 1)
{ {
<td class="@Html.Raw((dcaLogEntry.TargetGainValue.HasValue && (dcaLogEntry.ProfitPercent > dcaLogEntry.TargetGainValue.Value)) ? "text-success" : "text-danger")">@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? dcaLogEntry.TargetGainValue.Value.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : "&nbsp")</td> <td class="@Html.Raw((dcaLogEntry.TargetGainValue.HasValue && (profitPercentage > dcaLogEntry.TargetGainValue.Value)) ? "text-success" : "text-danger")">@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? dcaLogEntry.TargetGainValue.Value.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : "&nbsp")</td>
} }
else else
{ {
double TargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value; double TargetGain = leverageValue * dcaLogEntry.TargetGainValue.Value;
<td class="@Html.Raw((dcaLogEntry.TargetGainValue.HasValue && (dcaLogEntry.ProfitPercent > dcaLogEntry.TargetGainValue.Value)) ? "text-success" : "text-danger")">@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? TargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : "&nbsp")</td> <td class="@Html.Raw((dcaLogEntry.TargetGainValue.HasValue && (profitPercentage > dcaLogEntry.TargetGainValue.Value)) ? "text-success" : "text-danger")">@Html.Raw(dcaLogEntry.TargetGainValue.HasValue ? TargetGain.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US")) + "%" : "&nbsp")</td>
} }
} }
else else
@ -236,16 +227,17 @@
<td class="text-left"></td> <td class="text-left"></td>
} }
<!-- Profit -->
@if (!@lostValue) @if (!@lostValue)
{ {
<td class="text-autocolor">@dcaLogEntry.ProfitPercent.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%</td> <td class="text-autocolor">@profitPercentage.ToString("#,#0.00", new System.Globalization.CultureInfo("en-US"))%</td>
} }
else else
{ {
<td class="text-left">No Value!</td> <td class="text-left">No Value!</td>
} }
<!-- Bag details -->
<td class="text-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_get/BagDetails/?m=@dcaLogEntry.Market" data-remote="false" data-toggle="modal" data-target="#dca-chart"><i class="fa fa-plus-circle"></i></a></td> <td class="text-right"><a href="@Html.Raw(Model.PTMagicConfiguration.GeneralSettings.Monitor.RootUrl)_get/BagDetails/?m=@dcaLogEntry.Market" data-remote="false" data-toggle="modal" data-target="#dca-chart"><i class="fa fa-plus-circle"></i></a></td>
</tr> </tr>
} }

View File

@ -3,13 +3,17 @@
@{ @{
Layout = null; Layout = null;
// Single market settings tool tip
int activeSingleSettings = Model.MarketsWithSingleSettings.Count; int activeSingleSettings = Model.MarketsWithSingleSettings.Count;
string singleSettingInfoIcon = ""; string singleSettingInfoIcon = "";
if (activeSingleSettings > 0) { if (activeSingleSettings > 0) {
singleSettingInfoIcon = "<i class=\"fa fa-info-circle text-muted\" data-toggle=\"tooltip\" data-placement=\"top\" data-html=\"true\" title=\"<b>Single Market Settings active for:</b><br />-" + Core.Helper.SystemHelper.ConvertListToTokenString(Model.MarketsWithSingleSettings, "<br />-", true) + "\" data-template=\"<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner tooltip-200 text-left'></div></div>\"></i>"; singleSettingInfoIcon = "<i class=\"fa fa-info-circle text-muted\" data-toggle=\"tooltip\" data-placement=\"top\" data-html=\"true\" title=\"<b>Single Market Settings active for:</b><br />" + Core.Helper.SystemHelper.ConvertListToTokenString(Model.MarketsWithSingleSettings, "<br />", true) + "\" data-template=\"<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner tooltip-200 text-left'></div></div>\"></i>";
} }
// Global setting tool tip
string globalSettingInfoIcon = "<i class=\"fa fa-info-circle text-muted\" data-toggle=\"tooltip\" data-placement=\"top\" data-html=\"true\" title=\"<b>Instance: </b>" + Model.PTMagicConfiguration.GeneralSettings.Application.InstanceName + "\" data-template=\"<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner tooltip-100 text-left'></div></div>\"></i>"; string globalSettingInfoIcon = "<i class=\"fa fa-info-circle text-muted\" data-toggle=\"tooltip\" data-placement=\"top\" data-html=\"true\" title=\"<b>Instance: </b>" + Model.PTMagicConfiguration.GeneralSettings.Application.InstanceName + "\" data-template=\"<div class='tooltip' role='tooltip'><div class='tooltip-arrow'></div><div class='tooltip-inner tooltip-100 text-left'></div></div>\"></i>";
// Health indicator
DateTime lastRuntime = Model.Summary.LastRuntime; DateTime lastRuntime = Model.Summary.LastRuntime;
double elapsedSecondsSinceRuntime = DateTime.UtcNow.Subtract(lastRuntime).TotalSeconds; double elapsedSecondsSinceRuntime = DateTime.UtcNow.Subtract(lastRuntime).TotalSeconds;
double intervalSeconds = Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes * 60.0; double intervalSeconds = Model.PTMagicConfiguration.AnalyzerSettings.MarketAnalyzer.IntervalMinutes * 60.0;

View File

@ -21,14 +21,23 @@ namespace Monitor.Pages {
private void BindData() { private void BindData() {
// Get markets with active single settings // Get markets with active single settings
foreach (string key in Summary.MarketSummary.Keys) { var MarketsWithSingleSettingsData = from x in Summary.MarketSummary
if (Summary.MarketSummary[key].ActiveSingleSettings != null) { where x.Value.ActiveSingleSettings != null
if (Summary.MarketSummary[key].ActiveSingleSettings.Count > 0) { && x.Value.ActiveSingleSettings.Count > 0
MarketsWithSingleSettings.Add(key); orderby x.Key ascending
} select x;
foreach (var market in MarketsWithSingleSettingsData) {
// Get the name of all active single market settings
string activeSettings = string.Empty;
foreach (var singleSetting in market.Value.ActiveSingleSettings)
{
activeSettings += (", " + singleSetting.SettingName);
} }
activeSettings = activeSettings.Substring(2); // Chop the unrequired comma
MarketsWithSingleSettings.Add(String.Format("{0} : {1}", market.Key, activeSettings));
} }
MarketsWithSingleSettings.Sort();
} }
} }
} }