コード例 #1
0
        /// <summary>
        ///     Adds an order for the given contract and market side with the given properties
        /// </summary>
        /// <returns>The added order</returns>
        public IOrder AddOrder(long orderID,
                               Contract contract,
                               OrderType orderType,
                               MarketSide marketSide,
                               decimal price,
                               decimal quantity,
                               string clOrdID,
                               TradingAccount account)
        {
            var order = new Order(orderID,
                                  orderType,
                                  contract,
                                  marketSide,
                                  price,
                                  quantity,
                                  clOrdID,
                                  account);

            var stack = _market.GetOrCreate(
                contract,
                () =>
                    {
                        var os = OrderStackFactory.CreateStandardSortedStack(_orderMatcher);
                        os.OrdersMatched += OnOrdersMatched;
                        return os;
                    });
            stack.AddOrder(order);
            return order;
        }
コード例 #2
0
        public Message CreateNewOrderSingleMessage(string symbol,
                                                   MarketSide marketSide,
                                                   string clOrdID,
                                                   TradingAccount account,
                                                   decimal price,
                                                   decimal quantity,
                                                   OrderType orderType,
                                                   string execID)
        {
            var fOrdType = TranslateFixFields.Translate(orderType);
            var fSide = TranslateFixFields.Translate(marketSide);
            var fSymbol = new Symbol(symbol);
            var fTransactTime = new TransactTime(DateTime.Now);
            var fClOrdID = new ClOrdID(clOrdID);

            var nos = new NewOrderSingle(fClOrdID,
                                         fSymbol,
                                         fSide,
                                         fTransactTime,
                                         fOrdType)
            {
                OrderQty = new OrderQty(quantity),
                TimeInForce = new TimeInForce(TimeInForce.GOOD_TILL_CANCEL)
            };

            if (orderType == OrderType.Limit)
                nos.Price = new Price(price);

            return nos;
        }
コード例 #3
0
ファイル: IcebergOrder.cs プロジェクト: naziway/testtask
        public IcebergOrder(IServerFacade serverFacade,
                            string symbol,
                            string clOrdID,
                            MarketSide side,
                            decimal totalQuantity,
                            decimal clipSize,
                            decimal initialPrice,
                            decimal priceDelta)
        {
            if (totalQuantity <= 0)
                throw new ApplicationException(
                    "Iceberg Order must have a quantity greater than zero");

            if (clipSize > totalQuantity)
                throw new ApplicationException(
                    "Iceberg Order total quantity must be greater or equal to the clip size");

            Symbol = symbol;
            ClOrdID = clOrdID;
            Side = side;
            TotalQuantity = totalQuantity;
            ClipSize = clipSize;
            InitialPrice = initialPrice;
            PriceDelta = priceDelta;
            State = ActivationState.Suspended;

            _serverFacade = serverFacade;
            RemainingQuantity = totalQuantity;
            CurrentPrice = InitialPrice;
            CurrentQuantity = clipSize;
        }
コード例 #4
0
ファイル: OrderMediator.cs プロジェクト: naziway/testtask
        /// <summary>
        /// Adds an order to the system with the given properties
        /// </summary>
        /// <param name="sessionID">The FIX Session ID</param>
        /// <param name="orderType">
        /// The type of order, currently only Limit orders are supported
        /// </param>
        /// <param name="symbol">The symbol for the order</param>
        /// <param name="marketSide">The side of the market for the order</param>
        /// <param name="clOrdID">The FIX ClOrdID for the order, set by the client</param>
        /// <param name="account">The trading account associated with the order</param>
        /// <param name="quantity">The quantity of the order</param>
        /// <param name="price">The price of the order, may be null for market orders</param>
        /// <returns>The new order after it has been added</returns>
        /// <exception cref="FixATServerException">If the order is rejected</exception>
        public IOrder AddOrder(FixSessionID sessionID,
                               OrderType orderType,
                               string symbol,
                               MarketSide marketSide,
                               string clOrdID,
                               TradingAccount account,
                               decimal quantity,
                               decimal? price = null)
        {
            // A more complete system would look the contract up in a contract store
            var contract = new Contract(symbol);

            // TODO Replace this with a better mechanism (esp if more order types are supported)
            decimal orderPrice;
            switch (orderType)
            {
                case OrderType.Limit:
                    {
                        if (!price.HasValue)
                            throw new FixATServerException("Limit order must specify a price");
                        orderPrice = price.Value;
                        break;
                    }

                    // Uncomment this if and when market orders are supported
                    //case OrderType.Market:
                    //    {
                    //        if (price.HasValue)
                    //            throw new FixATServerException(
                    //                "Market order should not have a specified price");

                    //        orderPrice = GetMarketPrice(contract, marketSide);
                    //        break;
                    //    }

                default:
                    throw new FixATServerException(
                        string.Format("Order Type {0} not supported", orderType));
            }

            if (OrderWouldLeadToACrossedMarket(marketSide, contract, orderPrice))
                throw new FixATServerException("Order would lead to a crossed market");

            var order = _orderRepository.AddOrder(CreateOrderID(),
                                                  contract,
                                                  orderType,
                                                  marketSide,
                                                  orderPrice,
                                                  quantity,
                                                  clOrdID,
                                                  account);

            _orderOwners[order.ID] = sessionID;

            return order;
        }
コード例 #5
0
ファイル: OrderBook.xaml.cs プロジェクト: naziway/testtask
        private bool CanTradeOrder(object o, MarketSide side)
        {
            var vm = o as OrderBookViewModel;
            var selectedOrderRow = LvOrders.SelectedItem;
            var osr = selectedOrderRow as OrderBookViewModel.OrderStackRow;
            if (vm == null || osr == null) return false;

            return !string.IsNullOrWhiteSpace(
                side == MarketSide.Bid ? osr.BidClOrdID : osr.AskClOrdID);
        }
コード例 #6
0
ファイル: OrderBook.xaml.cs プロジェクト: naziway/testtask
        private void TradeOrder(object o, MarketSide side)
        {
            var vm = o as OrderBookViewModel;
            var selectedOrderRow = LvOrders.SelectedItem;
            var osr = selectedOrderRow as OrderBookViewModel.OrderStackRow;
            if (vm == null || osr == null) return;

            if (side == MarketSide.Bid)
                vm.BuyOrder(osr);
            else
                vm.SellOrder(osr);
        }
コード例 #7
0
ファイル: FixServerFacade.cs プロジェクト: naziway/testtask
 public bool CancelOrder(string symbol,
                           string clOrdID,
                           MarketSide side,
                           string orderID)
 {
     var msg =
         _fixMessageGenerator.CreateOrderCancelMessage(symbol,
                                                       clOrdID,
                                                       GenerateOrderCancelClOrdID(clOrdID),
                                                       side,
                                                       orderID);
     return _app.Send(msg);
 }
コード例 #8
0
 public void CreateIcebergOrder(string symbol,
                                string clOrdID,
                                MarketSide side,
                                decimal totalQuantity,
                                decimal clipSize,
                                decimal initialPrice,
                                decimal priceDelta)
 {
     _orderMediator.AddIcebergOrder(symbol,
                                    clOrdID,
                                    side,
                                    totalQuantity,
                                    clipSize,
                                    initialPrice,
                                    priceDelta);
 }
コード例 #9
0
ファイル: Order.cs プロジェクト: naziway/testtask
 public Order(long id,
              OrderType orderType,
              Contract contract,
              MarketSide marketSide,
              decimal price,
              decimal quantity,
              string clOrdID,
              TradingAccount tradingAccount)
 {
     ID = id;
     OrderType = orderType;
     Contract = contract;
     MarketSide = marketSide;
     Price = price;
     Quantity = quantity;
     LastUpdateTime = DateTime.UtcNow;
     ClOrdID = clOrdID;
     Account = tradingAccount;
     OriginalQuantity = quantity;
 }
コード例 #10
0
ファイル: ATOrderMediator.cs プロジェクト: naziway/testtask
        public void AddIcebergOrder(string symbol,
                                    string clOrdID,
                                    MarketSide side,
                                    decimal totalQuantity,
                                    decimal clipSize,
                                    decimal initialPrice,
                                    decimal priceDelta)
        {
            var io = new IcebergOrder(_serverFacade,
                                      symbol,
                                      clOrdID,
                                      side,
                                      totalQuantity,
                                      clipSize,
                                      initialPrice,
                                      priceDelta);

            _atOrderRepository.IcebergOrders.Add(io);

            OnIcebergOrderAdded(io);
        }
コード例 #11
0
 public OrderList(string symbol, MarketSide side)
 {
     Symbol = symbol;
     Side   = side;
 }
コード例 #12
0
ファイル: Program.cs プロジェクト: NovichikhinAlexey/LP3-hft
        public async Task <string> PlaceOrderAsync(string symbol, decimal price, decimal size, MarketSide side)
        {
            var orderId = Guid.NewGuid().ToString();

            _orders.Add(orderId, size);
            return(orderId);
        }
コード例 #13
0
ファイル: OrderMediator.cs プロジェクト: naziway/testtask
 private bool OrderWouldLeadToACrossedMarket(MarketSide marketSide,
                                             Contract contract,
                                             decimal orderPrice)
 {
     var bestOppositePrice = _orderRepository.GetBestPrice(contract,
                                                           marketSide.Opposite());
     var wouldCross = marketSide == MarketSide.Bid
                          ? orderPrice > bestOppositePrice
                          : orderPrice < bestOppositePrice;
     return wouldCross;
 }
コード例 #14
0
ファイル: OrderStack.cs プロジェクト: mjheller/wpffix
 private ReaderWriterLockSlim GetSidedLock(MarketSide side)
 {
     return((side == MarketSide.Bid) ? _bidsLock : _asksLock);
 }
コード例 #15
0
ファイル: Program.cs プロジェクト: NovichikhinAlexey/LP3-hft
        public async Task <string> RePlaceOrderAsync(string orderId, string symbol, decimal price, decimal size, MarketSide side)
        {
            if (_orders.TryGetValue(orderId, out var oldSize))
            {
                await CancelOrder(orderId);

                return(await PlaceOrderAsync(symbol, price, size, side));
            }

            return(null);
        }
コード例 #16
0
 public static MarketSide Opposite(this MarketSide side)
 {
     return(side == MarketSide.Bid ? MarketSide.Ask : MarketSide.Bid);
 }
コード例 #17
0
ファイル: OrderStack.cs プロジェクト: mjheller/wpffix
 private SortedSet <IOrder> GetSidedStack(MarketSide side)
 {
     return((side == MarketSide.Bid) ? _bids : _asks);
 }
コード例 #18
0
        public Message CreateRejectNewOrderExecutionReport(string symbol,
                                                           MarketSide marketSide,
                                                           string clOrdID,
                                                           decimal orderQuantity,
                                                           TradingAccount account,
                                                           string execID,
                                                           string rejectionReason,
                                                           int? rejectionCode = null)
        {
            var exReport = new ExecutionReport(
               new OrderID("unknown orderID"),
               new ExecID(execID),
               new ExecType(ExecType.REJECTED),
               new OrdStatus(OrdStatus.REJECTED),
               new Symbol(symbol),
               TranslateFixFields.Translate(marketSide),
               new LeavesQty(0m),
               new CumQty(0m),
               new AvgPx(0m))
            {
                ClOrdID = new ClOrdID(clOrdID),
                OrderQty = new OrderQty(orderQuantity)
            };

            if (rejectionCode.HasValue)
            {
                exReport.OrdRejReason = new OrdRejReason(rejectionCode.Value);
            }

            if (TradingAccount.IsSet(account))
            {
                exReport.Account = new Account(account.Name);
            }

            return exReport;
        }
コード例 #19
0
        protected override void ReceivedDepth(string _symbol, string _type, JToken _token)
        {
            JArray _array = (JArray)_token;
            JArray _list  = (_array.Count == 2 && _array[1].Type == JTokenType.Array) ? _array[1].Value <JArray>() : _array;

            //_symbol = _symbol.Split('.')[1];

            if (_type == "START")
            {
                BookItems _asks = new BookItems(MarketSide.Ask);
                BookItems _bids = new BookItems(MarketSide.Bid);

                foreach (JArray _item in _list)
                {
                    decimal    _price  = _item[0].Value <decimal>();
                    int        _count  = _item[1].Value <int>();
                    decimal    _amount = _item[2].Value <decimal>();
                    MarketSide _side   = _amount > 0 ? MarketSide.Bid : MarketSide.Ask;
                    string     _id     = _price.ToString();

                    BookItem _bookItem = new BookItem(_symbol, _side, _price, Math.Abs(_amount), _id);
                    if (_side == MarketSide.Bid)
                    {
                        _bids.TryAdd(_id, _bookItem);
                    }
                    if (_side == MarketSide.Ask)
                    {
                        _asks.TryAdd(_id, _bookItem);
                    }
                }

                this.Books[_symbol, MarketSide.Ask] = _asks;
                this.Books[_symbol, MarketSide.Bid] = _bids;
                this.OnBookStarted(_symbol);
            }
            else
            {
                decimal    _price  = _list[1].Value <decimal>();
                int        _count  = _list[2].Value <int>();
                decimal    _amount = _list[3].Value <decimal>();
                MarketSide _side   = _amount > 0 ? MarketSide.Bid : MarketSide.Ask;

                BookItems _items = this.Books[_symbol, _side];
                if (_count == 0)
                {
                    BookItem _item = _items.Delete(_price.ToString());
                    if (_item != null)
                    {
                        this.OnBookDelete(_item);
                    }
                }
                else
                {
                    BookItem _item = _items.Update(_price.ToString(), Math.Abs(_amount));
                    if (_item == null)
                    {
                        _item = _items.Insert(_price.ToString(), _price, _amount);
                        this.OnBookInsert(_item);
                    }
                    else
                    {
                        this.OnBookUpdate(_item);
                    }
                }
            }
        }
コード例 #20
0
 public BookItems(MarketSide _side)
 {
     this.Side = _side;
 }
コード例 #21
0
        public Message CreateOrderCancelMessage(string symbol,
                                                string clOrdID,
                                                string newClOrdID,
                                                MarketSide side,
                                                string orderID)
        {
            var ocq = new OrderCancelRequest(new OrigClOrdID(clOrdID),
                                             new ClOrdID(newClOrdID),
                                             new Symbol(symbol),
                                             TranslateFixFields.Translate(side),
                                             new TransactTime(DateTime.Now))
            {
                OrderID = new OrderID(orderID)
            };

            return ocq;
        }
コード例 #22
0
        public async Task <string> RePlaceOrderAsync(string orderId, string symbol, decimal price, decimal size, MarketSide side)
        {
            try
            {
                var request = new BulkLimitOrderRequest();
                request.AssetPairId          = symbol;
                request.CancelPreviousOrders = false;
                request.Orders.Add(new BulkOrder()
                {
                    OldId  = orderId,
                    Side   = side == MarketSide.Long ? Side.Buy : Side.Sell,
                    Price  = price.ToString(CultureInfo.InvariantCulture),
                    Volume = size.ToString(CultureInfo.InvariantCulture)
                });

                var result = await Client.PrivateApi.PlaceBulkLimitOrderAsync(request);

                if (result.Error != null)
                {
                    Console.WriteLine($"ERROR: Cannot PlaceBulkLimitOrderAsync ({orderId}): {result.Error.Message}");
                    return(null);
                }

                var status = result.Payload.Statuses.FirstOrDefault();

                if (status == null || status.Error != ErrorCode.Success)
                {
                    Console.WriteLine($"ERROR: Cannot PlaceBulkLimitOrderAsync ({orderId}): {status.Error}");
                    return(null);
                }

                return(status.Id);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR: Cannot RePlaceOrder ({orderId}):");
                Console.WriteLine(ex);
                return(null);
            }
        }
コード例 #23
0
        private void Trade(OrderStackRow osr, MarketSide side)
        {
            if (osr == null) throw new ArgumentNullException("osr");

            // The server currently does not support click trading, so we fake
            // it here by adding a matching order to the other side of the market.
            // If the server supported ImmediateOrCancel then we'd use that.
            var isBid = side == MarketSide.Bid;
            var matchingOrderDetails = new OrderRecord
            {

                ClOrdID = _clOrdIDGenerator.CreateClOrdID(),
                LastUpdateTime = DateTime.UtcNow,
                OrderID = string.Empty, // Set by server
                OrdType = OrderType.Limit,
                Price = decimal.Parse(isBid ? osr.BidPrice : osr.AskPrice),
                Quantity = decimal.Parse(isBid ? osr.BidQty : osr.AskQty),
                Side = isBid ? MarketSide.Ask : MarketSide.Bid,
                Symbol = osr.Symbol,
                Status = OrderStatus.New
            };

            _serverFacade.CreateOrder(matchingOrderDetails);
        }
コード例 #24
0
        public async Task <string> PlaceOrderAsync(string symbol, decimal price, decimal size, MarketSide side)
        {
            try
            {
                var request = new LimitOrderRequest()
                {
                    AssetPairId = symbol,
                    Price       = price.ToString(CultureInfo.InvariantCulture),
                    Side        = side == MarketSide.Long ? Side.Buy : Side.Sell,
                    Volume      = size.ToString(CultureInfo.InvariantCulture)
                };
                var result = await Client.PrivateApi.PlaceLimitOrderAsync(request);

                if (result.Error != null)
                {
                    Console.WriteLine($"ERROR: Cannot place limit order: {result.Error.Message}");
                    return(string.Empty);
                }

                return(result.Payload.OrderId);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: Cannot place limit order:");
                Console.WriteLine(ex);
                return(string.Empty);
            }
        }
コード例 #25
0
 public void TwoOrdersOnTheSameSideShouldNotMatch(MarketSide side)
 {
     var orderString = string.Format("Limit;TEST;{0};10@10", side);
     var stack = BuildStack(new[] {orderString, orderString});
     var sortedBids = stack.Item1;
     var sortedAsks = stack.Item2;
     var matcher = CreateMatcher();
     var matches = matcher.Match(sortedBids, sortedAsks);
     Assert.IsEmpty(matches, "There should not be any matches");
 }
コード例 #26
0
ファイル: OrderMediator.cs プロジェクト: mjheller/wpffix
        /// <summary>
        /// Adds an order to the system with the given properties
        /// </summary>
        /// <param name="sessionID">The FIX Session ID</param>
        /// <param name="orderType">
        /// The type of order, currently only Limit orders are supported
        /// </param>
        /// <param name="symbol">The symbol for the order</param>
        /// <param name="marketSide">The side of the market for the order</param>
        /// <param name="clOrdID">The FIX ClOrdID for the order, set by the client</param>
        /// <param name="account">The trading account associated with the order</param>
        /// <param name="quantity">The quantity of the order</param>
        /// <param name="price">The price of the order, may be null for market orders</param>
        /// <returns>The new order after it has been added</returns>
        /// <exception cref="FixATServerException">If the order is rejected</exception>
        public IOrder AddOrder(FixSessionID sessionID,
                               OrderType orderType,
                               string symbol,
                               MarketSide marketSide,
                               string clOrdID,
                               TradingAccount account,
                               decimal quantity,
                               decimal?price = null)
        {
            // A more complete system would look the contract up in a contract store
            var contract = new Contract(symbol);

            // TODO Replace this with a better mechanism (esp if more order types are supported)
            decimal orderPrice;

            switch (orderType)
            {
            case OrderType.Limit:
            {
                if (!price.HasValue)
                {
                    throw new FixATServerException("Limit order must specify a price");
                }
                orderPrice = price.Value;
                break;
            }

            // Uncomment this if and when market orders are supported
            //case OrderType.Market:
            //    {
            //        if (price.HasValue)
            //            throw new FixATServerException(
            //                "Market order should not have a specified price");

            //        orderPrice = GetMarketPrice(contract, marketSide);
            //        break;
            //    }

            default:
                throw new FixATServerException(
                          string.Format("Order Type {0} not supported", orderType));
            }

            if (OrderWouldLeadToACrossedMarket(marketSide, contract, orderPrice))
            {
                throw new FixATServerException("Order would lead to a crossed market");
            }

            var order = _orderRepository.AddOrder(CreateOrderID(),
                                                  contract,
                                                  orderType,
                                                  marketSide,
                                                  orderPrice,
                                                  quantity,
                                                  clOrdID,
                                                  account);

            _orderOwners[order.ID] = sessionID;

            return(order);
        }
コード例 #27
0
 /// <summary>
 ///     Gets the best price for the given contract and side of the market
 /// </summary>
 /// <returns>
 ///     null if there are no orders for that contract or side, otherwise the best price
 /// </returns>
 public decimal? GetBestPrice(Contract contract, MarketSide side)
 {
     OrderStack stack;
     if (!_market.TryGetValue(contract, out stack))
     {
         return null;
     }
     return stack.GetBestPrice(side);
 }
コード例 #28
0
ファイル: TestIcebergOrder.cs プロジェクト: naziway/testtask
 private static OrderRecord DefaultFakeOrderRecord(MarketSide side = MarketSide.Bid,
                                                   decimal price = 100,
                                                   decimal quantity = 10)
 {
     return new OrderRecord
     {
         ClOrdID = "ClOrdID",
         LastUpdateTime = DateTime.UtcNow,
         OrderID = "",
         OrdType = OrderType.Limit,
         Price = price,
         Quantity = quantity,
         Side = side,
         Status = OrderStatus.New,
         Symbol = "Symbol"
     };
 }
コード例 #29
0
ファイル: TestIcebergOrder.cs プロジェクト: naziway/testtask
        public void TotalFillWithDeltaAdjustsPriceAsWellAsRefilling(MarketSide side,
                                                                    decimal delta,
                                                                    decimal price,
                                                                    decimal priceAfterFill)
        {
            const decimal totalQ = 20;
            const decimal clipQ = 10;

            var expected = DefaultFakeOrderRecord(quantity: totalQ, price: price, side: side);
            var mockServer = new Mock<IServerFacade>();
            mockServer.Setup(s => s.CreateOrder(It.IsAny<OrderRecord>())).Returns(true);

            var iceberg = new IcebergOrder(mockServer.Object,
                                           expected.Symbol,
                                           expected.ClOrdID,
                                           expected.Side,
                                           expected.Quantity,
                                           clipQ,
                                           price,
                                           delta);

            iceberg.Activate();

            var idGen = new SimpleOrderIDGenerator();
            iceberg.ActivatedMarketOrderAccepted(idGen.GetID());

            iceberg.OnTotalFill();
            iceberg.ActivatedMarketOrderAccepted(idGen.GetID());

            mockServer.Verify(s => s.CreateOrder(It.IsAny<OrderRecord>()),
                              Times.Exactly(2));

            Assert.AreEqual(clipQ, iceberg.CurrentQuantity, "Order not refilled to clip size");
            Assert.AreEqual(totalQ - clipQ,
                            iceberg.RemainingQuantity,
                            "Remaining quantity should be total minus one clip");

            Assert.AreEqual(priceAfterFill,
                            iceberg.CurrentPrice,
                            "Current price not as expected after fill with delta");
            Assert.AreNotEqual(iceberg.InitialPrice,
                               iceberg.CurrentPrice,
                               "Current price should not equal initial price after fill with delta");
        }
コード例 #30
0
        protected override void ReceivedDepth(string _symbol, string _type, JToken _token)
        {
            //this.Log("ReceivedDepth - " + _token.ToString());
            JArray _list = (JArray)_token;

            if (_type == "partial")
            {
                _symbol = _list[0]["symbol"].Value <string>();
                BookItems _asks = new BookItems(MarketSide.Ask);
                BookItems _bids = new BookItems(MarketSide.Bid);

                foreach (JObject _item in _list)
                {
                    MarketSide _side   = _item["side"].Value <string>().ToUpper() == "BUY" ? MarketSide.Bid : MarketSide.Ask;
                    string     _id     = _item["id"].Value <string>();
                    decimal    _price  = _item["price"].Value <decimal>();
                    decimal    _amount = _item["size"].Value <decimal>() / _price;

                    BookItem _bookItem = new BookItem(_symbol, _side, _price, _amount, _id);
                    if (_side == MarketSide.Bid)
                    {
                        _bids.TryAdd(_id, _bookItem);
                    }
                    if (_side == MarketSide.Ask)
                    {
                        _asks.TryAdd(_id, _bookItem);
                    }
                }

                this.Books[_symbol, MarketSide.Ask] = _asks;
                this.Books[_symbol, MarketSide.Bid] = _bids;

                if (this.BookSize > 0)
                {
                    this.Books[_symbol, MarketSide.Ask].Resize(this.BookSize);
                    this.Books[_symbol, MarketSide.Bid].Resize(this.BookSize);
                }

                this.depths.Add(_symbol);
                this.OnBookStarted(_symbol);
            }
            else if (_type == "insert")
            {
                foreach (JObject _item in _list)
                {
                    _symbol = _item["symbol"].Value <string>().ToUpper();
                    if (!this.depths.Contains(_symbol))
                    {
                        continue;
                    }

                    MarketSide _side   = _item["side"].Value <string>().ToUpper() == "BUY" ? MarketSide.Bid : MarketSide.Ask;
                    string     _id     = _item["id"].Value <string>();
                    decimal    _price  = _item["price"].Value <decimal>();
                    decimal    _amount = _item["size"].Value <decimal>() / _price;

                    BookItem _bookItem = this.Books[_symbol, _side].Insert(_id, _price, _amount);
                    this.OnBookInsert(_bookItem);

                    if (this.BookSize > 0 && this.Books[_symbol, _side].Count > this.BookSize * 2)
                    {
                        this.Books[_symbol, _side].Resize(this.BookSize);
                    }
                }
            }
            else if (_type == "update")
            {
                foreach (JObject _item in _list)
                {
                    _symbol = _item["symbol"].Value <string>().ToUpper();
                    if (!this.depths.Contains(_symbol))
                    {
                        continue;
                    }

                    MarketSide _side   = _item["side"].Value <string>().ToUpper() == "BUY" ? MarketSide.Bid : MarketSide.Ask;
                    string     _id     = _item["id"].Value <string>();
                    decimal    _amount = _item["size"].Value <decimal>();

                    BookItem _bookItem = this.Books[_symbol, _side][_id];
                    if (_bookItem == null && this.BookSize > 0)
                    {
                        return;
                    }
                    else if (_bookItem == null)
                    {
                        this.Log("Book update failed 1 - " + _item.ToString(Newtonsoft.Json.Formatting.None));
                        return;
                    }

                    _amount   = _amount / _bookItem.Price;
                    _bookItem = this.Books[_symbol, _side].Update(_id, _amount);
                    if (_bookItem != null)
                    {
                        this.OnBookUpdate(_bookItem);
                    }
                    else if (this.BookSize == 0)
                    {
                        this.Log("Book update failed 2 - " + _item.ToString(Newtonsoft.Json.Formatting.None));
                    }
                }
            }
            else if (_type == "delete")
            {
                foreach (JObject _item in _list)
                {
                    _symbol = _item["symbol"].Value <string>().ToUpper();
                    if (!this.depths.Contains(_symbol))
                    {
                        continue;
                    }

                    MarketSide _side = _item["side"].Value <string>().ToUpper() == "BUY" ? MarketSide.Bid : MarketSide.Ask;
                    string     _id   = _item["id"].Value <string>();

                    BookItem _bookItem = this.Books[_symbol, _side].Delete(_id);
                    if (_bookItem != null)
                    {
                        this.OnBookDelete(_bookItem);
                    }
                    else if (this.BookSize == 0)
                    {
                        this.Log("Book delete failed - " + _item.ToString(Newtonsoft.Json.Formatting.None));
                    }
                }
            }
        }