Can solve inverse of currency pair

This commit is contained in:
nicolas.dorier 2018-05-05 00:40:54 +09:00
parent 8a4da361fd
commit c2dad08fef
4 changed files with 29 additions and 12 deletions

View File

@ -113,12 +113,21 @@ namespace BTCPayServer.Tests
builder.AppendLine("DOGE_BTC = 2000");
Assert.True(RateRules.TryParse(builder.ToString(), out rules));
rules.GlobalMultiplier = 1.1m;
rule2 = rules.GetRuleFor(CurrencyPair.Parse("DOGE_USD"));
Assert.Equal("(2000 * (-3 + coinbase(BTC_CAD) + 50 - 5)) * 1.1", rule2.ToString());
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), 1000m);
Assert.True(rule2.Reevaluate());
Assert.Equal("(2000 * (-3 + 1000 + 50 - 5)) * 1.1", rule2.ToString(true));
Assert.Equal((2000m * (-3m + 1000m + 50m - 5m)) * 1.1m, rule2.Value.Value);
// Test inverse
rule2 = rules.GetRuleFor(CurrencyPair.Parse("USD_DOGE"));
Assert.Equal("(1 / (2000 * (-3 + coinbase(BTC_CAD) + 50 - 5))) * 1.1", rule2.ToString());
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_CAD"), 1000m);
Assert.True(rule2.Reevaluate());
Assert.Equal("(1 / (2000 * (-3 + 1000 + 50 - 5))) * 1.1", rule2.ToString(true));
Assert.Equal(( 1.0m / (2000m * (-3m + 1000m + 50m - 5m))) * 1.1m, rule2.Value.Value);
////////
}
}

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Version>1.0.2.2</Version>
<Version>1.0.2.3</Version>
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
</PropertyGroup>
<ItemGroup>

View File

@ -90,5 +90,10 @@ namespace BTCPayServer.Rating
{
return $"{Left}_{Right}";
}
public CurrencyPair Inverse()
{
return new CurrencyPair(Right, Left);
}
}
}

View File

@ -133,28 +133,30 @@ namespace BTCPayServer.Rating
if (currencyPair.Left == "X" || currencyPair.Right == "X")
throw new ArgumentException(paramName: nameof(currencyPair), message: "Invalid X currency");
var candidate = FindBestCandidate(currencyPair);
if (GlobalMultiplier != decimal.One)
{
candidate = CreateExpression($"({candidate}) * {GlobalMultiplier.ToString(CultureInfo.InvariantCulture)}");
}
return new RateRule(this, currencyPair, candidate);
}
public ExpressionSyntax FindBestCandidate(CurrencyPair p)
{
var candidates = new List<(CurrencyPair Pair, int Prioriy, ExpressionSyntax Expression)>();
var invP = p.Inverse();
var candidates = new List<(CurrencyPair Pair, int Prioriy, ExpressionSyntax Expression, bool Inverse)>();
foreach (var pair in new[]
{
(Pair: p, Priority: 0),
(Pair: new CurrencyPair(p.Left, "X"), Priority: 1),
(Pair: new CurrencyPair("X", p.Right), Priority: 1),
(Pair: new CurrencyPair("X", "X"), Priority: 2)
(Pair: p, Priority: 0, Inverse: false),
(Pair: new CurrencyPair(p.Left, "X"), Priority: 1, Inverse: false),
(Pair: new CurrencyPair("X", p.Right), Priority: 1, Inverse: false),
(Pair: new CurrencyPair(invP.Left, "X"), Priority: 2, Inverse: true),
(Pair: new CurrencyPair("X", invP.Right), Priority: 2, Inverse: true),
(Pair: new CurrencyPair("X", "X"), Priority: 3, Inverse: false)
})
{
if (ruleList.ExpressionsByPair.TryGetValue(pair.Pair, out var expression))
{
candidates.Add((pair.Pair, pair.Priority, expression.Expression));
candidates.Add((pair.Pair, pair.Priority, expression.Expression, pair.Inverse));
}
}
if (candidates.Count == 0)
@ -163,8 +165,9 @@ namespace BTCPayServer.Rating
.OrderBy(c => c.Prioriy)
.ThenBy(c => c.Expression.Span.Start)
.First();
return best.Expression;
return best.Inverse
? CreateExpression($"1 / {invP}")
: best.Expression;
}
internal static ExpressionSyntax CreateExpression(string str)
@ -364,7 +367,7 @@ namespace BTCPayServer.Rating
string _ExchangeName = null;
public List<RateRulesErrors> Errors = new List<RateRulesErrors>();
const int MaxNestedCount = 6;
const int MaxNestedCount = 8;
public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
{
if (CurrencyPair.TryParse(node.Identifier.ValueText, out var currentPair))