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); }
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); }
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))); }
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))); }
public ActionResult Cancel(int id) { OrderBL.Cancel(id, base._DB); return(RedirectToAction("Index")); }