From c01bcc87b13d5d663d6cff09257c95b99e3f2da5 Mon Sep 17 00:00:00 2001 From: msg_kurt Date: Wed, 4 Sep 2019 12:48:20 +0300 Subject: [PATCH 1/3] added orderbook update event --- CryptoExchange.Net/OrderBook/SymbolOrderBook.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs index e6c2e29..5edd59d 100644 --- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs +++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs @@ -69,8 +69,11 @@ namespace CryptoExchange.Net.OrderBook /// /// Event when the state changes /// - public event Action OnStatusChange; - + public event Action OnStatusChange; + /// + /// Event when orderbook was updated + /// + public event Action OnOrderBookUpdate; /// /// The number of asks in the book /// @@ -259,6 +262,7 @@ namespace CryptoExchange.Net.OrderBook CheckProcessBuffer(); bookSet = true; + OnOrderBookUpdate?.Invoke(); log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks"); } } @@ -299,6 +303,7 @@ namespace CryptoExchange.Net.OrderBook ProcessUpdate(entry.Type, entry.Entry); LastSequenceNumber = lastSequenceNumber; CheckProcessBuffer(); + OnOrderBookUpdate?.Invoke(); log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} update: {entries.Count} entries processed"); } } From 43c17bae64339d4c32aecbf38daf1e8c749bb2f7 Mon Sep 17 00:00:00 2001 From: msg_kurt Date: Wed, 4 Sep 2019 16:49:32 +0300 Subject: [PATCH 2/3] 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; From 6a3df9f7e79327113a2b3a48203443e6a3e9fcdd Mon Sep 17 00:00:00 2001 From: msg_kurt Date: Wed, 4 Sep 2019 17:23:30 +0300 Subject: [PATCH 3/3] removed event triggering timeout --- CryptoExchange.Net/CryptoExchange.Net.xml | 10 ++++++++++ CryptoExchange.Net/Objects/Options.cs | 12 +++--------- CryptoExchange.Net/OrderBook/SymbolOrderBook.cs | 17 +++-------------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/CryptoExchange.Net/CryptoExchange.Net.xml b/CryptoExchange.Net/CryptoExchange.Net.xml index fd9367b..63ed486 100644 --- a/CryptoExchange.Net/CryptoExchange.Net.xml +++ b/CryptoExchange.Net/CryptoExchange.Net.xml @@ -1553,6 +1553,16 @@ Event when the state changes + + + Event when orderbook was updated. Be careful! It can generate a lot of events at high-liquidity markets + + + + + Should be useful for low-liquidity order-books to monitor market activity + + The number of asks in the book diff --git a/CryptoExchange.Net/Objects/Options.cs b/CryptoExchange.Net/Objects/Options.cs index 156364f..22c3729 100644 --- a/CryptoExchange.Net/Objects/Options.cs +++ b/CryptoExchange.Net/Objects/Options.cs @@ -27,11 +27,7 @@ namespace CryptoExchange.Net.Objects /// Base for order book options /// 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 /// @@ -46,10 +42,8 @@ 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. - /// 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; + public OrderBookOptions(string name, bool sequencesAreConsecutive) + { OrderBookName = name; SequenceNumbersAreConsecutive = sequencesAreConsecutive; } diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs index 2e5f2dc..d942ed9 100644 --- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs +++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs @@ -72,16 +72,14 @@ namespace CryptoExchange.Net.OrderBook /// public event Action OnStatusChange; /// - /// 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 + /// Event when orderbook was updated. Be careful! It can generate a lot of events at high-liquidity markets /// 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 /// @@ -149,7 +147,6 @@ namespace CryptoExchange.Net.OrderBook id = options.OrderBookName; processBuffer = new List(); sequencesAreConsecutive = options.SequenceNumbersAreConsecutive; - updateEventInterval = options.UpdateEventTimeout; Symbol = symbol; Status = OrderBookStatus.Disconnected; @@ -272,11 +269,7 @@ namespace CryptoExchange.Net.OrderBook CheckProcessBuffer(); bookSet = true; LastOrderBookUpdate = DateTime.UtcNow; - if ((LastOrderBookUpdate - LastOrderBookUpdateEventTrigger).TotalMilliseconds >= updateEventInterval) - { - OnOrderBookUpdate?.Invoke(); - LastOrderBookUpdateEventTrigger = DateTime.UtcNow; - } + OnOrderBookUpdate?.Invoke(); log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks"); } } @@ -318,11 +311,7 @@ namespace CryptoExchange.Net.OrderBook LastSequenceNumber = lastSequenceNumber; CheckProcessBuffer(); LastOrderBookUpdate = DateTime.UtcNow; - if ((LastOrderBookUpdate - LastOrderBookUpdateEventTrigger).TotalMilliseconds >= updateEventInterval) - { - OnOrderBookUpdate?.Invoke(); - LastOrderBookUpdateEventTrigger = DateTime.UtcNow; - } + OnOrderBookUpdate?.Invoke(); log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} update: {entries.Count} entries processed"); } }