public Task UpdateAsync(string assetPair)
        {
            string exchangeName = _settingsService.GetExchangeName();

            AssetPairModel assetPairSettings = _marketInstrumentService.GetAssetPair(assetPair, exchangeName);

            if (assetPairSettings == null)
            {
                throw new FailedOperationException("Asset pair not found");
            }

            IReadOnlyList <ExternalOrderBook> externalOrderBooks = _externalOrderBookService.GetByAssetPair(assetPair);

            var sellLevels = new Dictionary <decimal, decimal>();

            decimal ask = decimal.MaxValue;

            foreach (ExternalOrderBook externalOrderBook in externalOrderBooks)
            {
                foreach (ExternalOrderBookLevel priceLevel in externalOrderBook.SellLevels)
                {
                    decimal price = priceLevel.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy, true);

                    if (!sellLevels.ContainsKey(price))
                    {
                        sellLevels[price] = 0;
                    }

                    sellLevels[price] += priceLevel.Volume;

                    if (ask > price)
                    {
                        ask = price;
                    }
                }
            }

            var buyLevels = new Dictionary <decimal, decimal>();

            decimal bid = decimal.MinValue;

            foreach (ExternalOrderBook externalOrderBook in externalOrderBooks)
            {
                foreach (ExternalOrderBookLevel priceLevel in externalOrderBook.BuyLevels)
                {
                    decimal price = priceLevel.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy);

                    if (!buyLevels.ContainsKey(price))
                    {
                        buyLevels[price] = 0;
                    }

                    buyLevels[price] += priceLevel.Volume;

                    if (bid < price)
                    {
                        bid = price;
                    }
                }
            }

            if (ask <= bid)
            {
                decimal mid = Math.Round((ask + bid) / 2, assetPairSettings.PriceAccuracy);

                var basisPoint = (decimal)Math.Pow(.1, assetPairSettings.PriceAccuracy);

                ask = mid + basisPoint;

                bid = mid - basisPoint;
            }

            var sellOrderBookLevels = new List <OrderBookLevel>();

            var bestSellLevel = new OrderBookLevel {
                Price = ask
            };

            foreach (var(price, volume) in sellLevels)
            {
                if (price <= ask)
                {
                    bestSellLevel.Volume += volume;
                }
                else
                {
                    sellOrderBookLevels.Add(new OrderBookLevel {
                        Price = price, Volume = volume
                    });
                }
            }

            if (bestSellLevel.Volume > 0)
            {
                sellOrderBookLevels.Add(bestSellLevel);
            }

            var buyOrderBookLevels = new List <OrderBookLevel>();

            var bestBuyLevel = new OrderBookLevel {
                Price = bid
            };

            foreach (var(price, volume) in buyLevels)
            {
                if (price >= bid)
                {
                    bestBuyLevel.Volume += volume;
                }
                else
                {
                    buyOrderBookLevels.Add(new OrderBookLevel {
                        Price = price, Volume = volume
                    });
                }
            }

            if (bestBuyLevel.Volume > 0)
            {
                buyOrderBookLevels.Add(bestBuyLevel);
            }

            var internalOrderBook = new InternalOrderBook
            {
                AssetPair  = assetPairSettings.Name,
                Timestamp  = DateTime.UtcNow,
                SellLevels = sellOrderBookLevels
                             .OrderBy(o => o.Price)
                             .ToList(),
                BuyLevels = buyOrderBookLevels
                            .OrderByDescending(o => o.Price)
                            .ToList()
            };

            _orderBooks.AddOrUpdate(assetPair, internalOrderBook, (key, value) => internalOrderBook);

            return(Task.CompletedTask);
        }
Esempio n. 2
0
        public Task UpdateAsync(string assetPair)
        {
            string exchangeName = _settingsService.GetExchangeName();

            AssetPairModel assetPairSettings = _marketInstrumentService.GetAssetPair(assetPair, exchangeName);

            if (assetPairSettings == null)
            {
                throw new FailedOperationException("Asset pair not found");
            }

            IReadOnlyList <ExternalOrderBook> externalOrderBooks = _externalOrderBookService.GetByAssetPair(assetPair);

            var sellLevels = new Dictionary <decimal, Dictionary <string, ExternalOrderBookLevel> >();

            foreach (ExternalOrderBook externalOrderBook in externalOrderBooks)
            {
                foreach (ExternalOrderBookLevel priceLevel in externalOrderBook.SellLevels)
                {
                    decimal price = priceLevel.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy, true);

                    if (!sellLevels.ContainsKey(price))
                    {
                        sellLevels[price] = new Dictionary <string, ExternalOrderBookLevel>();
                    }

                    sellLevels[price][externalOrderBook.Exchange] = priceLevel;
                }
            }

            var buyLevels = new Dictionary <decimal, Dictionary <string, ExternalOrderBookLevel> >();

            foreach (ExternalOrderBook externalOrderBook in externalOrderBooks)
            {
                foreach (ExternalOrderBookLevel priceLevel in externalOrderBook.BuyLevels)
                {
                    decimal price = priceLevel.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy);

                    if (!buyLevels.ContainsKey(price))
                    {
                        buyLevels[price] = new Dictionary <string, ExternalOrderBookLevel>();
                    }

                    buyLevels[price][externalOrderBook.Exchange] = priceLevel;
                }
            }

            var aggregatedOrderBook = new AggregatedOrderBook
            {
                AssetPair  = assetPair,
                Timestamp  = DateTime.UtcNow,
                SellLevels = sellLevels
                             .Select(priceLevel => new AggregatedOrderBookLevel
                {
                    Price           = priceLevel.Key,
                    Volume          = priceLevel.Value.Sum(exchangeVolume => exchangeVolume.Value.Volume),
                    ExchangeVolumes = priceLevel.Value
                                      .Select(o => new AggregatedOrderBookVolume(o.Key, o.Value.OriginalPrice, o.Value.Volume))
                                      .ToList()
                })
                             .OrderBy(o => o.Price)
                             .ToList(),
                BuyLevels = buyLevels
                            .Select(priceLevel => new AggregatedOrderBookLevel
                {
                    Price           = priceLevel.Key,
                    Volume          = priceLevel.Value.Sum(exchangeVolume => exchangeVolume.Value.Volume),
                    ExchangeVolumes = priceLevel.Value
                                      .Select(o => new AggregatedOrderBookVolume(o.Key, o.Value.OriginalPrice, o.Value.Volume))
                                      .ToList()
                })
                            .OrderByDescending(o => o.Price)
                            .ToList()
            };

            _orderBooks.AddOrUpdate(assetPair, aggregatedOrderBook, (key, value) => aggregatedOrderBook);

            return(Task.CompletedTask);
        }