def test_update(): order = Order(price=10, volume=100, side=OrderSide.BUY) level = Level(orders=[order]) assert level.volume() == 100 order.update_volume(volume=50) level.update(order=order) assert level.volume() == 50
def test_check_integrity_shallow(empty_l2_book): empty_l2_book.add(Order(price=10.0, volume=5.0, side=OrderSide.SELL)) empty_l2_book.check_integrity() empty_l2_book.add(Order(price=20.0, volume=5.0, side=OrderSide.BUY)) with pytest.raises(AssertionError): empty_l2_book.check_integrity()
def test_from_dict_returns_expected_tick(self): # Arrange order1 = Order(price=10, size=5, side=OrderSide.BUY, id="1") delta1 = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.ADD, order=order1, ts_event_ns=0, ts_recv_ns=0, ) order2 = Order(price=10, size=15, side=OrderSide.BUY, id="2") delta2 = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.ADD, order=order2, ts_event_ns=0, ts_recv_ns=0, ) deltas = OrderBookDeltas( instrument_id=AUDUSD, level=BookLevel.L2, deltas=[delta1, delta2], ts_event_ns=0, ts_recv_ns=0, ) # Act result = OrderBookDeltas.from_dict(OrderBookDeltas.to_dict(deltas)) # Assert assert result == deltas
def test_exposure(): orders = [ Order(price=100.0, volume=10.0, side=OrderSide.SELL), Order(price=101.0, volume=10.0, side=OrderSide.SELL), Order(price=105.0, volume=5.0, side=OrderSide.SELL), ] ladder = TestStubs.ladder(reverse=True, orders=orders) assert tuple(ladder.exposures()) == (525.0, 1000.0, 1010.0)
def test_delete_individual_order(asks): orders = [ Order(price=100.0, volume=10.0, side=OrderSide.BUY, id="1"), Order(price=100.0, volume=5.0, side=OrderSide.BUY, id="2"), ] ladder = TestStubs.ladder(reverse=True, orders=orders) ladder.delete(orders[0]) assert ladder.volumes() == [5.0]
def test_update(): level = Level(price=10.0) order = Order(price=10.0, size=100.0, side=OrderSide.BUY) level.add(order) assert level.volume() == 100.0 order.update_size(size=50.0) level.update(order=order) assert level.volume() == 50.0
def test_delete_order(): level = Level(price=100.0) orders = [ Order(price=100.0, size=50.0, side=OrderSide.BUY, id="1"), Order(price=100.0, size=50.0, side=OrderSide.BUY, id="2"), ] level.bulk_add(orders=orders) level.delete(order=orders[1]) assert level.volume() == 50.0
def test_from_dict_returns_expected_order(): # Arrange order = Order(price=10, size=5, side=OrderSide.BUY) # Act result = Order.from_dict(Order.to_dict(order)) # Assert assert result == order
def test_level_comparison(): level1 = Level(price=10.0) level2 = Level(price=11.0) level1.add(Order(price=10.0, size=0.0, side=OrderSide.BUY)) level2.add(Order(price=11.0, size=0.0, side=OrderSide.BUY)) assert level2 >= level1 assert level1 < level2 assert level1 != level2
def ladder(): ladder = Ladder() orders = [ Order(price=100, volume=10, side=OrderSide.SELL), Order(price=100, volume=1, side=OrderSide.SELL), Order(price=105, volume=20, side=OrderSide.SELL), ] for order in orders: ladder.add(order=order) return ladder
def test_repr(): book = OrderBook.create( instrument=AUDUSD_SIM, level=OrderBookLevel.L2, ) # Act book.add(Order(price=10.0, volume=5.0, side=OrderSide.BUY)) book.add(Order(price=11.0, volume=6.0, side=OrderSide.SELL)) # Assert assert isinstance(repr(book), str) # <-- calls pprint internally
def sample_book(): ob = L3OrderBook(TestStubs.audusd_id()) orders = [ Order(price=0.900, volume=20, side=OrderSide.SELL), Order(price=0.887, volume=10, side=OrderSide.SELL), Order(price=0.886, volume=5, side=OrderSide.SELL), Order(price=0.830, volume=4, side=OrderSide.BUY), Order(price=0.820, volume=1, side=OrderSide.BUY), ] for order in orders: ob.add(order) return ob
def test_signed_volume(): order = Order(price=10.0, size=1.0, side=OrderSide.BUY) assert order.size == 1 and order.signed_size() == 1.0 order = Order(price=10.0, size=5.0, side=OrderSide.SELL) assert order.size == 5 and order.signed_size() == -5.0 order = Order(price=10.0, size=0.0, side=OrderSide.SELL) assert order.size == 0.0 and order.signed_size() == 0.0
def test_repr(self): book = OrderBook.create( instrument_id=AUDUSD, level=OrderBookLevel.L2, price_precision=2, size_precision=2, ) # Act book.add(Order(price=10, volume=5, side=OrderSide.BUY)) book.add(Order(price=11, volume=6, side=OrderSide.SELL)) # Assert assert isinstance(repr(book), str) # <-- calls pprint internally
def test_to_dict_returns_expected_dict(): # Arrange order = Order(price=10, size=5, side=OrderSide.BUY, id="1") # Act result = Order.to_dict(order) # Assert assert result == { "type": "Order", "id": "1", "price": 10.0, "side": "BUY", "size": 5.0, }
def test_apply(empty_l2_book, clock): snapshot = OrderBookSnapshot( instrument_id=empty_l2_book.instrument_id, level=OrderBookLevel.L2, bids=[[150.0, 0.51]], asks=[[160.0, 1.51]], timestamp_origin_ns=0, timestamp_ns=0, ) empty_l2_book.apply_snapshot(snapshot) assert empty_l2_book.best_ask_price() == 160 delta = OrderBookDelta( instrument_id=TestStubs.audusd_id(), level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( 155.0, 672.45, OrderSide.SELL, "4a25c3f6-76e7-7584-c5a3-4ec84808e240", ), timestamp_origin_ns=clock.timestamp(), timestamp_ns=clock.timestamp(), ) empty_l2_book.apply(delta) assert empty_l2_book.best_ask_price() == 155
def sample_book(): ob = L3OrderBook( instrument_id=TestStubs.audusd_id(), price_precision=5, size_precision=0, ) orders = [ Order(price=0.90000, volume=20.0, side=OrderSide.SELL), Order(price=0.88700, volume=10.0, side=OrderSide.SELL), Order(price=0.88600, volume=5.0, side=OrderSide.SELL), Order(price=0.83000, volume=4.0, side=OrderSide.BUY), Order(price=0.82000, volume=1.0, side=OrderSide.BUY), ] for order in orders: ob.add(order) return ob
def parse_line(d): if "status" in d: return {} elif "close_price" in d: # return {'timestamp': d['remote_timestamp'], "close_price": d['close_price']} return {} if "trade" in d: return {} # data = TradeTick() elif "level" in d and d["level"]["orders"][0]["volume"] == 0: op = "delete" else: op = "update" order_like = d["level"]["orders"][0] if op != "trade" else d[ "trade"] return { "timestamp": d["remote_timestamp"], "op": op, "order": Order( price=order_like["price"], volume=abs(order_like["volume"]), # Betting sides are reversed side={ 2: OrderSide.BUY, 1: OrderSide.SELL }[order_like["side"]], id=str(order_like["order_id"]), ), }
def inner(): if isinstance(data, OrderBookDeltas): yield from [_parse_delta(delta=delta) for delta in data.deltas] elif isinstance(data, OrderBookDelta): yield _parse_delta(delta=data) elif isinstance(data, OrderBookSnapshot): # For a snapshot, we store the individual deltas required to rebuild, namely a CLEAR, followed by ADDs yield _parse_delta( OrderBookDelta( instrument_id=data.instrument_id, level=data.level, order=None, delta_type=DeltaType.CLEAR, ts_event_ns=data.ts_event_ns, ts_recv_ns=data.ts_recv_ns, ), ) orders = list(zip(repeat(OrderSide.BUY), data.bids)) + list( zip(repeat(OrderSide.SELL), data.asks) ) yield from [ _parse_delta( OrderBookDelta( instrument_id=data.instrument_id, level=data.level, ts_event_ns=data.ts_event_ns, ts_recv_ns=data.ts_recv_ns, order=Order(price=price, size=volume, side=side), delta_type=DeltaType.ADD, ), ) for side, (price, volume) in orders ]
def _handle_book_updates(runner, instrument, timestamp_ns): deltas = [] for side in B_SIDE_KINDS: for upd in runner.get(side, []): # TODO - Fix this crap if len(upd) == 3: _, price, volume = upd else: price, volume = upd deltas.append( OrderBookDelta( delta_type=OrderBookDeltaType.DELETE if volume == 0 else OrderBookDeltaType.UPDATE, order=Order( price=price_to_probability( price, side=B2N_MARKET_STREAM_SIDE[side]), volume=volume, side=B2N_MARKET_STREAM_SIDE[side], ), instrument_id=instrument.id, timestamp_ns=timestamp_ns, )) if deltas: ob_update = OrderBookDeltas( level=OrderBookLevel.L2, instrument_id=instrument.id, deltas=deltas, timestamp_ns=timestamp_ns, ) return [ob_update] else: return []
def test_to_dict_returns_expected_dict(self): # Arrange order = Order(price=10, size=5, side=OrderSide.BUY, id="1") delta = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.ADD, order=order, ts_event_ns=0, ts_recv_ns=0, ) # Act result = OrderBookDelta.to_dict(delta) # Assert assert result == { "type": "OrderBookDelta", "instrument_id": "AUD/USD.SIM", "level": "L2", "delta_type": "ADD", "order_id": "1", "order_price": 10.0, "order_side": "BUY", "order_size": 5.0, "ts_event_ns": 0, "ts_recv_ns": 0, }
def _handle_book_updates(runner, instrument, ts_event_ns, ts_recv_ns): deltas = [] for side in B_SIDE_KINDS: for upd in runner.get(side, []): # TODO(bm): Clean this up if len(upd) == 3: _, price, volume = upd else: price, volume = upd deltas.append( OrderBookDelta( instrument_id=instrument.id, level=BookLevel.L2, delta_type=DeltaType.DELETE if volume == 0 else DeltaType.UPDATE, order=Order( price=price_to_probability( price, side=B2N_MARKET_STREAM_SIDE[side]), size=Quantity(volume, precision=8), side=B2N_MARKET_STREAM_SIDE[side], ), ts_event_ns=ts_event_ns, ts_recv_ns=ts_recv_ns, )) if deltas: ob_update = OrderBookDeltas( level=BookLevel.L2, instrument_id=instrument.id, deltas=deltas, ts_event_ns=ts_event_ns, ts_recv_ns=ts_recv_ns, ) return [ob_update] else: return []
def test_simulate_order_fills_multiple_levels(asks): fills = asks.simulate_order_fills( order=Order(price=20, volume=20, side=OrderSide.BUY, id="1")) expected = [ (Price("15.0000"), Quantity("10.0000")), (Price("16.0000"), Quantity("10.0000")), ] assert fills == expected
def test_add_orders_to_book(): # Arrange book = OrderBook.create( instrument=AUDUSD_SIM, level=OrderBookLevel.L2, ) # Act book.add(Order(price=10.0, volume=5.0, side=OrderSide.BUY)) book.add(Order(price=11.0, volume=6.0, side=OrderSide.SELL)) # Assert assert book.best_bid_price() == 10.0 assert book.best_ask_price() == 11.0 assert book.best_bid_qty() == 5.0 assert book.best_ask_qty() == 6.0 assert book.spread() == 1
def test_hash_str_and_repr(): # Arrange order = Order(price=10, size=5, side=OrderSide.BUY) # Act, Assert assert isinstance(hash(order), int) assert str(order) == f"Order(10.0, 5.0, BUY, {order.id})" assert repr(order) == f"Order(10.0, 5.0, BUY, {order.id})"
def test_simulate_order_fills_whole_ladder(asks): fills = asks.simulate_order_fills( order=Order(price=100, volume=1000, side=OrderSide.BUY, id="1")) expected = [ (Price("15.0000"), Quantity("10.0000")), (Price("16.0000"), Quantity("20.0000")), (Price("17.0000"), Quantity("30.0000")), ] assert fills == expected
def test_to_dict_returns_expected_dict(self): # Arrange order1 = Order(price=10, size=5, side=OrderSide.BUY, id="1") delta1 = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.ADD, order=order1, ts_event_ns=0, ts_recv_ns=0, ) order2 = Order(price=10, size=15, side=OrderSide.BUY, id="2") delta2 = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.ADD, order=order2, ts_event_ns=0, ts_recv_ns=0, ) deltas = OrderBookDeltas( instrument_id=AUDUSD, level=BookLevel.L2, deltas=[delta1, delta2], ts_event_ns=0, ts_recv_ns=0, ) # Act result = OrderBookDeltas.to_dict(deltas) # Assert assert result == { "type": "OrderBookDeltas", "instrument_id": "AUD/USD.SIM", "level": "L2", "deltas": '[{"type": "OrderBookDelta", "instrument_id": "AUD/USD.SIM", "level": "L2", "delta_type": "ADD", "order_price": 10.0, "order_size": 5.0, "order_side": "BUY", "order_id": "1", "ts_event_ns": 0, "ts_recv_ns": 0}, {"type": "OrderBookDelta", "instrument_id": "AUD/USD.SIM", "level": "L2", "delta_type": "ADD", "order_price": 10.0, "order_size": 15.0, "order_side": "BUY", "order_id": "2", "ts_event_ns": 0, "ts_recv_ns": 0}]', # noqa "ts_event_ns": 0, "ts_recv_ns": 0, }
def test_simulate_order_fills_l3(): ladder = Ladder(False, 4, 4) orders = [ Order(price=15, volume=1, side=OrderSide.SELL, id="1"), Order(price=16, volume=2, side=OrderSide.SELL, id="2"), Order(price=16, volume=3, side=OrderSide.SELL, id="3"), Order(price=20, volume=10, side=OrderSide.SELL, id="4"), ] for order in orders: ladder.add(order) fills = ladder.simulate_order_fills( order=Order(price=16.5, volume=4, side=OrderSide.BUY, id="1")) expected = [ (Price("15.0000"), Quantity("1.0000")), (Price("16.0000"), Quantity("2.0000")), (Price("16.0000"), Quantity("1.0000")), ] assert fills == expected
def test_add_orders_to_book(self): # Arrange book = OrderBook.create( instrument_id=AUDUSD, level=OrderBookLevel.L2, price_precision=2, size_precision=2, ) # Act book.add(Order(price=10, volume=5, side=OrderSide.BUY)) book.add(Order(price=11, volume=6, side=OrderSide.SELL)) # Assert assert book.best_bid_price() == 10 assert book.best_ask_price() == 11 assert book.best_bid_qty() == 5 assert book.best_ask_qty() == 6 assert book.spread() == 1
def test_orderbook_operation(empty_book): clock = TestClock() op = OrderBookOperation( op_type=OrderBookOperationType.UPDATE, order=Order( 0.5814, 672.45, OrderSide.SELL, "4a25c3f6-76e7-7584-c5a3-4ec84808e240" ), timestamp_ns=clock.timestamp(), ) empty_book.apply_operation(op) assert empty_book.best_ask_price() == 0.5814