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))); }