Merge pull request #217 from HojouFotytu/develop
removed formula parsing
This commit is contained in:
commit
3dd5a8bfd1
|
@ -9,205 +9,6 @@ using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Core.ProfitTrailer
|
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)
|
|
||||||
{
|
|
||||||
_text = text;
|
|
||||||
_reader = new StringReader(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Token> Tokenize()
|
|
||||||
{
|
|
||||||
var tokens = new List<Token>();
|
|
||||||
while (_reader.Peek() != -1)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class Parser
|
|
||||||
{
|
|
||||||
private readonly IEnumerator<Token> _tokens;
|
|
||||||
|
|
||||||
public Parser(IEnumerable<Token> 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
|
public static class StrategyHelper
|
||||||
{
|
{
|
||||||
public static string GetStrategyShortcut(string strategyName, bool onlyValidStrategies)
|
public static string GetStrategyShortcut(string strategyName, bool onlyValidStrategies)
|
||||||
|
@ -218,16 +19,20 @@ namespace Core.ProfitTrailer
|
||||||
string strategyLetter = "";
|
string strategyLetter = "";
|
||||||
string strategyNameOnly = strategyName;
|
string strategyNameOnly = strategyName;
|
||||||
|
|
||||||
// PT allows for "advanced_stats" to be turned on in the application settings, to show details of the trailing logic.
|
// PT allows for "advanced_stats" to show details of the trailing logic.
|
||||||
// This code ensures PTM doesn't generate an unnecessary shortcut for this information
|
|
||||||
if (result.Contains("STATS"))
|
if (result.Contains("STATS"))
|
||||||
{
|
{
|
||||||
result = "";
|
result = "";
|
||||||
}
|
}
|
||||||
// strategy labels that are variable value
|
// strategy labels with variable values
|
||||||
if (result.Contains("REBUY"))
|
if (result.Contains("BUY TIMEOUT AS"))
|
||||||
{
|
{
|
||||||
time = strategyName.Remove(0, 14);
|
time = strategyName.Remove(0, 15);
|
||||||
|
result = "REBUY " + time;
|
||||||
|
}
|
||||||
|
if (result.Contains("BUY TIMEOUT"))
|
||||||
|
{
|
||||||
|
time = strategyName.Remove(0, 12);
|
||||||
result = "REBUY " + time;
|
result = "REBUY " + time;
|
||||||
}
|
}
|
||||||
if (result.Contains("CHANGE PERC"))
|
if (result.Contains("CHANGE PERC"))
|
||||||
|
@ -246,7 +51,6 @@ namespace Core.ProfitTrailer
|
||||||
leverage = leverage.Remove(leverage.Length - 1, 1);
|
leverage = leverage.Remove(leverage.Length - 1, 1);
|
||||||
result = "ISOL " + 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
|
// remove the letter and colon, change to shortcut, then reapply the letter and colon
|
||||||
if (strategyName.Contains(":"))
|
if (strategyName.Contains(":"))
|
||||||
{
|
{
|
||||||
|
@ -592,54 +396,27 @@ namespace Core.ProfitTrailer
|
||||||
isValidStrategy = StrategyHelper.IsValidStrategy(strategy.Name);
|
isValidStrategy = StrategyHelper.IsValidStrategy(strategy.Name);
|
||||||
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 += "";
|
||||||
}
|
}
|
||||||
else if (strategy.Name.Contains("STATS"))
|
else if (strategy.Name.Contains("STATS"))
|
||||||
// avoid parsing advanced buy stats
|
// Avoid displaying advanced buy stats and completed level formulas
|
||||||
{
|
{
|
||||||
strategy.Name = "";
|
strategy.Name = "";
|
||||||
}
|
}
|
||||||
else if (strategy.Name.Contains("FORMULA"))
|
else if (strategy.Name.Contains("FORMULA"))
|
||||||
// Parse Various PT Formulas
|
// Avoid displaying formula details
|
||||||
{
|
{
|
||||||
if (strategy.Name.Contains("LEVEL"))
|
if (strategy.Name.Contains("LEVEL"))
|
||||||
// level X
|
|
||||||
{
|
{
|
||||||
string level = strategy.Name.Substring(5, 2);
|
string level = strategy.Name.Substring(5, 1);
|
||||||
string expression = strategy.Name.Remove(0, 17);
|
strategyText += "<span class=\"label label-warning\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"LEVEL FORMULA\">L " + level + "</span> ";
|
||||||
expression = expression.Replace("<span class=\"tdgreen\">", "true").Replace("<span class=\"red\">", "false").Replace("</span>", "").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 += "<span class=\"label label-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"LEVEL FORMULA\">L " + level + "</span> ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strategyText += "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"LEVEL FORMULA\">L " + level + "</span> ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// standard formula
|
|
||||||
{
|
{
|
||||||
string expression = strategy.Name.Remove(0, 10);
|
strategyText += "<span class=\"label label-warning\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"CONDITIONAL FORMULA\">FORM</span> ";
|
||||||
expression = expression.Replace("<span class=\"tdgreen\">", "true").Replace("<span class=\"red\">", "false").Replace("</span>", "").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 += "<span class=\"label label-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"CONDITIONAL FORMULA\">FORM</span> ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strategyText += "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"CONDITIONAL FORMULA\">FORM</span> ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -663,7 +440,7 @@ namespace Core.ProfitTrailer
|
||||||
{
|
{
|
||||||
if (isTrue)
|
if (isTrue)
|
||||||
{
|
{
|
||||||
strategyText = "<span class=\"label label-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>";
|
strategyText = "<span class=\"label label-success\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span> ";
|
||||||
|
|
||||||
if (isTrailingBuyActive)
|
if (isTrailingBuyActive)
|
||||||
{
|
{
|
||||||
|
@ -675,7 +452,7 @@ namespace Core.ProfitTrailer
|
||||||
isValidStrategy = StrategyHelper.IsValidStrategy(strategyText);
|
isValidStrategy = StrategyHelper.IsValidStrategy(strategyText);
|
||||||
if (isValidStrategy)
|
if (isValidStrategy)
|
||||||
{
|
{
|
||||||
strategyText = "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span>";
|
strategyText = "<span class=\"label label-danger\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"" + strategyText + "\">" + StrategyHelper.GetStrategyShortcut(strategyText, true) + "</span> ";
|
||||||
}
|
}
|
||||||
else if (strategyText.Equals("") && isValidStrategy == false)
|
else if (strategyText.Equals("") && isValidStrategy == false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ using Core.Helper;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("2.4.4")]
|
[assembly: AssemblyVersion("2.4.5")]
|
||||||
[assembly: AssemblyProduct("PT Magic")]
|
[assembly: AssemblyProduct("PT Magic")]
|
||||||
|
|
||||||
namespace PTMagic
|
namespace PTMagic
|
||||||
|
|
Loading…
Reference in New Issue