From 43c17bae64339d4c32aecbf38daf1e8c749bb2f7 Mon Sep 17 00:00:00 2001 From: msg_kurt Date: Wed, 4 Sep 2019 16:49:32 +0300 Subject: [PATCH] added timeout for triggering order book updating event --- CryptoExchange.Net/Objects/Options.cs | 18 +++++--- .../OrderBook/SymbolOrderBook.cs | 43 +++++++++++++------ 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/CryptoExchange.Net/Objects/Options.cs b/CryptoExchange.Net/Objects/Options.cs index 525f1c8..156364f 100644 --- a/CryptoExchange.Net/Objects/Options.cs +++ b/CryptoExchange.Net/Objects/Options.cs @@ -26,8 +26,12 @@ namespace CryptoExchange.Net.Objects /// /// Base for order book options /// - public class OrderBookOptions: BaseOptions + public class OrderBookOptions : BaseOptions { + /// + /// Update event raising timeout in milliseconds (to limit it at high-liquidity order books) + /// + public int UpdateEventTimeout { get; } /// /// The name of the order book implementation /// @@ -42,8 +46,10 @@ namespace CryptoExchange.Net.Objects /// /// The name of the order book implementation /// Whether each update should have a consecutive id number. Used to identify and reconnect when numbers are skipped. - public OrderBookOptions(string name, bool sequencesAreConsecutive) + /// Update event raising timeout in milliseconds (to limit it at high-liquidity order books) + public OrderBookOptions(string name, bool sequencesAreConsecutive, int? updateInterval) { + UpdateEventTimeout = updateInterval ?? 1000; OrderBookName = name; SequenceNumbersAreConsecutive = sequencesAreConsecutive; } @@ -52,7 +58,7 @@ namespace CryptoExchange.Net.Objects /// /// Base client options /// - public class ClientOptions: BaseOptions + public class ClientOptions : BaseOptions { /// @@ -74,7 +80,7 @@ namespace CryptoExchange.Net.Objects /// /// Base for rest client options /// - public class RestClientOptions: ClientOptions + public class RestClientOptions : ClientOptions { /// /// List of rate limiters to use @@ -96,7 +102,7 @@ namespace CryptoExchange.Net.Objects /// /// /// - public T Copy() where T:RestClientOptions, new() + public T Copy() where T : RestClientOptions, new() { var copy = new T { @@ -119,7 +125,7 @@ namespace CryptoExchange.Net.Objects /// /// Base for socket client options /// - public class SocketClientOptions: ClientOptions + public class SocketClientOptions : ClientOptions { /// /// Whether or not the socket should automatically reconnect when losing connection diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs index 5edd59d..2e5f2dc 100644 --- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs +++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs @@ -13,7 +13,7 @@ namespace CryptoExchange.Net.OrderBook /// /// Base for order book implementations /// - public abstract class SymbolOrderBook: IDisposable + public abstract class SymbolOrderBook : IDisposable { /// /// The process buffer, used while syncing @@ -27,6 +27,7 @@ namespace CryptoExchange.Net.OrderBook /// /// The bid list /// + protected SortedList bids; private OrderBookStatus status; private UpdateSubscription subscription; @@ -69,12 +70,19 @@ namespace CryptoExchange.Net.OrderBook /// /// Event when the state changes /// - public event Action OnStatusChange; + public event Action OnStatusChange; /// - /// Event when orderbook was updated - /// + /// Event when orderbook was updated, but not more often then timeout setted in orderbook options (1000ms by default). Be careful! with small timeout it can generate a lot of events at high-liquidity order books + /// public event Action OnOrderBookUpdate; /// + /// Should be useful for low-liquidity order-books to monitor market activity + /// + public DateTime LastOrderBookUpdate; + private DateTime LastOrderBookUpdateEventTrigger; + + private readonly int updateEventInterval; + /// /// The number of asks in the book /// public int AskCount { get; private set; } @@ -141,6 +149,7 @@ namespace CryptoExchange.Net.OrderBook id = options.OrderBookName; processBuffer = new List(); sequencesAreConsecutive = options.SequenceNumbersAreConsecutive; + updateEventInterval = options.UpdateEventTimeout; Symbol = symbol; Status = OrderBookStatus.Disconnected; @@ -166,7 +175,7 @@ namespace CryptoExchange.Net.OrderBook { Status = OrderBookStatus.Connecting; var startResult = await DoStart().ConfigureAwait(false); - if(!startResult.Success) + if (!startResult.Success) return new CallResult(false, startResult.Error); subscription = startResult.Data; @@ -234,7 +243,7 @@ namespace CryptoExchange.Net.OrderBook /// /// protected abstract Task> DoResync(); - + /// /// Set the initial data for the order book /// @@ -249,7 +258,7 @@ namespace CryptoExchange.Net.OrderBook return; asks.Clear(); - foreach(var ask in askList) + foreach (var ask in askList) asks.Add(ask.Price, new OrderBookEntry(ask.Price, ask.Quantity)); bids.Clear(); foreach (var bid in bidList) @@ -262,7 +271,12 @@ namespace CryptoExchange.Net.OrderBook CheckProcessBuffer(); bookSet = true; - OnOrderBookUpdate?.Invoke(); + LastOrderBookUpdate = DateTime.UtcNow; + if ((LastOrderBookUpdate - LastOrderBookUpdateEventTrigger).TotalMilliseconds >= updateEventInterval) + { + OnOrderBookUpdate?.Invoke(); + LastOrderBookUpdateEventTrigger = DateTime.UtcNow; + } log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks"); } } @@ -299,11 +313,16 @@ namespace CryptoExchange.Net.OrderBook } else { - foreach(var entry in entries) + foreach (var entry in entries) ProcessUpdate(entry.Type, entry.Entry); LastSequenceNumber = lastSequenceNumber; CheckProcessBuffer(); - OnOrderBookUpdate?.Invoke(); + LastOrderBookUpdate = DateTime.UtcNow; + if ((LastOrderBookUpdate - LastOrderBookUpdateEventTrigger).TotalMilliseconds >= updateEventInterval) + { + OnOrderBookUpdate?.Invoke(); + LastOrderBookUpdateEventTrigger = DateTime.UtcNow; + } log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} update: {entries.Count} entries processed"); } } @@ -316,7 +335,7 @@ namespace CryptoExchange.Net.OrderBook { foreach (var bufferEntry in processBuffer.OrderBy(b => b.FirstSequence).ToList()) { - if(bufferEntry.LastSequence < LastSequenceNumber) + if (bufferEntry.LastSequence < LastSequenceNumber) { processBuffer.Remove(bufferEntry); continue; @@ -325,7 +344,7 @@ namespace CryptoExchange.Net.OrderBook if (bufferEntry.FirstSequence > LastSequenceNumber + 1) break; - foreach(var entry in bufferEntry.Entries) + foreach (var entry in bufferEntry.Entries) ProcessUpdate(entry.Type, entry.Entry); processBuffer.Remove(bufferEntry); LastSequenceNumber = bufferEntry.LastSequence;