1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-08 00:16:27 +00:00

added timeout for triggering order book updating event

This commit is contained in:
msg_kurt 2019-09-04 16:49:32 +03:00
parent c01bcc87b1
commit 43c17bae64
2 changed files with 43 additions and 18 deletions

View File

@ -26,8 +26,12 @@ namespace CryptoExchange.Net.Objects
/// <summary> /// <summary>
/// Base for order book options /// Base for order book options
/// </summary> /// </summary>
public class OrderBookOptions: BaseOptions public class OrderBookOptions : BaseOptions
{ {
/// <summary>
/// Update event raising timeout in milliseconds (to limit it at high-liquidity order books)
/// </summary>
public int UpdateEventTimeout { get; }
/// <summary> /// <summary>
/// The name of the order book implementation /// The name of the order book implementation
/// </summary> /// </summary>
@ -42,8 +46,10 @@ namespace CryptoExchange.Net.Objects
/// </summary> /// </summary>
/// <param name="name">The name of the order book implementation</param> /// <param name="name">The name of the order book implementation</param>
/// <param name="sequencesAreConsecutive">Whether each update should have a consecutive id number. Used to identify and reconnect when numbers are skipped.</param> /// <param name="sequencesAreConsecutive">Whether each update should have a consecutive id number. Used to identify and reconnect when numbers are skipped.</param>
public OrderBookOptions(string name, bool sequencesAreConsecutive) /// <param name="updateInterval">Update event raising timeout in milliseconds (to limit it at high-liquidity order books)</param>
public OrderBookOptions(string name, bool sequencesAreConsecutive, int? updateInterval)
{ {
UpdateEventTimeout = updateInterval ?? 1000;
OrderBookName = name; OrderBookName = name;
SequenceNumbersAreConsecutive = sequencesAreConsecutive; SequenceNumbersAreConsecutive = sequencesAreConsecutive;
} }
@ -52,7 +58,7 @@ namespace CryptoExchange.Net.Objects
/// <summary> /// <summary>
/// Base client options /// Base client options
/// </summary> /// </summary>
public class ClientOptions: BaseOptions public class ClientOptions : BaseOptions
{ {
/// <summary> /// <summary>
@ -74,7 +80,7 @@ namespace CryptoExchange.Net.Objects
/// <summary> /// <summary>
/// Base for rest client options /// Base for rest client options
/// </summary> /// </summary>
public class RestClientOptions: ClientOptions public class RestClientOptions : ClientOptions
{ {
/// <summary> /// <summary>
/// List of rate limiters to use /// List of rate limiters to use
@ -96,7 +102,7 @@ namespace CryptoExchange.Net.Objects
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
public T Copy<T>() where T:RestClientOptions, new() public T Copy<T>() where T : RestClientOptions, new()
{ {
var copy = new T var copy = new T
{ {
@ -119,7 +125,7 @@ namespace CryptoExchange.Net.Objects
/// <summary> /// <summary>
/// Base for socket client options /// Base for socket client options
/// </summary> /// </summary>
public class SocketClientOptions: ClientOptions public class SocketClientOptions : ClientOptions
{ {
/// <summary> /// <summary>
/// Whether or not the socket should automatically reconnect when losing connection /// Whether or not the socket should automatically reconnect when losing connection

View File

@ -13,7 +13,7 @@ namespace CryptoExchange.Net.OrderBook
/// <summary> /// <summary>
/// Base for order book implementations /// Base for order book implementations
/// </summary> /// </summary>
public abstract class SymbolOrderBook: IDisposable public abstract class SymbolOrderBook : IDisposable
{ {
/// <summary> /// <summary>
/// The process buffer, used while syncing /// The process buffer, used while syncing
@ -27,6 +27,7 @@ namespace CryptoExchange.Net.OrderBook
/// <summary> /// <summary>
/// The bid list /// The bid list
/// </summary> /// </summary>
protected SortedList<decimal, OrderBookEntry> bids; protected SortedList<decimal, OrderBookEntry> bids;
private OrderBookStatus status; private OrderBookStatus status;
private UpdateSubscription subscription; private UpdateSubscription subscription;
@ -71,10 +72,17 @@ namespace CryptoExchange.Net.OrderBook
/// </summary> /// </summary>
public event Action<OrderBookStatus, OrderBookStatus> OnStatusChange; public event Action<OrderBookStatus, OrderBookStatus> OnStatusChange;
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
public event Action OnOrderBookUpdate; public event Action OnOrderBookUpdate;
/// <summary> /// <summary>
/// Should be useful for low-liquidity order-books to monitor market activity
/// </summary>
public DateTime LastOrderBookUpdate;
private DateTime LastOrderBookUpdateEventTrigger;
private readonly int updateEventInterval;
/// <summary>
/// The number of asks in the book /// The number of asks in the book
/// </summary> /// </summary>
public int AskCount { get; private set; } public int AskCount { get; private set; }
@ -141,6 +149,7 @@ namespace CryptoExchange.Net.OrderBook
id = options.OrderBookName; id = options.OrderBookName;
processBuffer = new List<ProcessBufferEntry>(); processBuffer = new List<ProcessBufferEntry>();
sequencesAreConsecutive = options.SequenceNumbersAreConsecutive; sequencesAreConsecutive = options.SequenceNumbersAreConsecutive;
updateEventInterval = options.UpdateEventTimeout;
Symbol = symbol; Symbol = symbol;
Status = OrderBookStatus.Disconnected; Status = OrderBookStatus.Disconnected;
@ -166,7 +175,7 @@ namespace CryptoExchange.Net.OrderBook
{ {
Status = OrderBookStatus.Connecting; Status = OrderBookStatus.Connecting;
var startResult = await DoStart().ConfigureAwait(false); var startResult = await DoStart().ConfigureAwait(false);
if(!startResult.Success) if (!startResult.Success)
return new CallResult<bool>(false, startResult.Error); return new CallResult<bool>(false, startResult.Error);
subscription = startResult.Data; subscription = startResult.Data;
@ -249,7 +258,7 @@ namespace CryptoExchange.Net.OrderBook
return; return;
asks.Clear(); asks.Clear();
foreach(var ask in askList) foreach (var ask in askList)
asks.Add(ask.Price, new OrderBookEntry(ask.Price, ask.Quantity)); asks.Add(ask.Price, new OrderBookEntry(ask.Price, ask.Quantity));
bids.Clear(); bids.Clear();
foreach (var bid in bidList) foreach (var bid in bidList)
@ -262,7 +271,12 @@ namespace CryptoExchange.Net.OrderBook
CheckProcessBuffer(); CheckProcessBuffer();
bookSet = true; bookSet = true;
LastOrderBookUpdate = DateTime.UtcNow;
if ((LastOrderBookUpdate - LastOrderBookUpdateEventTrigger).TotalMilliseconds >= updateEventInterval)
{
OnOrderBookUpdate?.Invoke(); OnOrderBookUpdate?.Invoke();
LastOrderBookUpdateEventTrigger = DateTime.UtcNow;
}
log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks"); log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks");
} }
} }
@ -299,11 +313,16 @@ namespace CryptoExchange.Net.OrderBook
} }
else else
{ {
foreach(var entry in entries) foreach (var entry in entries)
ProcessUpdate(entry.Type, entry.Entry); ProcessUpdate(entry.Type, entry.Entry);
LastSequenceNumber = lastSequenceNumber; LastSequenceNumber = lastSequenceNumber;
CheckProcessBuffer(); CheckProcessBuffer();
LastOrderBookUpdate = DateTime.UtcNow;
if ((LastOrderBookUpdate - LastOrderBookUpdateEventTrigger).TotalMilliseconds >= updateEventInterval)
{
OnOrderBookUpdate?.Invoke(); OnOrderBookUpdate?.Invoke();
LastOrderBookUpdateEventTrigger = DateTime.UtcNow;
}
log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} update: {entries.Count} entries processed"); 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()) foreach (var bufferEntry in processBuffer.OrderBy(b => b.FirstSequence).ToList())
{ {
if(bufferEntry.LastSequence < LastSequenceNumber) if (bufferEntry.LastSequence < LastSequenceNumber)
{ {
processBuffer.Remove(bufferEntry); processBuffer.Remove(bufferEntry);
continue; continue;
@ -325,7 +344,7 @@ namespace CryptoExchange.Net.OrderBook
if (bufferEntry.FirstSequence > LastSequenceNumber + 1) if (bufferEntry.FirstSequence > LastSequenceNumber + 1)
break; break;
foreach(var entry in bufferEntry.Entries) foreach (var entry in bufferEntry.Entries)
ProcessUpdate(entry.Type, entry.Entry); ProcessUpdate(entry.Type, entry.Entry);
processBuffer.Remove(bufferEntry); processBuffer.Remove(bufferEntry);
LastSequenceNumber = bufferEntry.LastSequence; LastSequenceNumber = bufferEntry.LastSequence;