Esempio n. 1
0
        public MockOrderBook HandleOrder(ExchangeOrder incomingOrder)
        {
            switch (incomingOrder.Status)
            {
            case ExchangeOrderStatus.Canceled:
                return(CancelOrder(incomingOrder));

            case ExchangeOrderStatus.Pending:
                return(PlaceOrder(incomingOrder));

            default:
                throw new Exception(string.Format("Unhandled incoming order status {0}", incomingOrder.Status));
            }
        }
Esempio n. 2
0
        //if the bid > ask or one and only of the orders is a market order, return the price of the transaction
        //else return -1
        //two birds one stone:
        //allows me to know IF there was a transaction and if so, tells me what the price is
        private decimal GetTransactionPrice(ExchangeOrder incomingOrder, ExchangeOrder targetOrder)
        {
            if (incomingOrder.OSide == targetOrder.OSide)
            {
                throw new ArgumentException("Cannot compute transaction price for two same-side orders");
            }

            if (incomingOrder.Status != ExchangeOrderStatus.Open || targetOrder.Status != ExchangeOrderStatus.Open)
            {
                throw new Exception("A transaction price can only be evaluated between two Open orders");
            }

            decimal price = -1;

            if (!((incomingOrder.OType == OrderType.Market) && (targetOrder.OType == OrderType.Market)))//there is no transaction if they are two market orders
            {
                if (incomingOrder.OType == OrderType.Market)
                {
                    //at this point we are sure the target order is a limit order
                    price = targetOrder.Price;
                }
                else if (targetOrder.OType == OrderType.Market)
                {
                    //at this point we are sure the incoming order is a limit order
                    price = incomingOrder.Price;
                }
                else
                {
                    //they are both limit orders
                    //we choose the price that favors the target order because it arrived first (first come best served)

                    if (((incomingOrder.OSide == OrderSide.Buy) && (incomingOrder.Price >= targetOrder.Price)) ||
                        ((incomingOrder.OSide == OrderSide.Sell) && (incomingOrder.Price <= targetOrder.Price))
                        )
                    {
                        price = incomingOrder.Price;
                    }
                }
            }

            return(price);
        }
Esempio n. 3
0
        public MockOrderBook PlaceOrder(ExchangeOrder pendingOrder)
        {
            if (pendingOrder == null)
            {
                throw new ArgumentNullException("pendingOrder");
            }
            if (pendingOrder.Status != ExchangeOrderStatus.Pending)
            {
                throw new Exception(string.Format("Cannot insert order with '{0}' status in the OrderBook", pendingOrder.Status));
            }

            //Now the order is opened
            var openOrder = pendingOrder.WithUpdatedStatus(ExchangeOrderStatus.Open);

            var orders = this.Orders;
            var bids   = this.Bids;
            var asks   = this.Asks;

            ImmutableSortedSet <ExchangeOrder> oppositeSideOrders = null;
            ImmutableSortedSet <ExchangeOrder> sameSideOrders     = null;

            if (openOrder.OSide == OrderSide.Buy)
            {
                oppositeSideOrders = asks;
                sameSideOrders     = bids;
            }
            else
            {
                oppositeSideOrders = bids;
                sameSideOrders     = asks;
            }

            var matchOuput = MatchOrder(Tuple.Create(openOrder, oppositeSideOrders));

            ExchangeOrder resultingOrder = matchOuput.Item1;
            ImmutableSortedSet <ExchangeOrder> resultingSameSideOrders = null;

            if (resultingOrder.RemainingVolume > 0)
            {
                resultingSameSideOrders = sameSideOrders.Add(resultingOrder);
            }
            else
            {
                resultingSameSideOrders = sameSideOrders;
            }

            ImmutableSortedSet <ExchangeOrder> resultingOppositeSideOrders = matchOuput.Item2;

            #region update orders
            var ordersBuilder = orders.ToBuilder();

            ordersBuilder[resultingOrder.ID] = resultingOrder;

            var oppositeSideOrdersDiff = resultingOppositeSideOrders.SymmetricExcept(oppositeSideOrders).                  //contains all the elements which are NOT PRESENT IN BOTH sets. for updated orders, both the old and new one will be returned
                                         GroupBy(o => o.ID, (_, g) => g.OrderBy(o => o.RemainingVolume).FirstOrDefault()). //for changed orders, take only the latest one
                                         ToList();

            foreach (var item in oppositeSideOrdersDiff)
            {
                //add or update the value in dictionary
                ordersBuilder[item.ID] = item;
            }
            #endregion

            #region reconstruct bids and asks
            ImmutableSortedSet <ExchangeOrder> resultingBids = null;
            ImmutableSortedSet <ExchangeOrder> resultingAsks = null;

            if (openOrder.OSide == OrderSide.Buy)
            {
                resultingBids = resultingSameSideOrders;
                resultingAsks = resultingOppositeSideOrders;
            }
            else
            {
                resultingBids = resultingOppositeSideOrders;
                resultingAsks = resultingSameSideOrders;
            }

            resultingBids = resultingBids.Where(o => o.Status == ExchangeOrderStatus.Open).ToImmutableSortedSet(OrderComparer.DescBidComparer());
            resultingAsks = resultingAsks.Where(o => o.Status == ExchangeOrderStatus.Open).ToImmutableSortedSet(OrderComparer.DescAskComparer());

            #endregion

            //return all orders + bids and asks from which completed orders are removed
            return(new MockOrderBook(this.ExchangeID,
                                     ordersBuilder.ToImmutable(),
                                     resultingBids,
                                     resultingAsks));
        }