def test_l3_feed(): book = L3OrderBook( instrument_id=TestStubs.audusd_id(), price_precision=5, size_precision=0, ) # Updates that cause the book to fail integrity checks will be deleted # immediately, but we may get also delete later. skip_deletes = [] i = 0 for i, m in enumerate(TestDataProvider.l3_feed()): # noqa (B007) if m["op"] == "update": book.update(order=m["order"]) try: book.check_integrity() except AssertionError: book.delete(order=m["order"]) skip_deletes.append(m["order"].id) elif m["op"] == "delete" and m["order"].id not in skip_deletes: book.delete(order=m["order"]) book.check_integrity() assert i == 100_047 assert book.best_ask_level().price == 61405.27923706 assert book.best_ask_level().volume() == 0.12227 assert book.best_bid_level().price == Price.from_int(61391) assert book.best_bid_level().volume() == 1
def test_from_int_returns_expected_value(self): # Arrange, Act price = Price.from_int(100) # Assert assert str(price) == "100" assert price.precision == 0
def price_to_probability(price: str) -> Price: PyCondition.type(price, str, "price", "str") PyCondition.positive(float(price), "price") price = Price.from_str(price) if price in BETFAIR_PRICE_TO_PROBABILITY_MAP: return BETFAIR_PRICE_TO_PROBABILITY_MAP[price] else: # This is likely a trade tick that has been currency adjusted, simply return the nearest price value = Price.from_int(1) / price bid = BETFAIR_TICK_SCHEME.next_bid_price(value=value) ask = BETFAIR_TICK_SCHEME.next_ask_price(value=value) if abs(bid - value) < abs(ask - value): return bid else: return ask
def test_update_order(self): # Arrange instrument = IBTestStubs.instrument("AAPL") contract_details = IBTestStubs.contract_details("AAPL") contract = contract_details.contract order = IBTestStubs.create_order() self.instrument_setup(instrument=instrument, contract_details=contract_details) self.exec_client._ib_insync_orders[ TestIdStubs.client_order_id()] = Trade(contract=contract, order=order) # Act command = TestCommandStubs.modify_order_command( instrument_id=instrument.id, price=Price.from_int(10), quantity=Quantity.from_str("100"), ) with patch.object(self.exec_client._client, "placeOrder") as mock: self.exec_client.modify_order(command=command) # Assert expected = { "contract": Contract( secType="STK", conId=265598, symbol="AAPL", exchange="SMART", primaryExchange="NASDAQ", currency="USD", localSymbol="AAPL", tradingClass="NMS", ), "order": LimitOrder(action="BUY", totalQuantity=100, lmtPrice=10.0), } name, args, kwargs = mock.mock_calls[0] # Can't directly compare kwargs for some reason? assert kwargs["contract"] == expected["contract"] assert kwargs["order"].action == expected["order"].action assert kwargs["order"].totalQuantity == expected["order"].totalQuantity assert kwargs["order"].lmtPrice == expected["order"].lmtPrice
def test_submit_limit_order_aggressive_multiple_levels(self): # Arrange: Prepare market self.cache.add_instrument(USDJPY_SIM) quote = QuoteTick( instrument_id=USDJPY_SIM.id, bid=Price.from_str("110.000"), ask=Price.from_str("110.010"), bid_size=Quantity.from_int(1500000), ask_size=Quantity.from_int(1500000), ts_event=0, ts_init=0, ) self.data_engine.process(quote) snapshot = TestDataStubs.order_book_snapshot( instrument_id=USDJPY_SIM.id, bid_volume=1000, ask_volume=1000, ) self.data_engine.process(snapshot) self.exchange.process_order_book(snapshot) # Create order order = self.strategy.order_factory.limit( instrument_id=USDJPY_SIM.id, order_side=OrderSide.BUY, quantity=Quantity.from_int(2000), price=Price.from_int(20), post_only=False, ) # Act self.strategy.submit_order(order) self.exchange.process(0) # Assert assert order.status == OrderStatus.FILLED assert order.filled_qty == Decimal("2000.0") # No slippage assert order.avg_px == Decimal("15.33333333333333333333333333") assert self.exchange.get_account().balance_total(USD) == Money( 999999.96, USD)
def test_pnl_calculation_from_trading_technologies_example(self): # https://www.tradingtechnologies.com/xtrader-help/fix-adapter-reference/pl-calculation-algorithm/understanding-pl-calculations/ # noqa # Arrange order1 = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(12), ) order2 = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(17), ) order3 = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.SELL, Quantity.from_int(9), ) order4 = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.SELL, Quantity.from_int(4), ) order5 = self.order_factory.market( ETHUSDT_BINANCE.id, OrderSide.BUY, Quantity.from_int(3), ) # Act fill1 = TestStubs.event_order_filled( order1, instrument=ETHUSDT_BINANCE, position_id=PositionId("P-19700101-000000-000-001-1"), last_px=Price.from_int(100), ) position = Position(instrument=ETHUSDT_BINANCE, fill=fill1) fill2 = TestStubs.event_order_filled( order2, instrument=ETHUSDT_BINANCE, position_id=PositionId("P-19700101-000000-000-001-1"), last_px=Price.from_int(99), ) position.apply(fill2) self.assertEqual(Quantity.from_int(29), position.quantity) self.assertEqual(Money(-0.28830000, USDT), position.realized_pnl) self.assertEqual(Decimal("99.41379310344827586206896552"), position.avg_px_open) fill3 = TestStubs.event_order_filled( order3, instrument=ETHUSDT_BINANCE, position_id=PositionId("P-19700101-000000-000-001-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_int(101), ) position.apply(fill3) self.assertEqual(Quantity.from_int(20), position.quantity) self.assertEqual(Money(13.89666207, USDT), position.realized_pnl) self.assertEqual(Decimal("99.41379310344827586206896552"), position.avg_px_open) fill4 = TestStubs.event_order_filled( order4, instrument=ETHUSDT_BINANCE, position_id=PositionId("P-19700101-000000-000-001-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_int(105), ) position.apply(fill4) self.assertEqual(Quantity.from_int(16), position.quantity) self.assertEqual(Money(36.19948966, USDT), position.realized_pnl) self.assertEqual(Decimal("99.41379310344827586206896552"), position.avg_px_open) fill5 = TestStubs.event_order_filled( order5, instrument=ETHUSDT_BINANCE, position_id=PositionId("P-19700101-000000-000-001-1"), strategy_id=StrategyId("S-001"), last_px=Price.from_int(103), ) position.apply(fill5) self.assertEqual(Quantity.from_int(19), position.quantity) self.assertEqual(Money(36.16858966, USDT), position.realized_pnl) self.assertEqual(Decimal("99.98003629764065335753176042"), position.avg_px_open) self.assertEqual( "Position(LONG 19.00000 ETH/USDT.BINANCE, id=P-19700101-000000-000-001-1)", repr(position), )
(2, 3, 0.02), (3, 4, 0.05), (4, 6, 0.1), (6, 10, 0.2), (10, 20, 0.5), (20, 30, 1), (30, 50, 2), (50, 100, 5), (100, 1010, 10), ] BETFAIR_PRICES = list( reversed( TieredTickScheme(name="betfair_prob", tiers=BETFAIR_PRICE_TIERS).ticks)) BETFAIR_PROBABILITIES = [ Price(Price.from_int(1) / tick, precision=BETFAIR_PRICE_PRECISION) for tick in BETFAIR_PRICES ] BETFAIR_PRICE_TO_PROBABILITY_MAP = { price: prob for price, prob in zip(BETFAIR_PRICES, BETFAIR_PROBABILITIES) } BETFAIR_PROBABILITY_TO_PRICE_MAP = { price: prob for price, prob in zip(BETFAIR_PROBABILITIES, BETFAIR_PRICES) } MAX_BET_PROB = max(BETFAIR_PROBABILITY_TO_PRICE_MAP) MIN_BET_PROB = min(BETFAIR_PROBABILITY_TO_PRICE_MAP) BETFAIR_TICK_SCHEME = TieredTickScheme( name="BETFAIR",