public void ShouldNotMatchSellStopLimitOrderLowerThanMarket() { var executions = new List <INewExecution>(); var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var matchAlgo = new LimitOrderMatchingAlgorithm(new DateService()); matchAlgo.AddExecutionsHandler(executions.Add); var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock.Object, orderBookBestBidAsk); var sellOrder1 = new LimitOrder("ABC", 10, 1161.8d, WayEnum.Sell, 9); book.AddLimitOrder(sellOrder1); var buyOrder1 = new LimitOrder("ABC", 10, 1161.7d, WayEnum.Buy, 9); book.AddLimitOrder(buyOrder1); var trigger = new BestPriceTrigger("ABC", 1160, WayEnum.Sell); trigger.SetTriggerAction(() => { Console.WriteLine("Boom!"); int i = 0; }); var sellStopLimit = new StopLimitOrder("ABC", 1, 1160, 1160, WayEnum.Sell, 5, trigger); book.AddStopLimitOrder(sellStopLimit); Assert.AreEqual(0, executions.Count); }
public void HandleAddLimitOrder(ILimitOrder limitOrder) { string symbol = limitOrder.Symbol; if (!OrderBooks.ContainsKey(symbol)) { var bookMatchingLimitAlgo = new LimitOrderMatchingAlgorithm(dateService); bookMatchingLimitAlgo.AddExecutionsHandler(outgoingQueue.EnqueueClientExecution); var bookMatchingMarketAlgo = new MarketOrderMatchingAlgorithm(dateService); bookMatchingMarketAlgo.AddExecutionsHandler(outgoingQueue.EnqueueClientExecution); var level1 = new OrderBookBestBidAsk(symbol); level1.RegisterUpdateHandler(outgoingQueue.EnqueueLevel1Update); var book = new OrderBook(symbol, bookMatchingLimitAlgo, bookMatchingMarketAlgo, level1); OrderBooks.Add(symbol, book); } outgoingQueue.EnqueueAddedLimitOrder(limitOrder); limitOrder.RegisterDeleteNotificationHandler(OrderBooks[symbol].RemoveLimitOrder); limitOrder.RegisterFilledNotification(OrderBooks[symbol].RemoveLimitOrder); limitOrder.RegisterModifyNotificationHandler(OrderBooks[symbol].HandleLimitOrderModify); OrderBooks[symbol].AddLimitOrder(limitOrder); }
public void HandleAddLimitOrder(ILimitOrder limitOrder) { string symbol = limitOrder.Symbol; if (!OrderBooks.ContainsKey(symbol)) { var bookMatchingLimitAlgo = new LimitOrderMatchingAlgorithm(dateService); bookMatchingLimitAlgo.AddExecutionsHandler(outgoingQueue.EnqueueClientExecution); var bookMatchingMarketAlgo = new MarketOrderMatchingAlgorithm(dateService); bookMatchingMarketAlgo.AddExecutionsHandler(outgoingQueue.EnqueueClientExecution); var level1 = new OrderBookBestBidAsk(symbol); level1.RegisterUpdateHandler(outgoingQueue.EnqueueLevel1Update); var book = new OrderBook(symbol, bookMatchingLimitAlgo, bookMatchingMarketAlgo, level1); OrderBooks.Add(symbol, book); } outgoingQueue.EnqueueAddedLimitOrder(limitOrder); limitOrder.RegisterDeleteNotificationHandler(OrderBooks[symbol].RemoveLimitOrder); limitOrder.RegisterFilledNotification(OrderBooks[symbol].RemoveLimitOrder); limitOrder.RegisterModifyNotificationHandler(OrderBooks[symbol].HandleLimitOrderModify); OrderBooks[symbol].AddLimitOrder(limitOrder); }
public void ShouldNotMatchOrderWhenMatchingIsSuspendedButMatchWhenSuspensionsIsCancelled() { var executions = new List <INewExecution>(); var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var matchAlgo = new LimitOrderMatchingAlgorithm(new DateService()); matchAlgo.AddExecutionsHandler(executions.Add); var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock.Object, orderBookBestBidAsk); var sellOrder1 = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 9); var buyOrder1 = new LimitOrder("ABC", 10, 80, WayEnum.Buy, 9); sellOrder1.RegisterModifyNotificationHandler(book.HandleLimitOrderModify); buyOrder1.RegisterModifyNotificationHandler(book.HandleLimitOrderModify); book.AddLimitOrder(sellOrder1); book.AddLimitOrder(buyOrder1); Assert.AreEqual(0, executions.Count); book.SetSuspendLimitOrderMatchingStatus(true); sellOrder1.Modify(10, 70); Assert.AreEqual(0, executions.Count); book.SetSuspendLimitOrderMatchingStatus(true); book.TryMatchLimitOrder(sellOrder1); book.TryMatchLimitOrder(buyOrder1); Assert.AreEqual(1, executions.Count); }
public void ShouldNotMatchOrdersWithDifferentSymbols() { var generatedExecutions = new List <INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("QQQ", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); }
public void ShouldNotMatchHigherSellOrderWithLowerBuyOrder() { var generatedExecutions = new List <INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock.Object); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 10, 100, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); }
public void ShouldExecuteOnLowestQuantity() { var staticDatetimeOffset = DateTimeOffset.UtcNow; dateServiceMock.Stub(a => a.UtcNow()).Return(staticDatetimeOffset); var generatedExecutions = new List<INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 40, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 100, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(1, generatedExecutions.Count); Assert.AreEqual(40, generatedExecutions[0].MatchedQuantity); }
public void OrdersShouldNotHaveModifiedQuantitiesAfterNoMatch() { var staticDatetimeOffset = DateTimeOffset.UtcNow; dateServiceMock.Stub(a => a.UtcNow()).Return(staticDatetimeOffset); var generatedExecutions = new List<INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 40, 91, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 100, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(40, sellOrder.Quantity); Assert.AreEqual(100, buyOrder.Quantity); }
public void OrdersShouldNotHaveModifiedQuantitiesAfterNoMatch() { var staticDatetimeOffset = DateTimeOffset.UtcNow; dateServiceMock.Stub(a => a.UtcNow()).Return(staticDatetimeOffset); var generatedExecutions = new List <INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 40, 91, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 100, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(40, sellOrder.Quantity); Assert.AreEqual(100, buyOrder.Quantity); }
public void ShouldExecuteOnLowestQuantity() { var staticDatetimeOffset = DateTimeOffset.UtcNow; dateServiceMock.Stub(a => a.UtcNow()).Return(staticDatetimeOffset); var generatedExecutions = new List <INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 40, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 100, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(1, generatedExecutions.Count); Assert.AreEqual(40, generatedExecutions[0].MatchedQuantity); }
public void ShouldNotMatchOrdersWithZeroQuantity() { var generatedExecutions = new List <INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock.Object); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 0, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); sellOrder.Modify(90); buyOrder.Modify(0); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); }
public void ShouldMatchBuyOrderCompletely() { var executions = new List<INewExecution>(); var executionalgo = new LimitOrderMatchingAlgorithm(new DateService()); executionalgo.AddExecutionsHandler(executions.Add); var priceSlot = new PriceSlot(90, executionalgo, new MarketOrderMatchingAlgorithm(new DateService())); var sellOrder = new LimitOrder("ABC", 100, 90, WayEnum.Sell, 90); var buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 80); priceSlot.AddOrder(sellOrder); priceSlot.TryMatchLimitOrder(buyOrder); Assert.AreEqual(1, executions.Count); Assert.AreEqual(0, priceSlot.BuyOrders.Count); Assert.AreEqual(1, priceSlot.SellOrders.Count); Assert.AreEqual(90, priceSlot.SellOrders[0].Quantity); }
public void ShouldMatchMultipleSellOrdersToSameBuyOrder() { var executions = new List<INewExecution>(); var executionalgo = new LimitOrderMatchingAlgorithm(new DateService()); executionalgo.AddExecutionsHandler(executions.Add); var priceSlot = new PriceSlot(90, executionalgo, new MarketOrderMatchingAlgorithm(new DateService())); var sellOrder1 = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 90); var sellOrder2 = new LimitOrder("ABC", 40, 90, WayEnum.Sell, 90); var buyOrder = new LimitOrder("ABC", 50, 90, WayEnum.Buy, 80); priceSlot.AddOrder(sellOrder1); priceSlot.AddOrder(sellOrder2); priceSlot.TryMatchLimitOrder(buyOrder); Assert.AreEqual(2, executions.Count); Assert.AreEqual(0, priceSlot.BuyOrders.Count); Assert.AreEqual(0, priceSlot.SellOrders.Count); }
public void ShouldMatchMultipleSellOrdersToSameBuyOrder() { var executions = new List <INewExecution>(); var executionalgo = new LimitOrderMatchingAlgorithm(new DateService()); executionalgo.AddExecutionsHandler(executions.Add); var priceSlot = new PriceSlot(90, executionalgo, new MarketOrderMatchingAlgorithm(new DateService())); var sellOrder1 = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 90); var sellOrder2 = new LimitOrder("ABC", 40, 90, WayEnum.Sell, 90); var buyOrder = new LimitOrder("ABC", 50, 90, WayEnum.Buy, 80); priceSlot.AddOrder(sellOrder1); priceSlot.AddOrder(sellOrder2); priceSlot.TryMatchLimitOrder(buyOrder); Assert.AreEqual(2, executions.Count); Assert.AreEqual(0, priceSlot.BuyOrders.Count); Assert.AreEqual(0, priceSlot.SellOrders.Count); }
public void HigherBuyOrderShouldMatchLowerSellOrdersAndPlaceBuyOrderInBookOnRestQuantity() { var executions = new List <INewExecution>(); var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var matchAlgo = new LimitOrderMatchingAlgorithm(new DateService()); matchAlgo.AddExecutionsHandler(executions.Add); var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock.Object, orderBookBestBidAsk); var sellOrder1 = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 9); var sellOrder2 = new LimitOrder("ABC", 10, 91, WayEnum.Sell, 9); var sellOrder3 = new LimitOrder("ABC", 10, 92, WayEnum.Sell, 9); var sellOrder4 = new LimitOrder("ABC", 10, 93, WayEnum.Sell, 9); var sellOrder5 = new LimitOrder("ABC", 10, 94, WayEnum.Sell, 9); book.AddLimitOrder(sellOrder1); book.AddLimitOrder(sellOrder2); book.AddLimitOrder(sellOrder3); book.AddLimitOrder(sellOrder4); book.AddLimitOrder(sellOrder5); Assert.AreEqual(90, orderBookBestBidAsk.BestAskPrice); Assert.AreEqual(10, orderBookBestBidAsk.BestAskQuantity); var buyOrder1 = new LimitOrder("ABC", 100, 93, WayEnum.Buy, 9); book.AddLimitOrder(buyOrder1); Assert.AreEqual(4, executions.Count); Assert.AreEqual(60, buyOrder1.Quantity); Assert.AreEqual(94, orderBookBestBidAsk.BestAskPrice); Assert.AreEqual(10, orderBookBestBidAsk.BestAskQuantity); Assert.AreEqual(93, orderBookBestBidAsk.BestBidPrice); Assert.AreEqual(60, orderBookBestBidAsk.BestBidQuantity); }
public void ShouldMatchBuyOrderCompletely() { var executions = new List <INewExecution>(); var executionalgo = new LimitOrderMatchingAlgorithm(new DateService()); executionalgo.AddExecutionsHandler(executions.Add); var priceSlot = new PriceSlot(90, executionalgo, new MarketOrderMatchingAlgorithm(new DateService())); var sellOrder = new LimitOrder("ABC", 100, 90, WayEnum.Sell, 90); var buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 80); priceSlot.AddOrder(sellOrder); priceSlot.TryMatchLimitOrder(buyOrder); Assert.AreEqual(1, executions.Count); Assert.AreEqual(0, priceSlot.BuyOrders.Count); Assert.AreEqual(1, priceSlot.SellOrders.Count); Assert.AreEqual(90, priceSlot.SellOrders[0].Quantity); }
public void ShouldGenerateExecutionWithSamePriceAsBuyAndSell() { var staticDatetimeOffset = DateTimeOffset.UtcNow; dateServiceMock.Stub(a => a.UtcNow()).Return(staticDatetimeOffset); var generatedExecutions = new List <INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(1, generatedExecutions.Count); Assert.AreEqual(10, generatedExecutions[0].MatchedQuantity); Assert.AreEqual(90, generatedExecutions[0].MatchedPrice); Assert.AreEqual(buyOrder, generatedExecutions[0].BuySideOrder); Assert.AreEqual(sellOrder, generatedExecutions[0].SellSideOrder); Assert.AreEqual(staticDatetimeOffset, generatedExecutions[0].ExecutionTime); }
public void HigherBuyOrderShouldMatchLowerSellOrdersAndPlaceBuyOrderInBookOnRestQuantity() { var executions = new List<INewExecution>(); var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var matchAlgo = new LimitOrderMatchingAlgorithm(new DateService()); matchAlgo.AddExecutionsHandler(executions.Add); var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock, orderBookBestBidAsk); var sellOrder1 = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 9); var sellOrder2 = new LimitOrder("ABC", 10, 91, WayEnum.Sell, 9); var sellOrder3 = new LimitOrder("ABC", 10, 92, WayEnum.Sell, 9); var sellOrder4 = new LimitOrder("ABC", 10, 93, WayEnum.Sell, 9); var sellOrder5 = new LimitOrder("ABC", 10, 94, WayEnum.Sell, 9); book.AddLimitOrder(sellOrder1); book.AddLimitOrder(sellOrder2); book.AddLimitOrder(sellOrder3); book.AddLimitOrder(sellOrder4); book.AddLimitOrder(sellOrder5); Assert.AreEqual(90, orderBookBestBidAsk.BestAskPrice); Assert.AreEqual(10, orderBookBestBidAsk.BestAskQuantity); var buyOrder1 = new LimitOrder("ABC", 100, 93, WayEnum.Buy, 9); book.AddLimitOrder(buyOrder1); Assert.AreEqual(4, executions.Count); Assert.AreEqual(60, buyOrder1.Quantity); Assert.AreEqual(94, orderBookBestBidAsk.BestAskPrice); Assert.AreEqual(10, orderBookBestBidAsk.BestAskQuantity); Assert.AreEqual(93, orderBookBestBidAsk.BestBidPrice); Assert.AreEqual(60, orderBookBestBidAsk.BestBidQuantity); }
public void ShouldNotMatchOrderWhenMatchingIsSuspendedButMatchWhenSuspensionsIsCancelled() { var executions = new List<INewExecution>(); var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var matchAlgo = new LimitOrderMatchingAlgorithm(new DateService()); matchAlgo.AddExecutionsHandler(executions.Add); var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock, orderBookBestBidAsk); var sellOrder1 = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 9); var buyOrder1 = new LimitOrder("ABC", 10, 80, WayEnum.Buy, 9); sellOrder1.RegisterModifyNotificationHandler(book.HandleLimitOrderModify); buyOrder1.RegisterModifyNotificationHandler(book.HandleLimitOrderModify); book.AddLimitOrder(sellOrder1); book.AddLimitOrder(buyOrder1); Assert.AreEqual(0, executions.Count); book.SetSuspendLimitOrderMatchingStatus(true); sellOrder1.Modify(10,70); Assert.AreEqual(0, executions.Count); book.SetSuspendLimitOrderMatchingStatus(true); book.TryMatchLimitOrder(sellOrder1); book.TryMatchLimitOrder(buyOrder1); Assert.AreEqual(1, executions.Count); }
public void ShouldNotMatchSellStopLimitOrderLowerThanMarket() { var executions = new List<INewExecution>(); var orderBookBestBidAsk = new OrderBookBestBidAsk("ABC"); var matchAlgo = new LimitOrderMatchingAlgorithm(new DateService()); matchAlgo.AddExecutionsHandler(executions.Add); var book = new OrderBook("ABC", matchAlgo, marketOrderMatchingAlgorithmMock, orderBookBestBidAsk); var sellOrder1 = new LimitOrder("ABC", 10, 1161.8d, WayEnum.Sell, 9); book.AddLimitOrder(sellOrder1); var buyOrder1 = new LimitOrder("ABC", 10, 1161.7d, WayEnum.Buy, 9); book.AddLimitOrder(buyOrder1); var trigger = new BestPriceTrigger("ABC", 1160, WayEnum.Sell); trigger.SetTriggerAction(() => { Console.WriteLine("Boom!"); int i = 0; }); var sellStopLimit = new StopLimitOrder("ABC", 1, 1160,1160, WayEnum.Sell, 5, trigger); book.AddStopLimitOrder(sellStopLimit); Assert.AreEqual(0, executions.Count); }
public void ShouldNotMatchOrdersWithZeroQuantity() { var generatedExecutions = new List<INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 0, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); sellOrder.Modify(90); buyOrder.Modify(0); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); }
public void ShouldNotMatchHigherSellOrderWithLowerBuyOrder() { var generatedExecutions = new List<INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 10, 100, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(0, generatedExecutions.Count); }
public void ShouldGenerateExecutionWithSamePriceAsBuyAndSell() { var staticDatetimeOffset = DateTimeOffset.UtcNow; dateServiceMock.Stub(a => a.UtcNow()).Return(staticDatetimeOffset); var generatedExecutions = new List<INewExecution>(); var algo = new LimitOrderMatchingAlgorithm(dateServiceMock); algo.AddExecutionsHandler(generatedExecutions.Add); ILimitOrder sellOrder = new LimitOrder("ABC", 10, 90, WayEnum.Sell, 13); ILimitOrder buyOrder = new LimitOrder("ABC", 10, 90, WayEnum.Buy, 12); algo.TryMatch(buyOrder, sellOrder); Assert.AreEqual(1, generatedExecutions.Count); Assert.AreEqual(10, generatedExecutions[0].MatchedQuantity); Assert.AreEqual(90, generatedExecutions[0].MatchedPrice); Assert.AreEqual(buyOrder, generatedExecutions[0].BuySideOrder); Assert.AreEqual(sellOrder, generatedExecutions[0].SellSideOrder); Assert.AreEqual(staticDatetimeOffset, generatedExecutions[0].ExecutionTime); }