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 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_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 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_orderbook_operation(empty_book): clock = TestClock() op = OrderBookDelta( delta_type=OrderBookDeltaType.UPDATE, order=Order( 0.5814, 672.45, OrderSide.SELL, "4a25c3f6-76e7-7584-c5a3-4ec84808e240" ), instrument_id=TestStubs.audusd_id(), timestamp_ns=clock.timestamp(), ) empty_book.apply_delta(op) assert empty_book.best_ask_price() == 0.5814
def test_hash_str_and_repr(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, Assert assert isinstance(hash(deltas), int) assert ( str(deltas) == "OrderBookDeltas('AUD/USD.SIM', level=L2, [OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 5.0, BUY, 1), ts_recv_ns=0), OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 15.0, BUY, 2), ts_recv_ns=0)], ts_recv_ns=0)" # noqa ) assert ( repr(deltas) == "OrderBookDeltas('AUD/USD.SIM', level=L2, [OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 5.0, BUY, 1), ts_recv_ns=0), OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 15.0, BUY, 2), ts_recv_ns=0)], ts_recv_ns=0)" # noqa )
def test_timestamp_ns(empty_l2_book, clock): delta = OrderBookDelta( instrument_id=TestStubs.audusd_id(), level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( 0.5900, 672.45, OrderSide.SELL, "4a25c3f6-76e7-7584-c5a3-4ec84808e240", ), timestamp_ns=clock.timestamp(), ) empty_l2_book.apply_delta(delta) assert empty_l2_book.timestamp_ns == delta.timestamp_ns
def test_orderbook_operation_update(empty_l2_book, clock): delta = OrderBookDelta( instrument_id=TestStubs.audusd_id(), level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.UPDATE, order=Order( 0.5814, 672.45, OrderSide.SELL, "4a25c3f6-76e7-7584-c5a3-4ec84808e240", ), timestamp_ns=clock.timestamp(), ) empty_l2_book.apply_delta(delta) assert empty_l2_book.best_ask_price() == 0.5814
def test_from_dict_returns_expected_clear(self): # Arrange delta = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.CLEAR, order=None, ts_event_ns=0, ts_recv_ns=0, ) # Act result = OrderBookDelta.from_dict(OrderBookDelta.to_dict(delta)) # Assert assert result == delta
def test_serialize_and_deserialize_order_book_delta(self): delta = OrderBookDelta( instrument_id=TestStubs.audusd_id(), level=BookLevel.L2, delta_type=DeltaType.CLEAR, order=None, ts_event_ns=0, ts_recv_ns=0, ) serialized = to_parquet(buff=self.buffer, objects=[delta]) deserialized = from_parquet(serialized) # Assert assert deserialized == [delta]
def test_from_dict_returns_expected_delta(self): # Arrange order = Order(price=10, size=5, side=OrderSide.BUY) 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.from_dict(OrderBookDelta.to_dict(delta)) # Assert assert result == delta
def test_orderbook_operations(empty_book): delta = OrderBookDelta( delta_type=OrderBookDeltaType.UPDATE, order=Order( 0.5814, 672.45, OrderSide.SELL, "4a25c3f6-76e7-7584-c5a3-4ec84808e240" ), instrument_id=TestStubs.audusd_id(), timestamp_ns=pd.Timestamp.utcnow().timestamp() * 1e9, ) deltas = OrderBookDeltas( instrument_id=TestStubs.audusd_id(), level=OrderBookLevel.L2, deltas=[delta], timestamp_ns=pd.Timestamp.utcnow().timestamp() * 1e9, ) empty_book.apply_deltas(deltas) assert empty_book.best_ask_price() == 0.5814
def test_repr(self): # Arrange order = Order(price=10, volume=5, side=OrderSide.BUY) op = OrderBookDelta( delta_type=OrderBookDeltaType.ADD, order=order, instrument_id=AUDUSD, timestamp_ns=0, ) print(repr(op)) # Act # Assert assert ( repr(op) == f"OrderBookDelta(op_type=ADD, order=Order(10.0, 5.0, BUY, {order.id}), timestamp_ns=0)" )
def test_repr(self): # Arrange order = Order(price=10, volume=5, side=OrderSide.BUY) op = OrderBookDelta( instrument_id=AUDUSD, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=order, timestamp_origin_ns=0, timestamp_ns=0, ) print(repr(op)) # Act # Assert assert ( repr(op) == f"OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 5.0, BUY, {order.id}), timestamp_ns=0)" )
def test_hash_str_and_repr(self): # Arrange order = Order(price=10, size=5, side=OrderSide.BUY) delta = OrderBookDelta( instrument_id=AUDUSD, level=BookLevel.L2, delta_type=DeltaType.ADD, order=order, ts_event_ns=0, ts_recv_ns=0, ) # Act, Assert assert isinstance(hash(delta), int) assert ( str(delta) == f"OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 5.0, BUY, {order.id}), ts_recv_ns=0)" ) assert ( repr(delta) == f"OrderBookDelta('AUD/USD.SIM', level=L2, delta_type=ADD, order=Order(10.0, 5.0, BUY, {order.id}), ts_recv_ns=0)" )
def test_add_order_book_operations_adds_to_container(self): # Arrange data = BacktestDataContainer() deltas = [ OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order(price=Price("13.0"), volume=Quantity("40"), side=OrderSide.SELL), timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order(price=Price("12.0"), volume=Quantity("30"), side=OrderSide.SELL), timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order(price=Price("11.0"), volume=Quantity("20"), side=OrderSide.SELL), timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order(price=Price("10.0"), volume=Quantity("20"), side=OrderSide.BUY), timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order(price=Price("9.0"), volume=Quantity("30"), side=OrderSide.BUY), timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order(price=Price("0.0"), volume=Quantity("40"), side=OrderSide.BUY), timestamp_ns=0, ), ] operations1 = OrderBookDeltas( instrument_id=ETHUSDT_BINANCE.id, level=OrderBookLevel.L2, deltas=deltas, timestamp_ns=0, ) operations2 = OrderBookDeltas( instrument_id=ETHUSDT_BINANCE.id, level=OrderBookLevel.L2, deltas=deltas, timestamp_ns=1000, ) # Act data.add_order_book_data([operations2, operations1]) # <-- not sorted # Assert assert ClientId("BINANCE") in data.clients assert ETHUSDT_BINANCE.id in data.books assert data.order_book_data == [operations1, operations2] # <-- sorted
def test_add_order_book_operations_adds_to_container(self): # Arrange engine = BacktestEngine() engine.add_instrument(AUDUSD_SIM) engine.add_instrument(ETHUSDT_BINANCE) deltas = [ OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( price=Price.from_str("13.0"), volume=Quantity.from_str("40"), side=OrderSide.SELL, ), timestamp_origin_ns=0, timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( price=Price.from_str("12.0"), volume=Quantity.from_str("30"), side=OrderSide.SELL, ), timestamp_origin_ns=0, timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( price=Price.from_str("11.0"), volume=Quantity.from_str("20"), side=OrderSide.SELL, ), timestamp_origin_ns=0, timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( price=Price.from_str("10.0"), volume=Quantity.from_str("20"), side=OrderSide.BUY, ), timestamp_origin_ns=0, timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( price=Price.from_str("9.0"), volume=Quantity.from_str("30"), side=OrderSide.BUY, ), timestamp_origin_ns=0, timestamp_ns=0, ), OrderBookDelta( instrument_id=AUDUSD_SIM.id, level=OrderBookLevel.L2, delta_type=OrderBookDeltaType.ADD, order=Order( price=Price.from_str("0.0"), volume=Quantity.from_str("40"), side=OrderSide.BUY, ), timestamp_origin_ns=0, timestamp_ns=0, ), ] operations1 = OrderBookDeltas( instrument_id=ETHUSDT_BINANCE.id, level=OrderBookLevel.L2, deltas=deltas, timestamp_origin_ns=0, timestamp_ns=0, ) operations2 = OrderBookDeltas( instrument_id=ETHUSDT_BINANCE.id, level=OrderBookLevel.L2, deltas=deltas, timestamp_origin_ns=1000, timestamp_ns=1000, ) # Act engine.add_order_book_data([operations2, operations1]) # <-- not sorted
def test_add_order_book_operations_adds_to_container(self): # Arrange data = BacktestDataContainer() deltas = [ OrderBookDelta( OrderBookDeltaType.ADD, Order(13.0, 40, OrderSide.SELL), instrument_id=AUDUSD_SIM.id, timestamp_ns=0, ), OrderBookDelta( OrderBookDeltaType.ADD, Order(12.0, 30, OrderSide.SELL), instrument_id=AUDUSD_SIM.id, timestamp_ns=0, ), OrderBookDelta( OrderBookDeltaType.ADD, Order(11.0, 20, OrderSide.SELL), instrument_id=AUDUSD_SIM.id, timestamp_ns=0, ), OrderBookDelta( OrderBookDeltaType.ADD, Order(10.0, 20, OrderSide.BUY), instrument_id=AUDUSD_SIM.id, timestamp_ns=0, ), OrderBookDelta( OrderBookDeltaType.ADD, Order(9.0, 30, OrderSide.BUY), instrument_id=AUDUSD_SIM.id, timestamp_ns=0, ), OrderBookDelta( OrderBookDeltaType.ADD, Order(0.0, 40, OrderSide.BUY), instrument_id=AUDUSD_SIM.id, timestamp_ns=0, ), ] operations1 = OrderBookDeltas( instrument_id=ETHUSDT_BINANCE.id, level=OrderBookLevel.L2, deltas=deltas, timestamp_ns=0, ) operations2 = OrderBookDeltas( instrument_id=ETHUSDT_BINANCE.id, level=OrderBookLevel.L2, deltas=deltas, timestamp_ns=1000, ) # Act data.add_order_book_data([operations2, operations1]) # <-- not sorted # Assert assert ClientId("BINANCE") in data.clients assert ETHUSDT_BINANCE.id in data.books assert data.order_book_data == [operations1, operations2] # <-- sorted