diff --git a/CryptoExchange.Net/CryptoExchange.Net.xml b/CryptoExchange.Net/CryptoExchange.Net.xml index b225bc8..d674aa2 100644 --- a/CryptoExchange.Net/CryptoExchange.Net.xml +++ b/CryptoExchange.Net/CryptoExchange.Net.xml @@ -1541,11 +1541,20 @@ Whether each update should have a consecutive id number. Used to identify and reconnect when numbers are skipped. - + + + Whether or not a level should be removed from the book when it's pushed out of scope of the limit. For example with a book of limit 10, + when a new bid is added which makes the total amount of bids 11, should the last bid entry be removed + + + 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. + Whether or not a level should be removed from the book when it's pushed out of scope of the limit. For example with a book of limit 10, + when a new bid is added which makes the total amount of bids 11, should the last bid entry be removed + Amount of levels for this order book @@ -1757,6 +1766,11 @@ If order book is set + + + The amount of levels for this book + + The status of the order book. Order book is up to date when the status is `Synced` @@ -2946,148 +2960,3 @@ -System.Diagnostics.CodeAnalysis.AllowNullAttribute"> - - Specifies that is allowed as an input even if the - corresponding type disallows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that is disallowed as an input even if the - corresponding type allows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that a method that will never return under any circumstance. - - - - - Initializes a new instance of the class. - - - - - Specifies that the method will not return if the associated - parameter is passed the specified value. - - - - - Gets the condition parameter value. - Code after the method is considered unreachable by diagnostics if the argument - to the associated parameter matches this value. - - - - - Initializes a new instance of the - class with the specified parameter value. - - - The condition parameter value. - Code after the method is considered unreachable by diagnostics if the argument - to the associated parameter matches this value. - - - - - Specifies that an output may be even if the - corresponding type disallows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that when a method returns , - the parameter may be even if the corresponding type disallows it. - - - - - Gets the return value condition. - If the method returns this value, the associated parameter may be . - - - - - Initializes the attribute with the specified return value condition. - - - The return value condition. - If the method returns this value, the associated parameter may be . - - - - - Specifies that an output is not even if the - corresponding type allows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that the output will be non- if the - named parameter is non-. - - - - - Gets the associated parameter name. - The output will be non- if the argument to the - parameter specified is non-. - - - - - Initializes the attribute with the associated parameter name. - - - The associated parameter name. - The output will be non- if the argument to the - parameter specified is non-. - - - - - Specifies that when a method returns , - the parameter will not be even if the corresponding type allows it. - - - - - Gets the return value condition. - If the method returns this value, the associated parameter will not be . - - - - - Initializes the attribute with the specified return value condition. - - - The return value condition. - If the method returns this value, the associated parameter will not be . - - - - diff --git a/CryptoExchange.Net/Objects/Options.cs b/CryptoExchange.Net/Objects/Options.cs index 18744ab..515494d 100644 --- a/CryptoExchange.Net/Objects/Options.cs +++ b/CryptoExchange.Net/Objects/Options.cs @@ -44,20 +44,30 @@ namespace CryptoExchange.Net.Objects /// public bool SequenceNumbersAreConsecutive { get; } + /// + /// Whether or not a level should be removed from the book when it's pushed out of scope of the limit. For example with a book of limit 10, + /// when a new bid is added which makes the total amount of bids 11, should the last bid entry be removed + /// + public bool StrictLevels { get; } + /// /// /// 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) + /// Whether or not a level should be removed from the book when it's pushed out of scope of the limit. For example with a book of limit 10, + /// when a new bid is added which makes the total amount of bids 11, should the last bid entry be removed + /// Amount of levels for this order book + public OrderBookOptions(string name, bool sequencesAreConsecutive, bool strictLevels) { OrderBookName = name; SequenceNumbersAreConsecutive = sequencesAreConsecutive; + StrictLevels = strictLevels; } /// public override string ToString() { - return $"{base.ToString()}, OrderBookName: {OrderBookName}, SequenceNumbersAreConsequtive: {SequenceNumbersAreConsecutive}"; + return $"{base.ToString()}, OrderBookName: {OrderBookName}, SequenceNumbersAreConsequtive: {SequenceNumbersAreConsecutive}, StrictLevels: {StrictLevels}"; } } diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs index 24adc47..b8674f5 100644 --- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs +++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs @@ -35,6 +35,7 @@ namespace CryptoExchange.Net.OrderBook private OrderBookStatus status; private UpdateSubscription? subscription; private readonly bool sequencesAreConsecutive; + private readonly bool strictLevels; private Task _processTask; private AutoResetEvent _queueEvent; @@ -54,6 +55,11 @@ namespace CryptoExchange.Net.OrderBook /// protected bool bookSet; + /// + /// The amount of levels for this book + /// + protected int? Levels { get; set; } = null; + /// /// The status of the order book. Order book is up to date when the status is `Synced` /// @@ -194,6 +200,7 @@ namespace CryptoExchange.Net.OrderBook _queueEvent = new AutoResetEvent(false); sequencesAreConsecutive = options.SequenceNumbersAreConsecutive; + strictLevels = options.StrictLevels; Symbol = symbol; Status = OrderBookStatus.Disconnected; @@ -236,6 +243,8 @@ namespace CryptoExchange.Net.OrderBook log.Write(LogVerbosity.Warning, $"{Id} order book {Symbol} connection lost"); Status = OrderBookStatus.Connecting; _queueEvent.Set(); + // Clear queue + while(_processQueue.TryDequeue(out _)) processBuffer.Clear(); bookSet = false; DoReset(); @@ -328,6 +337,14 @@ namespace CryptoExchange.Net.OrderBook CheckProcessBuffer(); var (prevBestBid, prevBestAsk) = BestOffers; ProcessRangeUpdates(item.StartUpdateId, item.EndUpdateId, item.Bids, item.Asks); + + if (asks.First().Key < bids.First().Key) + { + log.Write(LogVerbosity.Warning, $"{Id} order book {Symbol} detected out of sync order book. Resyncing"); + _ = subscription?.Reconnect(); + return; + } + OnOrderBookUpdate?.Invoke(item.Bids, item.Asks); CheckBestOffersChanged(prevBestBid, prevBestAsk); } @@ -429,6 +446,21 @@ namespace CryptoExchange.Net.OrderBook foreach (var entry in asks) ProcessUpdate(LastSequenceNumber + 1, OrderBookEntryType.Ask, entry); + if (Levels.HasValue && strictLevels) + { + while (this.bids.Count() > Levels.Value) + { + BidCount--; + this.bids.Remove(this.bids.Last().Key); + } + + while (this.asks.Count() > Levels.Value) + { + AskCount--; + this.asks.Remove(this.asks.Last().Key); + } + } + LastSequenceNumber = lastUpdateId; log.Write(LogVerbosity.Debug, $"{Id} order book {Symbol} update processed #{firstUpdateId}-{lastUpdateId}"); }