private static void GetBidsAndAsks(Core.Model.OrderBook orderBook, int pricePrecision, int quantityPrecision,
                                           int listDisplayCount, int chartDisplayCount,
                                           out List <OrderBookPriceLevel> topAsks, out List <OrderBookPriceLevel> topBids,
                                           out List <OrderBookPriceLevel> chartAsks, out List <OrderBookPriceLevel> chartBids,
                                           out List <OrderBookPriceLevel> aggregatedAsks, out List <OrderBookPriceLevel> aggregatedBids,
                                           out decimal bidAskSpread)
        {
            var orderBookCount = chartDisplayCount > listDisplayCount ? chartDisplayCount : listDisplayCount;

            // Order by price: bids (DESC) and asks (ASC)
            var orderedAsks = orderBook.Asks.OrderBy(a => a.Price).ToList();
            var orderedBids = orderBook.Bids.OrderByDescending(b => b.Price).ToList();

            // The OrderBookCount is the greater of the OrderBookDisplayCount OrderBookChartDisplayCount.
            // Take the asks and bids for the OrderBookCount as new instances of type OrderBookPriceLevel
            // i.e. discard those that we are not interested in displaying on the screen.
            var asks = orderedAsks.Take(orderBookCount).Select(ask => new OrderBookPriceLevel
            {
                Price    = ask.Price.Trim(pricePrecision),
                Quantity = ask.Quantity.Trim(quantityPrecision)
            }).ToList();

            var bids = orderedBids.Take(orderBookCount).Select(bid => new OrderBookPriceLevel
            {
                Price    = bid.Price.Trim(pricePrecision),
                Quantity = bid.Quantity.Trim(quantityPrecision)
            }).ToList();

            var topAsk = asks.First();
            var topBid = bids.First();

            if (topAsk.Price != 0)
            {
                bidAskSpread = Math.Round(((topAsk.Price - topBid.Price) / topAsk.Price) * 100, 2, MidpointRounding.AwayFromZero);
            }
            else
            {
                bidAskSpread = 0.00m;
            }

            // Take the top bids and asks for the order book bid and ask lists and order descending.
            topAsks = asks.Take(listDisplayCount).Reverse().ToList();
            topBids = bids.Take(listDisplayCount).ToList();

            // Take the bid and aks to display in the the order book chart.
            chartAsks = asks.Take(chartDisplayCount).ToList();
            var tempbids = bids.Take(chartDisplayCount).ToList();

            chartBids = tempbids.Reverse <OrderBookPriceLevel>().ToList();

            // Create the aggregated bids and asks for the aggregated bid and ask chart.
            aggregatedAsks = GetAggregatedList(asks);
            var aggBids = GetAggregatedList(bids);

            aggregatedBids = aggBids.Reverse <OrderBookPriceLevel>().ToList();
        }
Exemple #2
0
        public Task <OrderBook> CreateLocalOrderBook(Symbol symbol, Core.Model.OrderBook orderBook, int listDisplayCount, int chartDisplayCount)
        {
            if (symbol == null)
            {
                throw new ArgumentNullException(nameof(symbol));
            }

            if (orderBook == null)
            {
                throw new ArgumentNullException(nameof(orderBook));
            }

            var tcs = new TaskCompletionSource <OrderBook>();

            try
            {
                List <OrderBookPriceLevel> topAsks;
                List <OrderBookPriceLevel> topBids;
                List <OrderBookPriceLevel> chartAsks;
                List <OrderBookPriceLevel> chartBids;
                List <OrderBookPriceLevel> aggregatedAsks;
                List <OrderBookPriceLevel> aggregatedBids;
                decimal bidAskSpread;

                GetBidsAndAsks(orderBook, symbol.PricePrecision, symbol.QuantityPrecision, listDisplayCount, chartDisplayCount,
                               out topAsks, out topBids, out chartAsks, out chartBids, out aggregatedAsks, out aggregatedBids, out bidAskSpread);

                var newOrderBook = new OrderBook
                {
                    LastUpdateId = orderBook.LastUpdateId,
                    Symbol       = orderBook.Symbol,
                    BaseSymbol   = symbol.BaseAsset.Symbol,
                    QuoteSymbol  = symbol.QuoteAsset.Symbol,
                    BidAskSpread = bidAskSpread
                };

                newOrderBook.TopAsks.AddRange(topAsks);
                newOrderBook.TopBids.AddRange(topBids);
                newOrderBook.ChartAsks.AddRange(new ChartValues <OrderBookPriceLevel>(chartAsks));
                newOrderBook.ChartBids.AddRange(new ChartValues <OrderBookPriceLevel>(chartBids));
                newOrderBook.ChartAggregatedAsks.AddRange(new ChartValues <OrderBookPriceLevel>(aggregatedAsks));
                newOrderBook.ChartAggregatedBids.AddRange(new ChartValues <OrderBookPriceLevel>(aggregatedBids));

                tcs.SetResult(newOrderBook);
            }
            catch (Exception ex)
            {
                tcs.SetException(ex);
            }

            return(tcs.Task);
        }
Exemple #3
0
        private static Core.Model.OrderBook NewOrderBook(OrderBook ob)
        {
            var orderBook = new Core.Model.OrderBook
            {
                Symbol       = ob.Symbol,
                Exchange     = Exchange.Binance,
                LastUpdateId = ob.LastUpdateId
            };

            orderBook.Asks = (from ask in ob.Asks select new Core.Model.OrderBookPriceLevel {
                Price = ask.Price, Quantity = ask.Quantity
            }).ToList();
            orderBook.Bids = (from bid in ob.Bids select new Core.Model.OrderBookPriceLevel {
                Price = bid.Price, Quantity = bid.Quantity
            }).ToList();

            return(orderBook);
        }
Exemple #4
0
        public void UpdateLocalOrderBook(OrderBook orderBook, Core.Model.OrderBook updateOrderBook,
                                         int pricePrecision, int quantityPrecision, int listDisplayCount, int chartDisplayCount)
        {
            if (updateOrderBook == null)
            {
                throw new ArgumentNullException(nameof(updateOrderBook));
            }

            if (orderBook == null)
            {
                throw new ArgumentNullException(nameof(orderBook));
            }

            orderBook.LastUpdateId = updateOrderBook.LastUpdateId;

            List <OrderBookPriceLevel> topAsks;
            List <OrderBookPriceLevel> topBids;
            List <OrderBookPriceLevel> chartAsks;
            List <OrderBookPriceLevel> chartBids;
            List <OrderBookPriceLevel> aggregatedAsks;
            List <OrderBookPriceLevel> aggregatedBids;
            decimal bidAskSpread;

            GetBidsAndAsks(updateOrderBook, pricePrecision, quantityPrecision, listDisplayCount, chartDisplayCount,
                           out topAsks, out topBids, out chartAsks, out chartBids, out aggregatedAsks, out aggregatedBids, out bidAskSpread);

            // Create new instances of the top
            // bids and asks, reversing the asks
            orderBook.TopAsks.Clear();
            orderBook.TopBids.Clear();
            orderBook.TopAsks.AddRange(topAsks);
            orderBook.TopBids.AddRange(topBids);
            orderBook.BidAskSpread = bidAskSpread;

            // Update the existing orderbook chart
            // bids and asks, reversing the bids.
            UpdateChartValues(orderBook.ChartAsks, chartAsks);
            UpdateChartValues(orderBook.ChartBids, chartBids);
            UpdateChartValues(orderBook.ChartAggregatedAsks, aggregatedAsks);
            UpdateChartValues(orderBook.ChartAggregatedBids, aggregatedBids);
        }
        internal async void UpdateOrderBook(Core.Model.OrderBook exchangeOrderBook)
        {
            if (symbolCancellationTokenSource.IsCancellationRequested)
            {
                return;
            }

            await orderBookSemaphoreSlim.WaitAsync(symbolCancellationTokenSource.Token);

            try
            {
                if (OrderBook == null)
                {
                    OrderBook = await orderBookHelper.CreateLocalOrderBook(Symbol, exchangeOrderBook, OrderBookDisplayCount, OrderBookChartDisplayCount);

                    if (IsLoadingOrderBook)
                    {
                        IsLoadingOrderBook = false;
                    }
                }
                else if (OrderBook.LastUpdateId >= exchangeOrderBook.LastUpdateId)
                {
                    // If the incoming order book is older than the local one ignore it.
                    return;
                }
                else
                {
                    orderBookHelper.UpdateLocalOrderBook(OrderBook, exchangeOrderBook,
                                                         symbol.PricePrecision, symbol.QuantityPrecision,
                                                         OrderBookDisplayCount, OrderBookChartDisplayCount);
                }
            }
            finally
            {
                orderBookSemaphoreSlim.Release();
            }
        }
        public async Task <OrderBook> CreateLocalOrderBook(Symbol symbol, Core.Model.OrderBook orderBook, int listDisplayCount, int chartDisplayCount)
        {
            if (symbol == null)
            {
                throw new ArgumentNullException(nameof(symbol));
            }

            if (orderBook == null)
            {
                throw new ArgumentNullException(nameof(orderBook));
            }

            Core.Model.OrderBook snapShot;

            using (var cancellationTokenSource = new CancellationTokenSource())
            {
                snapShot = await kucoinExchangeApi.GetOrderBookAsync(symbol.ExchangeSymbol, 100, cancellationTokenSource.Token).ConfigureAwait(false);
            }

            // Order by price: bids (ASC) and asks (ASC)
            // Discard those that we are not interested in displaying on the screen.
            var snapShotAsks = new List <Core.Model.OrderBookPriceLevel>(snapShot.Asks.OrderBy(a => a.Price).ToList());
            var snapShotBids = new List <Core.Model.OrderBookPriceLevel>(snapShot.Bids.OrderBy(b => b.Price).ToList());

            long latestSquence = snapShot.LastUpdateId;

            ReplayPriceLevels(snapShotAsks, orderBook.Asks, snapShot.LastUpdateId, ref latestSquence);
            ReplayPriceLevels(snapShotBids, orderBook.Bids, snapShot.LastUpdateId, ref latestSquence);

            var pricePrecision    = symbol.PricePrecision;
            var quantityPrecision = symbol.QuantityPrecision;

            var asks = snapShotAsks.Select(ask => new OrderBookPriceLevel
            {
                Price    = ask.Price.Trim(pricePrecision),
                Quantity = ask.Quantity.Trim(quantityPrecision)
            }).ToList();

            var bids = snapShotBids.Select(bid => new OrderBookPriceLevel
            {
                Price    = bid.Price.Trim(pricePrecision),
                Quantity = bid.Quantity.Trim(quantityPrecision)
            }).ToList();

            var topAsk = asks.First();
            var topBid = bids.First();

            decimal bidAskSpread;

            if (topAsk.Price != 0)
            {
                bidAskSpread = Math.Round(((topAsk.Price - topBid.Price) / topAsk.Price) * 100, 2, MidpointRounding.AwayFromZero);
            }
            else
            {
                bidAskSpread = 0.00m;
            }

            // Take the top bids and asks for the order book bid and ask lists and order descending.
            var topAsks = asks.Take(listDisplayCount).OrderByDescending(a => a.Price).ToList();
            var topBids = bids.OrderByDescending(b => b.Price).Take(listDisplayCount).ToList();

            var skipExcessBids = 0;

            if (bids.Count > chartDisplayCount)
            {
                skipExcessBids = bids.Count - chartDisplayCount;
            }

            // Take the bid and aks to display in the the order book chart.
            var chartAsks = asks.Take(chartDisplayCount).ToList();
            var chartBids = bids.Skip(skipExcessBids).ToList();

            // Create the aggregated bids and asks for the aggregated bid and ask chart.
            var aggregatedAsks = GetAggregatedAsks(chartAsks);
            var aggregatedBids = GetAggregatedBids(chartBids);

            var newOrderBook = new OrderBook
            {
                LastUpdateId = latestSquence,
                Symbol       = orderBook.Symbol,
                BaseSymbol   = symbol.BaseAsset.Symbol,
                QuoteSymbol  = symbol.QuoteAsset.Symbol,
                BidAskSpread = bidAskSpread
            };

            newOrderBook.Asks.AddRange(snapShotAsks);
            newOrderBook.Bids.AddRange(snapShotBids);
            newOrderBook.TopAsks.AddRange(topAsks);
            newOrderBook.TopBids.AddRange(topBids);
            newOrderBook.ChartAsks.AddRange(new ChartValues <OrderBookPriceLevel>(chartAsks));
            newOrderBook.ChartBids.AddRange(new ChartValues <OrderBookPriceLevel>(chartBids));
            newOrderBook.ChartAggregatedAsks.AddRange(new ChartValues <OrderBookPriceLevel>(aggregatedAsks));
            newOrderBook.ChartAggregatedBids.AddRange(new ChartValues <OrderBookPriceLevel>(aggregatedBids));

            return(newOrderBook);
        }
        public void UpdateLocalOrderBook(OrderBook orderBook, Core.Model.OrderBook updateOrderBook,
                                         int pricePrecision, int quantityPrecision, int listDisplayCount, int chartDisplayCount)
        {
            if (orderBook == null)
            {
                throw new ArgumentNullException(nameof(orderBook));
            }

            if (updateOrderBook == null)
            {
                throw new ArgumentNullException(nameof(updateOrderBook));
            }

            long latestSquence = orderBook.LastUpdateId;

            ReplayPriceLevels(orderBook.Asks, updateOrderBook.Asks, orderBook.LastUpdateId, ref latestSquence);
            ReplayPriceLevels(orderBook.Bids, updateOrderBook.Bids, orderBook.LastUpdateId, ref latestSquence);

            orderBook.LastUpdateId = latestSquence;

            var asks = orderBook.Asks.Select(ask => new OrderBookPriceLevel
            {
                Price    = ask.Price.Trim(pricePrecision),
                Quantity = ask.Quantity.Trim(quantityPrecision)
            }).ToList();

            var bids = orderBook.Bids.Select(bid => new OrderBookPriceLevel
            {
                Price    = bid.Price.Trim(pricePrecision),
                Quantity = bid.Quantity.Trim(quantityPrecision)
            }).ToList();

            var topAsk = asks.First();
            var topBid = bids.First();

            if (topAsk.Price != 0)
            {
                orderBook.BidAskSpread = Math.Round(((topAsk.Price - topBid.Price) / topAsk.Price), 2, MidpointRounding.AwayFromZero);
            }
            else
            {
                orderBook.BidAskSpread = 0.00m;
            }

            // Take the top bids and asks for the order book bid and ask lists and order descending.
            orderBook.TopAsks.Clear();
            orderBook.TopBids.Clear();
            orderBook.TopAsks.AddRange(asks.Take(listDisplayCount).OrderByDescending(a => a.Price).ToList());
            orderBook.TopBids.AddRange(bids.OrderByDescending(b => b.Price).Take(listDisplayCount).ToList());

            var skipExcessBids = 0;

            if (bids.Count > chartDisplayCount)
            {
                skipExcessBids = bids.Count - chartDisplayCount;
            }

            // Take the bid and aks to display in the the order book chart.
            var chartAsks = asks.Take(chartDisplayCount).ToList();
            var chartBids = bids.Skip(skipExcessBids).ToList();

            // Create the aggregated bids and asks for the aggregated bid and ask chart.
            var aggregatedAsks = GetAggregatedAsks(chartAsks);
            var aggregatedBids = GetAggregatedBids(chartBids);

            UpdateChartValues(orderBook.ChartAsks, chartAsks);
            UpdateChartValues(orderBook.ChartBids, chartBids);
            UpdateChartValues(orderBook.ChartAggregatedAsks, aggregatedAsks);
            UpdateChartValues(orderBook.ChartAggregatedBids, aggregatedBids);
        }