예제 #1
0
        public void AddOrderTest()
        {
            OrderBook book = new OrderBook("ERX", OrderAction.OrderBuy);
            Exception e    = Assert.Throws <ArgumentNullException>(() =>
                                                                   book.AddOrder(null));

            Assert.Equal("Value cannot be null. (Parameter 'order')",
                         e.Message);
            String  accountId = Guid.NewGuid().ToString();
            OrderBL buyMarket = TestUtils.NewBuyMarketOrder(accountId, "E", 100);

            e = Assert.Throws <ArgumentException>(() =>
                                                  book.AddOrder(buyMarket));
            Assert.Equal(String.Format(OrderBook.ERROR_MARKET_ORDER, buyMarket.OrderId),
                         e.Message);
            OrderBL buyLimit = TestUtils.NewBuyLimitDayOrder(accountId, "E", 100, 0.50M);

            buyLimit.Cancel();
            e = Assert.Throws <ArgumentException>(() =>
                                                  book.AddOrder(buyLimit));
            Assert.Equal(String.Format(OrderBook.ERROR_NOT_OPEN_ORDER, buyLimit.OrderId),
                         e.Message);
            buyLimit = TestUtils.NewBuyLimitDayOrder(accountId, "E", 100, 0.50M);
            e        = Assert.Throws <ArgumentException>(() =>
                                                         book.AddOrder(buyLimit));
            Assert.Equal(String.Format(OrderBook.ERROR_TICKER, "ERX", buyLimit.OrderId),
                         e.Message);
            OrderBL sellLimit = TestUtils.NewSellLimitDayOrder(accountId, "ERX", 100, 18.81M);

            e = Assert.Throws <ArgumentException>(() =>
                                                  book.AddOrder(sellLimit));
            Assert.Equal(String.Format(OrderBook.ERROR_ACTION, OrderAction.OrderBuy, sellLimit.Action),
                         e.Message);

            OrderBL order1 = TestUtils.NewBuyLimitDayOrder(accountId, "ERX", 100, 18.81M);
            OrderBL order2 = TestUtils.NewBuyLimitDayOrder(accountId, "ERX", 100, 18.82M);
            OrderBL order3 = TestUtils.NewBuyLimitDayOrder(accountId, "ERX", 100, 18.83M);
            OrderBL order4 = TestUtils.NewBuyLimitDayOrder(accountId, "ERX", 100, 18.84M);
            OrderBL order5 = TestUtils.NewBuyLimitDayOrder(accountId, "ERX", 100, 18.85M);

            book.AddOrder(order3);
            book.AddOrder(order5);
            book.AddOrder(order1);
            book.AddOrder(order2);
            book.AddOrder(order4);

            e = Assert.Throws <ArgumentException>(() =>
                                                  book.AddOrder(order1));
            Assert.Equal(String.Format(OrderBook.ERROR_ORDER_EXISTS, order1.OrderId),
                         e.Message);
        }
예제 #2
0
        public OrderBL CancelOrder(String orderId)
        {
            CheckNotNullOrWhitespace(orderId, paramName: nameof(orderId));

            CheckArgument(orderIds.ContainsKey(orderId),
                          String.Format(ERROR_ORDER_NOT_EXISTS, orderId));

            OrderBL order = orderIds[orderId];

            RemoveOrder(order);
            order.Cancel();

            return(order);
        }
예제 #3
0
        private OrderTransactionResponseBL TryFillOrderBook(IAccountServiceRpcClient accountService)
        {
#if PERF_FINEST
            long start = Now;
#endif

            OrderBL            buyOrder     = BuyBook.First;
            OrderBL            sellOrder    = SellBook.First;
            List <OrderBL>     orders       = new List <OrderBL>();
            List <Transaction> transactions = new List <Transaction>();
            // QUESTION: Execute the limit order at sell price benefits BUYER fat finger
            //           What to do if SELLER fat finger? Shouldn't that give the SELLER
            //           the higher BID price?
            decimal executionPrice = sellOrder.StrikePrice;
            int     fillQuantity   = Math.Min(buyOrder.OpenQuantity, sellOrder.OpenQuantity);
            Task <CanFillOrderResponse> buyerResponse = accountService
                                                        .CanFillOrderAsync(new CanFillOrderRequest {
                Order        = buyOrder.ToMessage(),
                FillQuantity = fillQuantity
            }).ResponseAsync;
            Task <CanFillOrderResponse> sellerResponse = accountService
                                                         .CanFillOrderAsync(new CanFillOrderRequest {
                Order        = sellOrder.ToMessage(),
                FillQuantity = fillQuantity
            }).ResponseAsync;
            Task.WaitAll(buyerResponse, sellerResponse);
            bool canExecute = true;
            if (!buyerResponse.Result.Value)
            {
                BuyBook.RemoveOrder(buyOrder);
                buyOrder.Cancel();
                orders.Add(buyOrder);
                canExecute = false;
                // TODO: Publish order has been cancelled
            }
            if (!sellerResponse.Result.Value)
            {
                SellBook.RemoveOrder(sellOrder);
                sellOrder.Cancel();
                orders.Add(sellOrder);
                canExecute = false;
                // TODO: Publish order has been cancelled
            }
            if (!canExecute)
            {
                return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
            }

            buyOrder.OpenQuantity  -= fillQuantity;
            sellOrder.OpenQuantity -= fillQuantity;
            Transaction transaction = new Transaction(buyOrder, sellOrder, buyOrder.Ticker,
                                                      fillQuantity, executionPrice);
            transactions.Add(transaction);
            orders.Add(SellBook.First);
            if (SellBook.First.IsFilled)
            {
                OrderBL filledOrder = SellBook.First;
                SellBook.RemoveOrder(filledOrder);
                filledOrder.Complete();
            }
            orders.Add(BuyBook.First);
            if (BuyBook.First.IsFilled)
            {
                OrderBL filledOrder = BuyBook.First;
                BuyBook.RemoveOrder(filledOrder);
                filledOrder.Complete();
            }
#if PERF_FINEST
            Logger.Here().Information(String.Format("TryFillOrderBook executed in {0} milliseconds", ((Now - start) / TimeSpan.TicksPerMillisecond)));
#endif

            return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
        }
예제 #4
0
        private OrderTransactionResponseBL FillMarketOrder(IAccountServiceRpcClient accountService,
                                                           OrderBL order, OrderBook book)
        {
#if PERF_FINEST
            long start = Now;
#endif
            CheckArgument(!order.Action.Equals(book.Type), "Error: Wrong book");

            bool               done         = false;
            List <OrderBL>     orders       = new List <OrderBL>();
            List <Transaction> transactions = new List <Transaction>();
            while (!done)
            {
                if (book.IsEmpty)
                {
                    throw new SystemException("Order book is empty");          // TODO: Handle order book is empty
                }
                OrderBL buyOrder       = order.IsBuyOrder ? order : book.First;
                OrderBL sellOrder      = order.IsSellOrder ? order : book.First;
                decimal executionPrice = order.IsBuyOrder ? sellOrder.StrikePrice : buyOrder.StrikePrice;
                int     fillQuantity   = Math.Min(buyOrder.OpenQuantity, sellOrder.OpenQuantity);
                // QUESTION: Many issues here, partial fill, etc
                Task <CanFillOrderResponse> buyerResponse = accountService
                                                            .CanFillOrderAsync(new CanFillOrderRequest {
                    Order        = buyOrder.ToMessage(),
                    FillQuantity = fillQuantity
                }).ResponseAsync;
                Task <CanFillOrderResponse> sellerResponse = accountService
                                                             .CanFillOrderAsync(new CanFillOrderRequest {
                    Order        = sellOrder.ToMessage(),
                    FillQuantity = fillQuantity
                }).ResponseAsync;
                Task.WaitAll(buyerResponse, sellerResponse);
                bool canExecute = true;
                if (!buyerResponse.Result.Value)
                {
                    if (!order.IsBuyOrder)
                    {
                        BuyBook.RemoveOrder(buyOrder);
                    }
                    buyOrder.Cancel();
                    orders.Add(buyOrder);
                    canExecute = false;
                    // TODO: Publish order has been cancelled
                }
                if (!sellerResponse.Result.Value)
                {
                    if (!order.IsSellOrder)
                    {
                        SellBook.RemoveOrder(sellOrder);
                    }
                    sellOrder.Cancel();
                    orders.Add(sellOrder);
                    canExecute = false;
                    // TODO: Publish order has been cancelled
                }
                if (!order.IsOpen)
                {
                    return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
                }
                if (!canExecute)
                {
                    continue;
                }

                buyOrder.OpenQuantity  -= fillQuantity;
                sellOrder.OpenQuantity -= fillQuantity;
                Transaction transaction = new Transaction(buyOrder, sellOrder, buyOrder.Ticker,
                                                          fillQuantity, executionPrice);
                transactions.Add(transaction);
                orders.Add(book.First);
                if (book.First.IsFilled)
                {
                    OrderBL filledOrder = book.First;
                    book.RemoveOrder(filledOrder);
                    filledOrder.Complete();
                }
                if (order.IsFilled)
                {
                    order.Complete();
                    orders.Add(order);
                    done = true;
                }
            }
#if PERF_FINEST
            Logger.Here().Information(String.Format("Market order executed in {0} milliseconds", ((Now - start) / TimeSpan.TicksPerMillisecond)));
#endif

            return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
        }
예제 #5
0
        public ActionResult Cancel(int id)
        {
            OrderBL.Cancel(id, base._DB);

            return(RedirectToAction("Index"));
        }