示例#1
0
def test_matching_engine_can_add_and_run_multiple_instruments():
    instrument_id_1 = "AAPL"
    instrument_id_2 = "MSFT"
    quantity = 100
    price = 10
    limit_orders_1 = [
        LimitOrder(instrument_id=instrument_id_1,
                   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)
    ]
    limit_orders_2 = [
        LimitOrder(instrument_id=instrument_id_2,
                   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)
    ]

    matching_engine = MatchingEngine()

    for order in limit_orders_1 + limit_orders_2:
        matching_engine.add_order(order)

    matching_engine.run()
    matching_engine.live = False
    order_book = matching_engine.order_books[instrument_id_1]

    assert len(matching_engine.order_books
               ) == 2, "Test Failed: There should be 2 order books"
    assert not matching_engine.orders, "Test Failed: There should be no orders"
    assert len(matching_engine.processed_orders
               ) == 20, "Test Failed: There should be 20 processed_orders"

    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"

    order_book = matching_engine.order_books[instrument_id_2]

    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
示例#2
0
def test_matching_engine_can_add_and_process():
    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)
    ]

    matching_engine = MatchingEngine()

    for order in limit_orders:
        matching_engine.add_order(order)
    matching_engine.match()
    order_book = matching_engine.order_books[instrument_id]

    assert len(matching_engine.order_books
               ) == 1, "Test Failed: There should be 1 order book"
    assert not matching_engine.orders, "Test Failed: There should be no orders"
    assert len(matching_engine.processed_orders
               ) == 10, "Test Failed: There should be 10 processed_orders"
    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
示例#3
0
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
示例#4
0
def test_order_book_cannot_match_non_crossing_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 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 not order_book.attempt_match, "Test Failed: attempt_match should be False"
    pass
示例#5
0
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
示例#6
0
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
示例#7
0
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
示例#8
0
def test_limit_order_sell_can_handle_trade():
    instrument_id = "AAPL"
    order_direction = OrderDirection.sell
    quantity = 100
    price = 10
    limit_order = LimitOrder(instrument_id=instrument_id,
                             order_direction=order_direction,
                             quantity=quantity,
                             price=price)
    trade = Trade(datetime=np.datetime64("2020-01-01"), price=10, quantity=10)
    limit_order.update_on_trade(trade)
    assert limit_order.quantity == quantity, "Test failed, incorrect quantity"
    assert limit_order.order_direction == order_direction, "Test failed, incorrect quantity"
    assert limit_order.price == price, "Test failed, incorrect price for limit order"
    assert limit_order.instrument_id == instrument_id, "Test failed, incorrect instrument_id"
    assert limit_order.order_type == OrderType.limit, "Test failed, incorrect order type"
    assert limit_order.fill_info, "Test failed, no fill info"
    assert limit_order.unfilled_quantity == quantity - \
        10, "Test failed, incorrect unfilled quantity"
    pass
示例#9
0
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 get_data(n):
    instrument_ids = ["AAPL", "MSFT", "TSLA", "FB", "NFLX"]
    quantity = 100
    price = 40
    m = n // len(instrument_ids)
    output = []
    for instr in instrument_ids:
        buy_limits = [
            LimitOrder(instrument_id=instr,
                       order_direction=OrderDirection.buy,
                       quantity=quantity + random.uniform(-50, 50),
                       price=price + random.uniform(-2.5, 2.5))
            for i in range(m // 4)
        ]
        sell_limits = [
            LimitOrder(instrument_id=instr,
                       order_direction=OrderDirection.sell,
                       quantity=quantity + random.uniform(-50, 50),
                       price=price + random.uniform(-2.5, 2.5))
            for i in range(m // 4)
        ]

        buy_markets = [
            MarketOrder(instrument_id=instr,
                        order_direction=OrderDirection.buy,
                        quantity=quantity + random.uniform(-50, 50))
            for i in range(m // 4)
        ]

        sell_markets = [
            MarketOrder(instrument_id=instr,
                        order_direction=OrderDirection.sell,
                        quantity=quantity + random.uniform(-50, 50))
            for i in range(m // 4)
        ]
        output += buy_limits + sell_limits + buy_markets + sell_markets
        random.shuffle(output)
    return output
def test_cannot_cancel_filled_order():
    instrument_id = "AAPL"
    order_direction = OrderDirection.buy
    quantity = 100
    price = 10
    limit_order = LimitOrder(instrument_id=instrument_id,
                             order_direction=order_direction,
                             quantity=quantity,
                             price=price)
    limit_order.order_id = 1
    limit_order.status = OrderStatus.filled

    instrument_id = "AAPL"
    order_id = 1
    cancel_order = CancelOrder(instrument_id=instrument_id,
                               order_id=order_id,
                               order_direction=order_direction)

    cancel_order.cancel_order(order=limit_order)

    assert limit_order.status == OrderStatus.filled, "Test failed: order cancelled"
    assert not cancel_order.cancel_success, "Test Failed: order cancelled"
    pass
示例#12
0
def test_limit_order_sell():
    instrument_id = "AAPL"
    order_direction = OrderDirection.sell
    quantity = 100
    price = 10
    limit_order = LimitOrder(instrument_id=instrument_id,
                             order_direction=order_direction,
                             quantity=quantity,
                             price=price)

    assert limit_order.quantity == quantity, "Test failed, incorrect quantity"
    assert limit_order.order_direction == order_direction, "Test failed, incorrect quantity"
    assert limit_order.price == price, "Test failed, incorrect price for limit order"
    assert limit_order.instrument_id == instrument_id, "Test failed, incorrect instrument_id"
    assert limit_order.order_type == OrderType.limit, "Test failed, incorrect order type"
    assert limit_order.unfilled_quantity == quantity, "Test failed, incorrect unfilled quantity"
    pass
示例#13
0
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
示例#14
0
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
示例#15
0
def test_matching_engine_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)
    ]

    matching_engine = MatchingEngine()

    for order in limit_orders:
        matching_engine.add_order(order)

    assert not matching_engine.order_books, "Test Failed: There should beno order books"
    assert matching_engine.orders, "Test Failed: There should be orders"
    assert len(
        matching_engine.orders) == 10, "Test Failed: There should be 10 orders"
    assert not matching_engine.processed_orders, "Test Failed: There should be no processed_orders"
    pass
示例#16
0
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