diff --git a/CryptoExchange.Net/CryptoExchange.Net.xml b/CryptoExchange.Net/CryptoExchange.Net.xml index 800ba58..eb9478e 100644 --- a/CryptoExchange.Net/CryptoExchange.Net.xml +++ b/CryptoExchange.Net/CryptoExchange.Net.xml @@ -797,6 +797,11 @@ Event when order book was updated. Be careful! It can generate a lot of events at high-liquidity markets + + + Event when the BestBid or BestAsk changes ie a Pricing Tick + + Timestamp of the last update @@ -1769,6 +1774,11 @@ Event when the state changes + + + Event when the BestBid or BestAsk changes ie a Pricing Tick + + Event when order book was updated, containing the changed bids and asks. Be careful! It can generate a lot of events at high-liquidity markets @@ -2888,5 +2898,148 @@ + + + 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/Interfaces/ISymbolOrderBook.cs b/CryptoExchange.Net/Interfaces/ISymbolOrderBook.cs index 1571feb..1800689 100644 --- a/CryptoExchange.Net/Interfaces/ISymbolOrderBook.cs +++ b/CryptoExchange.Net/Interfaces/ISymbolOrderBook.cs @@ -33,6 +33,10 @@ namespace CryptoExchange.Net.Interfaces /// event Action, IEnumerable> OnOrderBookUpdate; /// + /// Event when the BestBid or BestAsk changes ie a Pricing Tick + /// + event Action OnPriceChanged; + /// /// Timestamp of the last update /// DateTime LastOrderBookUpdate { get; } diff --git a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs index cc890c8..b33512d 100644 --- a/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs +++ b/CryptoExchange.Net/OrderBook/SymbolOrderBook.cs @@ -51,7 +51,7 @@ namespace CryptoExchange.Net.OrderBook /// /// The status of the order book. Order book is up to date when the status is `Synced` /// - public OrderBookStatus Status + public OrderBookStatus Status { get => status; set @@ -79,6 +79,12 @@ namespace CryptoExchange.Net.OrderBook /// Event when the state changes /// public event Action? OnStatusChange; + + /// + /// Event when the BestBid or BestAsk changes ie a Pricing Tick + /// + public event Action? OnPriceChanged; + /// /// Event when order book was updated, containing the changed bids and asks. Be careful! It can generate a lot of events at high-liquidity markets /// @@ -112,7 +118,7 @@ namespace CryptoExchange.Net.OrderBook /// /// The list of bids /// - public IEnumerable Bids + public IEnumerable Bids { get { @@ -136,7 +142,7 @@ namespace CryptoExchange.Net.OrderBook /// /// The best ask currently in the order book /// - public ISymbolOrderBookEntry BestAsk + public ISymbolOrderBookEntry BestAsk { get { @@ -286,9 +292,16 @@ namespace CryptoExchange.Net.OrderBook log.Write(LogVerbosity.Debug, $"{Id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks. #{orderBookSequenceNumber}"); CheckProcessBuffer(); OnOrderBookUpdate?.Invoke(bidList, askList); + OnPriceChanged?.Invoke(BestBid, BestAsk); } } + private bool BestPricingUpdated(ISymbolOrderBookEntry prevBestBid, ISymbolOrderBookEntry prevBestAsk) + { + return BestBid.Price != prevBestBid.Price || BestBid.Quantity != prevBestBid.Quantity || + BestAsk.Price != prevBestAsk.Price || BestAsk.Quantity != prevBestAsk.Quantity; + } + /// /// Update the order book using a single id for an update /// @@ -315,8 +328,12 @@ namespace CryptoExchange.Net.OrderBook else { CheckProcessBuffer(); + var prevBestBid = BestBid; + var prevBestAsk = BestAsk; ProcessSingleSequenceUpdates(rangeUpdateId, bids, asks); OnOrderBookUpdate?.Invoke(bids, asks); + if (BestPricingUpdated(prevBestBid, prevBestAsk)) + OnPriceChanged?.Invoke(BestBid, BestAsk); } } } @@ -349,8 +366,12 @@ namespace CryptoExchange.Net.OrderBook else { CheckProcessBuffer(); + var prevBestBid = BestBid; + var prevBestAsk = BestAsk; ProcessRangeUpdates(firstUpdateId, lastUpdateId, bids, asks); OnOrderBookUpdate?.Invoke(bids, asks); + if (BestPricingUpdated(prevBestBid, prevBestAsk)) + OnPriceChanged?.Invoke(BestBid, BestAsk); } } } @@ -376,8 +397,13 @@ namespace CryptoExchange.Net.OrderBook else { CheckProcessBuffer(); + var prevBestBid = BestBid; + var prevBestAsk = BestAsk; ProcessUpdates(bids, asks); OnOrderBookUpdate?.Invoke(bids, asks); + if (BestPricingUpdated(prevBestBid, prevBestAsk)) + OnPriceChanged?.Invoke(BestBid, BestAsk); + } } } diff --git a/CryptoExchange.Net/RestClient.cs b/CryptoExchange.Net/RestClient.cs index 521f9b9..048cf6c 100644 --- a/CryptoExchange.Net/RestClient.cs +++ b/CryptoExchange.Net/RestClient.cs @@ -181,7 +181,7 @@ namespace CryptoExchange.Net } string? paramString = null; - if (parameters != null && method == HttpMethod.Post) + if (method == HttpMethod.Post) paramString = " with request body " + request.Content; log.Write(LogVerbosity.Debug, $"Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null? "": $" via proxy {apiProxy.Host}")}");