def test_order_book_can_add_orders(): instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if i % 2 else OrderDirection.sell, quantity=quantity, price=price + (i if i % 2 else -i)) for i in range(10) ] order_book = OrderBook() for order in limit_orders: order_book.add_order(order) assert len(order_book.bids) == 4, "Test Failed: There should be 5 bids" assert len(order_book.asks) == 4, "Test Failed: There should be 5 asks" assert order_book.best_bid is not None, "Test Failed: best_bid should not be empty" assert order_book.best_ask is not None, "Test Failed: best_ask should not be empty" assert order_book.best_bid.price > order_book.best_ask.price, "Test Failed: best prices are not aligned" assert all(order_book.bids[i].price > order_book.asks[i].price for i in range(4)), \ "Test Failed: prices are not aligned" assert not order_book.trades, "Test Failed: trades should be empty" assert not order_book.complete_orders, "Test Failed: complete_orders should be empty" assert order_book.attempt_match, "Test Failed: attempt_match should be True" pass
def test_order_book_cannot_cancel_nothing(): instrument_id = "AAPL" order_book = OrderBook() cancel_order = CancelOrder(instrument_id=instrument_id, order_id=2, order_direction=OrderDirection.sell) order_book.add_order(cancel_order) assert not cancel_order.cancel_success, "Test Failed: cancel should fail" pass
def test_order_book_raise_exception_on_invalid_order(): instrument_id = "AAPL" quantity = 100 price = 10 limit_order = LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.test, quantity=quantity, price=price) order_book = OrderBook() with pytest.raises(InvalidOrderDirectionException) as exn: order_book.add_order(limit_order) pass
def test_order_book_can_handle_limit_and_market_orders_together(): """ Here there are more asks than bids, so the bids will fill""" instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy, quantity=quantity - 10 * i, price=price + i) for i in range(5) ] market_order = MarketOrder(instrument_id=instrument_id, order_direction=OrderDirection.sell, quantity=400) order_book = OrderBook() for order in limit_orders: order_book.add_order(order) order_book.add_order(market_order) order_book.match() assert not order_book.asks, "Test Failed: There should be no asks after this matching" assert order_book.best_ask is None, "Test Failed: best_ask should be empty" assert not order_book.bids, "Test Failed: There should be no bids after this matching" assert order_book.best_bid is None, "Test Failed: best_bid should be empty" assert len(order_book.trades) == 5, "Test Failed: there should be 5 trades" assert len(order_book.complete_orders ) == 6, "Test Failed: complete_orders should have 6 orders" assert not order_book.attempt_match, "Test Failed: attempt_match should be False" pass
def match(self): while self.orders: order = self.orders.popleft() instrument_id = order.instrument_id order_books = self.order_books if instrument_id in order_books.keys(): order_book = order_books[instrument_id] order_book.add_order(order) order_book.match() else: order_book = OrderBook() order_book.add_order(order) order_books[instrument_id] = order_book self.processed_orders.append(order)
def test_order_book_init(): order_book = OrderBook() assert not order_book.bids, "Test Failed: bids should be empty" assert not order_book.asks, "Test Failed: asks should be empty" assert order_book.best_bid is None, "Test Failed: best_bid should be empty" assert order_book.best_ask is None, "Test Failed: best_ask should be empty" assert not order_book.trades, "Test Failed: trades should be empty" assert not order_book.complete_orders, "Test Failed: complete_orders should be empty" assert not order_book.attempt_match, "Test Failed: attempt_match should default to False" pass
def test_order_book_can_match_orders(): instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if i % 2 else OrderDirection.sell, quantity=quantity, price=price + (i if i % 2 else -i)) for i in range(10) ] order_book = OrderBook() for order in limit_orders: order_book.add_order(order) order_book.match() assert not order_book.bids, "Test Failed: There should be no bids after complete matching" assert not order_book.asks, "Test Failed: There should be no asks after complete matching" assert order_book.best_bid is None, "Test Failed: best_bid should be empty" assert order_book.best_ask is None, "Test Failed: best_ask should be empty" assert len( order_book.trades) == 5, "Test Failed: trades should have 5 orders" assert len(order_book.complete_orders ) == 10, "Test Failed: complete_orders should have all orders" assert not order_book.attempt_match, "Test Failed: attempt_match should be False" pass
def test_order_book_can_cancel_sell_other_than_best_ask(): instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if i % 2 else OrderDirection.sell, quantity=quantity - 10 * i, price=price + (i if i % 2 else -i)) for i in range(10) ] for i, l in enumerate(limit_orders): l.order_id = i limit_orders[i] = l order_book = OrderBook() for order in limit_orders: order_book.add_order(order) cancel_order = CancelOrder(instrument_id=instrument_id, order_id=2, order_direction=OrderDirection.sell) order_book.add_order(cancel_order) assert len(order_book.bids) > len( order_book.asks), "Test Failed: should be more buys than sells" assert cancel_order.cancel_success, "Test Failed: cancel should succeed" pass
def test_order_book_can_match_incomplete_more_bids(): """ Here there are more asks than bids, so the bids will fill""" instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if not i % 2 else OrderDirection.sell, quantity=quantity - 10 * i, price=price + (i if not i % 2 else -i)) for i in range(10) ] order_book = OrderBook() for order in limit_orders: order_book.add_order(order) order_book.match() assert not order_book.asks, "Test Failed: There should be no asks after this matching" assert order_book.best_ask is None, "Test Failed: best_ask should be empty" assert not order_book.bids, "Test Failed: There should be no bids after this matching" assert order_book.best_bid is not None, "Test Failed: best_bid should not be empty" assert len( order_book.trades) > 5, "Test Failed: trades should more than 5 trades" assert len( order_book.complete_orders ) < 10, "Test Failed: complete_orders should have fewer than 10 orders" assert not order_book.attempt_match, "Test Failed: attempt_match should be False" pass
def test_order_book_can_generate_execution_plot(): instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if not i % 2 else OrderDirection.sell, quantity=quantity - 10 * i, price=price + (i if not i % 2 else -2 * i)) for i in range(10) ] order_book = OrderBook() for order in limit_orders: order_book.add_order(order) order_book.match() order_book.plot_executions() pass
def test_order_book_can_cancel_sell(): """ Here there are more asks than bids, so the bids will fill""" instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if i % 2 else OrderDirection.sell, quantity=quantity - 10 * i, price=price + (i if i % 2 else -i)) for i in range(10) ] for i, l in enumerate(limit_orders): l.order_id = i limit_orders[i] = l order_book = OrderBook() for order in limit_orders: order_book.add_order(order) cancel_order = CancelOrder(instrument_id=instrument_id, order_id=0, order_direction=OrderDirection.sell) order_book.match() order_book.add_order(cancel_order) assert not order_book.asks, "Test Failed: There should be no asks after this matching" assert order_book.best_ask is None, "Test Failed: best_ask should be empty" assert not order_book.bids, "Test Failed: There should be no bids after this matching" assert order_book.best_bid is None, "Test Failed: best_bid should be empty" assert len( order_book.trades) > 5, "Test Failed: trades should more than 5 trades" assert len(order_book.complete_orders ) == 10, "Test Failed: complete_orders should have 10 orders" assert cancel_order.cancel_success, "Test Failed: cancel should succeed" pass
def test_order_book_can_generate_order_book_plot(): instrument_id = "AAPL" quantity = 100 price = 10 limit_orders = [ LimitOrder(instrument_id=instrument_id, order_direction=OrderDirection.buy if i % 2 else OrderDirection.sell, quantity=quantity, price=price + (-i if i % 2 else i)) for i in range(10) ] order_book = OrderBook() for order in limit_orders: order_book.add_order(order) order_book.plot_order_book() pass