/// <summary>
        /// Updates or inserts a bid price level in the order book
        /// </summary>
        /// <param name="price">The bid price level to be inserted or updated</param>
        /// <param name="size">The new size at the bid price level</param>
        public void UpdateBidRow(decimal price, decimal size)
        {
            lock (_locker)
            {
                _bids[price] = size;
            }

            if (BestBidPrice == 0 || price >= BestBidPrice)
            {
                BestBidPrice = price;
                BestBidSize  = size;

                BestBidAskUpdated?.Invoke(this, new BestBidAskUpdatedEventArgs(_symbol, BestBidPrice, BestBidSize, BestAskPrice, BestAskSize));
            }
        }
        /// <summary>
        /// Updates or inserts an ask price level in the order book
        /// </summary>
        /// <param name="price">The ask price level to be inserted or updated</param>
        /// <param name="size">The new size at the ask price level</param>
        public void UpdateAskRow(decimal price, decimal size)
        {
            lock (_locker)
            {
                Asks[price] = size;

                if (_bestAskPrice == 0 || price <= _bestAskPrice)
                {
                    _bestAskPrice = price;
                    _bestAskSize  = size;

                    BestBidAskUpdated?.Invoke(this, new BestBidAskUpdatedEventArgs(_symbol, _bestBidPrice, _bestBidSize, _bestAskPrice, _bestAskSize));
                }
            }
        }
        /// <summary>
        /// Removes an ask price level from the order book
        /// </summary>
        /// <param name="price">The ask price level to be removed</param>
        public void RemoveAskRow(decimal price)
        {
            lock (_locker)
            {
                Asks.Remove(price);

                if (price == _bestAskPrice)
                {
                    var priceLevel = Asks.FirstOrDefault();
                    _bestAskPrice = priceLevel.Key;
                    _bestAskSize  = priceLevel.Value;

                    BestBidAskUpdated?.Invoke(this, new BestBidAskUpdatedEventArgs(_symbol, _bestBidPrice, _bestBidSize, _bestAskPrice, _bestAskSize));
                }
            }
        }
        /// <summary>
        /// Removes an ask price level from the order book
        /// </summary>
        /// <param name="price">The ask price level to be removed</param>
        public void RemoveAskRow(decimal price)
        {
            lock (_locker)
            {
                _asks.Remove(price);
            }

            if (price == BestAskPrice)
            {
                lock (_locker)
                {
                    BestAskPrice = _asks.Keys.FirstOrDefault();
                    BestAskSize  = BestAskPrice > 0 ? _asks[BestAskPrice] : 0;
                }

                BestBidAskUpdated?.Invoke(this, new BestBidAskUpdatedEventArgs(_symbol, BestBidPrice, BestBidSize, BestAskPrice, BestAskSize));
            }
        }