private async void OnOrderBook(Binance.WsDepth depth) { try { await _lock.WaitAsync(); if (orderBook2.IsEmpty) { var result = await client.GetDepthAsync(depth.symbol, 1000); if (result.Success) { orderBook2.AddRange(Convert(result.Data, si)); lastUpdateId = result.Data.lastUpdateId; //Debug.Print($"{lastUpdateId}"); } } if (depth.finalUpdateId <= lastUpdateId) { //Debug.Print($"{depth.firstUpdateId} : {depth.finalUpdateId} dropped"); return; } if (depth.firstUpdateId <= lastUpdateId + 1 && depth.finalUpdateId >= lastUpdateId + 1) { var sw = Stopwatch.StartNew(); var bookUpdates = Convert(depth, si); foreach (var e in bookUpdates) { if (e.Quantity == decimal.Zero) { orderBook2.RemoveAll(orderBook2.Where(x => x.Price == e.Price).ToList()); } else { // add or update var item = orderBook2.LastOrDefault(x => e.Side == x.Side && e.Price <= x.Price); if (item != null) { if (e.Price == item.Price) { item.Quantity = e.Quantity; } else { var idx = orderBook2.IndexOf(item); orderBook2.Insert(idx + 1, e); //Debug.Print($"Inserting {e.Price} after {item.Price}"); } } else { if (e.Side == TradeSide.Sell) { orderBook2.Insert(0, e); } else { item = orderBook2.FirstOrDefault(x => x.Side == e.Side); var idx = orderBook2.IndexOf(item); orderBook2.Insert(idx, e); //Debug.Print($"Inserting {e.Price} before {item.Price}"); } } } } { // remove items which are out of size var item = orderBook2.FirstOrDefault(x => x.Side == TradeSide.Buy); var idx = orderBook2.IndexOf(item); if (false) { var count = (int)cmbBookSize.SelectedValue; while (idx + count < orderBook2.Count) { orderBook2.Remove(orderBook2.Last()); } while (idx-- > count) { orderBook2.Remove(orderBook2.First()); } } // calculate agg. totals decimal aggTotal = decimal.Zero; for (var i = idx; i < orderBook2.Count; ++i) { aggTotal += orderBook2[i].Total; orderBook2[i].TotalCumulative = aggTotal; } aggTotal = 0; for (var i = idx - 1; i >= 0; --i) { aggTotal += orderBook2[i].Total; orderBook2[i].TotalCumulative = aggTotal; } } lastUpdateId = depth.finalUpdateId; Debug.Print($"Update {lastUpdateId} took {sw.ElapsedMilliseconds}ms."); //if (true) //{ // // remove items which are out of size // var item = orderBook.FirstOrDefault(x => x.Side == TradeSide.Buy); // var idx = orderBook.IndexOf(item); // var count = (int)cmbBookSize.SelectedValue; // var askCount = idx > count ? count : idx; // var bidCount = count; // orderBookCopy.Clear(); // orderBookCopy.AddRange(orderBook.Skip(idx - askCount).Take(askCount + bidCount)); //} } else { //Debug.Print($"{depth.firstUpdateId} : {depth.finalUpdateId} dropped"); } } finally { _lock.Release(); } }