From 109c3964c5fbb89a798d0e82dc22960219bfba78 Mon Sep 17 00:00:00 2001 From: sonvister Date: Wed, 5 Dec 2018 11:06:49 -0500 Subject: [PATCH] Updates For #111. --- .../Controllers/GetSymbols.cs | 7 +++- .../Controllers/IntegrationTests.cs | 39 ++++++++++++++++--- src/Binance/PriceRange.cs | 22 +++++++++-- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/samples/BinanceConsoleApp/Controllers/GetSymbols.cs b/samples/BinanceConsoleApp/Controllers/GetSymbols.cs index 00335047..e2ed7993 100644 --- a/samples/BinanceConsoleApp/Controllers/GetSymbols.cs +++ b/samples/BinanceConsoleApp/Controllers/GetSymbols.cs @@ -18,10 +18,15 @@ public async Task HandleAsync(string command, CancellationToken token = de var args = command.Split(' '); - if (args.Length > 1 && args[1].Equals("refresh", StringComparison.OrdinalIgnoreCase)) + if (args.Length > 1 && (args[1].Equals("refresh", StringComparison.OrdinalIgnoreCase) || args[1].Equals("update", StringComparison.OrdinalIgnoreCase))) { await Symbol.UpdateCacheAsync(Program.Api, token); } + else + { + Console.WriteLine($"Invalid command: \"{args[1]}\""); + return true; + } var symbols = Symbol.Cache.GetAll().OrderBy(s => s.ToString()); //var symbols = await Program.Api.SymbolsAsync(token); // as string. diff --git a/samples/BinanceConsoleApp/Controllers/IntegrationTests.cs b/samples/BinanceConsoleApp/Controllers/IntegrationTests.cs index b2db31c2..21d9b025 100644 --- a/samples/BinanceConsoleApp/Controllers/IntegrationTests.cs +++ b/samples/BinanceConsoleApp/Controllers/IntegrationTests.cs @@ -20,15 +20,44 @@ public async Task HandleAsync(string command, CancellationToken token = de /////////////////////////////////////////////////////////////////// var valid = symbol.IsPriceQuantityValid(5000.01m, 0.1m); - var _valid = symbol.IsPriceQuantityValid(50000.01m, 0.1m); - var __valid = symbol.IsPriceQuantityValid(50.01m, 0.1m); + var _valid = symbol.IsPriceQuantityValid(symbol.Price.Maximum + 1, 0.01m); + var __valid = symbol.IsPriceQuantityValid(symbol.Price.Minimum - 1, 1.0m); lock (Program.ConsoleSync) { Console.WriteLine(); Console.WriteLine($"Price/Quantity Valid: {valid}"); - Console.WriteLine($"Price/Quantity Valid: {_valid}"); - Console.WriteLine($"Price/Quantity Valid: {__valid}"); + Console.WriteLine($"Price/Quantity Not Valid: {!_valid}"); + Console.WriteLine($"Price/Quantity Not Valid: {!__valid}"); + + Console.WriteLine($"Maximum: {symbol.Price.Maximum}"); + Console.WriteLine($"Minimum: {symbol.Price.Minimum}"); + } + + try + { + await Program.Api.TestPlaceAsync(new LimitOrder(Program.User) + { + Symbol = symbol, + Side = OrderSide.Sell, + Quantity = 0.01m, + Price = symbol.Price.Maximum, + }); + Console.WriteLine("Maximum Test Order Placed."); + + await Program.Api.TestPlaceAsync(new LimitOrder(Program.User) + { + Symbol = symbol, + Side = OrderSide.Buy, + Quantity = 1.0m, + Price = symbol.Price.Minimum + }); + Console.WriteLine("Minimum Test Order Placed."); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; } /////////////////////////////////////////////////////////////////// @@ -122,7 +151,7 @@ public async Task HandleAsync(string command, CancellationToken token = de /////////////////////////////////////////////////////////////////*/ - return true; + return await Task.FromResult(true); } } } diff --git a/src/Binance/PriceRange.cs b/src/Binance/PriceRange.cs index 6c2393ec..8d11e766 100644 --- a/src/Binance/PriceRange.cs +++ b/src/Binance/PriceRange.cs @@ -10,9 +10,21 @@ public sealed class PriceRange : InclusiveRange public decimal MultiplierDown { get; } - public override decimal Minimum => Math.Floor(GetAveragePrice() * MultiplierDown / Increment) * Increment; - - public override decimal Maximum => Math.Ceiling(GetAveragePrice() * MultiplierUp / Increment) * Increment; + /// + /// Get the realtime minimum price. + /// + /// NOTE: Average price changes frequently; using the exact minimum value for an order price occassionaly fails. + /// So, a (10 * Increment) buffer is added to the minimum calculation to improve reliability. + /// + public override decimal Minimum => Math.Ceiling(GetAveragePrice() * MultiplierDown / Increment) * Increment + 10 * Increment; + + /// + /// Get the realtime maximum price. + /// + /// NOTE: Average price changes frequently; using the exact maximum value for an order price occassionaly fails. + /// So, a (10 * Increment) buffer is subtraced from the maximum calculation to improve reliability. + /// + public override decimal Maximum => Math.Floor(GetAveragePrice() * MultiplierUp / Increment) * Increment - 10 * Increment; #endregion Public Properties @@ -49,9 +61,11 @@ public PriceRange(IBinanceApi api, string symbol, decimal multiplierUp, decimal private decimal GetAveragePrice() { + // TODO: Add a BinanceApiOption property for this update delay seconds/milliseconds... ? if (_averagePrice == 0 || DateTime.UtcNow - _lastUpdate > TimeSpan.FromSeconds(1)) { - _averagePrice = _api.GetAvgPriceAsync(_symbol).GetAwaiter().GetResult().Value; + // TODO: Redesign price/quantity validation to use async methods rather than properties... ? + _averagePrice = _api.GetAvgPriceAsync(_symbol).GetAwaiter().GetResult().Value; // HACK _lastUpdate = DateTime.UtcNow; }