Пример #1
0
        public void Start()
        {
            var data = _writer.GetRowsAsync <OrderBookNoSql>().ToListAsync().GetAwaiter().GetResult();

            lock (_gate)
            {
                foreach (var book in data.GroupBy(e => e.PartitionKey))
                {
                    var(brokerId, symbol) = OrderBookNoSql.GetBrokerIdAndSymbol(book.Key);
                    var manager = new OrderBookManager(brokerId, symbol, _logger);
                    var price   = manager.SetState(book);

                    if (!_data.TryGetValue(brokerId, out var symbolManagers))
                    {
                        symbolManagers  = new Dictionary <string, OrderBookManager>();
                        _data[brokerId] = symbolManagers;
                    }

                    symbolManagers[symbol] = manager;

                    _logger.LogInformation("Book manager is inited. BrokerId: {brokerId}; Symbol:{symbol}; Count: {count}. Price: {ask} / {bid}", brokerId, symbol, book.Count(), price.Ask, price.Bid);
                }

                _isInit = true;
            }
        }
Пример #2
0
        public static double CalculateAveragePrice(
            OrderBookNoSql orderBook,
            ISpotInstrument instrument,
            IAsset fromAsset,
            IAsset toAsset,
            IAsset volumeAsset,
            double volume)
        {
            if (instrument.BaseAsset == fromAsset.Symbol && volumeAsset.Symbol == fromAsset.Symbol)
            {
                return((double)CalculateAveragePriceStraight(orderBook.BuyLevels.OrderByDescending(e => e.Price),
                                                             (decimal)volume, instrument.Accuracy));
            }
            if (instrument.BaseAsset == fromAsset.Symbol && volumeAsset.Symbol == toAsset.Symbol)
            {
                return((double)CalculateAveragePriceNotStraight(orderBook.BuyLevels.OrderByDescending(e => e.Price),
                                                                (decimal)volume, instrument.Accuracy));
            }
            if (instrument.BaseAsset == toAsset.Symbol && volumeAsset.Symbol == toAsset.Symbol)
            {
                return((double)CalculateAveragePriceStraight(orderBook.SellLevels.OrderBy(e => e.Price),
                                                             (decimal)volume, instrument.Accuracy));
            }
            if (instrument.BaseAsset == toAsset.Symbol && volumeAsset.Symbol == fromAsset.Symbol)
            {
                return((double)CalculateAveragePriceNotStraight(orderBook.SellLevels.OrderBy(e => e.Price),
                                                                (decimal)volume, instrument.Accuracy));
            }

            throw new Exception("CalculateAveragePrice cant calculate price and volume");
        }
        /// <summary>
        /// Register order and notify about best price update
        /// </summary>
        public BidAsk RegisterOrderUpdate(List <OrderBookOrder> updates, Dictionary <string, OrderBookNoSql> updateList, Dictionary <string, OrderBookNoSql> deleteList)
        {
            var priceUpdated = false;



            foreach (var order in updates.Where(e => e.IsActive))
            {
                var orderLevel = ConvertOrder(order);

                if (!_data.TryGetValue(order.OrderId, out var entity))
                {
                    entity = OrderBookNoSql.Create(order.BrokerId, order.Symbol, orderLevel, order.Side);
                    _data[order.OrderId] = entity;
                }

                entity.Level = orderLevel;

                updateList[entity.Level.OrderId] = entity;

                if (order.Side == OrderSide.Sell && (_ask == null || _ask?.Price > order.Price))
                {
                    _ask         = entity.Level;
                    priceUpdated = true;
                }

                if (order.Side == OrderSide.Buy && (_ask == null || _bid?.Price < order.Price))
                {
                    _bid         = entity.Level;
                    priceUpdated = true;
                }
            }

            foreach (var order in updates.Where(e => !e.IsActive))
            {
                var orderId = order.OrderId;

                var orderLevel = ConvertOrder(order);

                if (!_data.TryGetValue(order.OrderId, out var entity))
                {
                    entity = OrderBookNoSql.Create(order.BrokerId, order.Symbol, orderLevel, order.Side);
                }

                _data.Remove(orderId);
                deleteList[orderId] = entity;


                if (_ask?.OrderId == orderId)
                {
                    _ask         = null;
                    priceUpdated = true;
                }

                if (_bid?.OrderId == orderId)
                {
                    _bid         = null;
                    priceUpdated = true;
                }
            }

            if (priceUpdated && _ask == null)
            {
                _ask = _data.Values.Where(e => e.Side == OrderSide.Sell).OrderBy(e => e.Level.Price).FirstOrDefault()?.Level;
            }

            if (priceUpdated && _bid == null)
            {
                _bid = _data.Values.Where(e => e.Side == OrderSide.Buy).OrderByDescending(e => e.Level.Price).FirstOrDefault()?.Level;
            }

            if (_ask != null && _bid != null && _ask.Price <= _bid.Price)
            {
                _logger.LogError("NEGATIVE SPREAD {symbol}; Ask: {ask}; Bid: {bid}", Symbol, _ask.Price, _bid.Price);
                priceUpdated = false;
            }

            if (priceUpdated)
            {
                var updateTs = updates.Max(e => e.Timestamp);

                var bidAsk = new BidAsk
                {
                    Id = Symbol,
                    LiquidityProvider = BrokerId,
                    Ask                     = _ask != null?Convert.ToDouble(_ask.Price) : 0,
                                        Bid = _bid != null?Convert.ToDouble(_bid.Price) : 0,
                                                  DateTime = updateTs
                };

                return(bidAsk);
            }

            return(null);
        }
        public List <OrderBookLevelNoSql> GetOrderBook(string brokerId, string symbol)
        {
            var orderBook = _reader.Get(OrderBookNoSql.GeneratePartitionKey(brokerId, symbol));

            return(orderBook.Select(e => e.Level).ToList());
        }