示例#1
0
    async def test_duplicate_execution_id(self):
        # Arrange
        await self._setup_account()
        for update in BetfairStreaming.ocm_DUPLICATE_EXECUTION():
            self._setup_exec_client_and_cache(update)

        # # Load submitted orders
        # for client_order_id in (ClientOrderId('0'), ClientOrderId('1')):
        #     order = BetfairTestStubs.make_order(
        #         price=Price.from_str("0.5"), quantity=Quantity.from_int(10), client_order_id=client_order_id
        #     )
        #     command = BetfairTestStubs.submit_order_command(order=order)
        #     self.client.submit_order(command)
        # await asyncio.sleep(0)

        # Act
        for update in BetfairStreaming.ocm_DUPLICATE_EXECUTION():
            self._setup_exec_client_and_cache(update=update)
            await self.client._handle_order_stream_update(update=update)
            await asyncio.sleep(0)

        # Assert
        _, fill1, cancel, fill2, fill3 = self.messages
        # First order example, partial fill followed by remainder canceled
        assert isinstance(fill1, OrderFilled)
        assert isinstance(cancel, OrderCanceled)
        # Second order example, partial fill followed by remainder filled
        assert (isinstance(fill2, OrderFilled) and fill2.execution_id.value
                == "4721ad7594e7a4a4dffb1bacb0cb45ccdec0747a")
        assert (isinstance(fill3, OrderFilled) and fill3.execution_id.value
                == "8b3e65be779968a3fdf2d72731c848c5153e88cd")
    def test_orderbook_updates(self):
        order_books = {}
        for raw_update in BetfairStreaming.market_updates():
            for update in on_market_update(
                update=raw_update,
                instrument_provider=self.client.instrument_provider(),
            ):
                if len(order_books) > 1 and update.instrument_id != list(order_books)[1]:
                    continue
                print(update)
                if isinstance(update, OrderBookSnapshot):
                    order_books[update.instrument_id] = L2OrderBook(
                        instrument_id=update.instrument_id,
                        price_precision=4,
                        size_precision=4,
                    )
                    order_books[update.instrument_id].apply_snapshot(update)
                elif isinstance(update, OrderBookDeltas):
                    order_books[update.instrument_id].apply_deltas(update)
                elif isinstance(update, TradeTick):
                    pass
                else:
                    raise KeyError

        book = order_books[list(order_books)[0]]
        expected = """bids       price   asks
--------  -------  ---------
          0.8621   [932.64]
          0.8547   [1275.83]
          0.8475   [151.96]
[147.79]  0.8403
[156.74]  0.8333
[11.19]   0.8197"""
        result = book.pprint()
        assert result == expected
示例#3
0
 async def test_betfair_order_cancelled_no_timestamp(self):
     update = BetfairStreaming.ocm_error_fill()
     self._setup_exec_client_and_cache(update)
     for upd in update["oc"][0]["orc"][0]["uo"]:
         self.client._handle_stream_execution_complete_order_update(
             update=upd)
         await asyncio.sleep(1)
 async def test_market_sub_image_market_def(self):
     update = BetfairStreaming.mcm_SUB_IMAGE()
     self.client._on_market_update(update)
     result = [type(event).__name__ for event in self.messages]
     expected = ["InstrumentStatusUpdate"] * 7 + ["OrderBookSnapshot"] * 7
     assert result == expected
     # Check prices are probabilities
     result = set(
         float(order[0])
         for ob_snap in self.messages
         if isinstance(ob_snap, OrderBookSnapshot)
         for order in ob_snap.bids + ob_snap.asks
     )
     expected = set(
         [
             0.0010204,
             0.0076923,
             0.0217391,
             0.0238095,
             0.1724138,
             0.2173913,
             0.3676471,
             0.3937008,
             0.4587156,
             0.5555556,
         ]
     )
     assert result == expected
 def test_market_update_live_image(self):
     self.client._on_market_update(BetfairStreaming.mcm_live_IMAGE())
     result = [type(event).__name__ for event in self.messages]
     expected = (
         ["OrderBookSnapshot"] + ["TradeTick"] * 13 + ["OrderBookSnapshot"] + ["TradeTick"] * 17
     )
     assert result == expected
示例#6
0
    async def test_order_multiple_fills(self):
        # Arrange
        self.exec_engine.start()
        client_order_id = ClientOrderId("1")
        venue_order_id = VenueOrderId("246938411724")
        submitted = BetfairTestStubs.make_submitted_order(
            client_order_id=client_order_id, quantity=Quantity.from_int(20))
        self.cache.add_order(submitted,
                             position_id=BetfairTestStubs.position_id())
        self.client.venue_order_id_to_client_order_id[
            venue_order_id] = client_order_id

        # Act
        for update in BetfairStreaming.ocm_multiple_fills():
            await self.client._handle_order_stream_update(update)
            await asyncio.sleep(0.1)

        # Assert
        result = [fill.last_qty for fill in self.messages]
        expected = [
            Quantity.from_str("16.1900"),
            Quantity.from_str("0.77"),
            Quantity.from_str("0.77"),
        ]
        assert result == expected
示例#7
0
    async def test_order_stream_new_full_image(self):
        update = BetfairStreaming.ocm_NEW_FULL_IMAGE()
        await self._setup_account()
        self._setup_exec_client_and_cache(update=update)

        await self.client._handle_order_stream_update(update=update)
        await asyncio.sleep(0)
        assert len(self.messages) == 4
 def test_orderbook_repr(self):
     self.client._on_market_update(BetfairStreaming.mcm_live_IMAGE())
     ob_snap = self.messages[14]
     ob = L2OrderBook(InstrumentId(Symbol("1"), BETFAIR_VENUE), 5, 5)
     ob.apply_snapshot(ob_snap)
     print(ob.pprint())
     assert ob.best_ask_price() == 0.5882353
     assert ob.best_bid_price() == 0.5847953
示例#9
0
    async def test_order_filled_avp_update(self):
        # Arrange
        update = BetfairStreaming.ocm_filled_different_price()
        self._setup_exec_client_and_cache(update)
        await self._setup_account()

        # Act
        update = BetfairStreaming.generate_order_update(
            price="1.50", size=20, side="B", status="E", avp="1.50", sm=10
        )
        await self.client._handle_order_stream_update(update=update)
        await asyncio.sleep(0)

        update = BetfairStreaming.generate_order_update(
            price="1.30", size=20, side="B", status="E", avp="1.50", sm=10
        )
        await self.client._handle_order_stream_update(update=update)
        await asyncio.sleep(0)
 def test_stream_latency(self):
     logs = []
     self.logger.register_sink(logs.append)
     self.client.start()
     self.client._on_market_update(BetfairStreaming.mcm_latency())
     warning, degrading, degraded = logs[2:]
     assert warning["level"] == "WRN"
     assert warning["msg"] == "Stream unhealthy, waiting for recover"
     assert degraded["msg"] == "DEGRADED."
 def test_market_sub_image_no_market_def(self):
     self.client._on_market_update(
         BetfairStreaming.mcm_SUB_IMAGE_no_market_def())
     result = Counter([type(event).__name__ for event in self.messages])
     expected = Counter({
         "InstrumentStatusUpdate": 270,
         "OrderBookSnapshot": 270,
         "InstrumentClosePrice": 22,
     })
     assert result == expected
 def test_stream_con_true(self):
     logs = []
     self.logger.register_sink(logs.append)
     self.client._on_market_update(BetfairStreaming.mcm_con_true())
     (warning, ) = logs
     assert warning["level"] == "WRN"
     assert (
         warning["msg"] ==
         "Conflated stream - consuming data too slow (data received is delayed)"
     )
示例#13
0
    async def test_various_betfair_order_fill_scenarios(self, price, size, side, status, updates):
        # Arrange
        update = BetfairStreaming.ocm_filled_different_price()
        self._setup_exec_client_and_cache(update)
        await self._setup_account()

        # Act
        for raw in updates:
            update = BetfairStreaming.generate_order_update(
                price=price, size=size, side=side, status=status, **raw
            )
            await self.client._handle_order_stream_update(update=update)
            await asyncio.sleep(0)

        # Assert
        assert len(self.messages) == 1 + len(updates)
        for msg, raw in zip(self.messages[1:], updates):
            assert isinstance(msg, OrderFilled)
            assert msg.last_qty == raw["sm"]
 def test_market_update(self):
     self.client._on_market_update(BetfairStreaming.mcm_UPDATE())
     result = [type(event).__name__ for event in self.messages]
     expected = ["OrderBookDeltas"] * 1
     assert result == expected
     result = [d.action for d in self.messages[0].deltas]
     expected = [BookAction.UPDATE, BookAction.DELETE]
     assert result == expected
     # Ensure order prices are coming through as probability
     update_op = self.messages[0].deltas[0]
     assert update_op.order.price == 0.212766
示例#15
0
    async def test_order_stream_update(self):
        # Arrange
        update = BetfairStreaming.ocm_UPDATE()
        await self._setup_account()
        self._setup_exec_client_and_cache(update=update)

        # Act
        await self.client._handle_order_stream_update(update=update)
        await asyncio.sleep(0)

        # Assert
        assert len(self.messages) == 2
示例#16
0
    async def test_order_stream_filled(self):
        # Arrange
        update = BetfairStreaming.ocm_FILLED()
        self._setup_exec_client_and_cache(update)
        await self._setup_account()

        # Act
        await self.client._handle_order_stream_update(update=update)
        await asyncio.sleep(0)

        # Assert
        assert len(self.messages) == 2
        assert isinstance(self.messages[1], OrderFilled)
        assert self.messages[1].last_px == Price.from_str("0.9090909")
示例#17
0
    async def test_order_stream_filled_multiple_prices(self):
        # Arrange
        await self._setup_account()
        update1 = BetfairStreaming.generate_order_update(
            price="1.50",
            size=20,
            side="B",
            status="E",
            sm=10,
            avp="1.60",
        )
        self._setup_exec_client_and_cache(update1)
        await self.client._handle_order_stream_update(update=update1)
        await asyncio.sleep(0)
        order = self.cache.order(client_order_id=ClientOrderId("0"))
        event = self.messages[-1]
        order.apply(event)

        # Act
        update2 = BetfairStreaming.generate_order_update(
            price="1.50",
            size=20,
            side="B",
            status="EC",
            sm=20,
            avp="1.55",
        )
        self._setup_exec_client_and_cache(update2)
        await self.client._handle_order_stream_update(update=update2)
        await asyncio.sleep(0)

        # Assert
        assert len(self.messages) == 3
        assert isinstance(self.messages[1], OrderFilled)
        assert isinstance(self.messages[2], OrderFilled)
        assert self.messages[1].last_px == price_to_probability("1.60")
        assert self.messages[2].last_px == price_to_probability("1.50")
示例#18
0
    async def test_order_stream_mixed(self):
        # Arrange
        update = BetfairStreaming.ocm_MIXED()
        self._setup_exec_client_and_cache(update)
        await self._setup_account()

        # Act
        await self.client._handle_order_stream_update(update=update)
        await asyncio.sleep(0)

        # Assert
        _, fill1, fill2, cancel = self.messages
        assert isinstance(fill1, OrderFilled) and fill1.venue_order_id.value == "229430281341"
        assert isinstance(fill2, OrderFilled) and fill2.venue_order_id.value == "229430281339"
        assert isinstance(cancel, OrderCanceled) and cancel.venue_order_id.value == "229430281339"
    def test_market_update_runner_removed(self):
        update = BetfairStreaming.market_definition_runner_removed()

        # Setup
        market_def = update["mc"][0]["marketDefinition"]
        market_def["marketId"] = update["mc"][0]["id"]
        instruments = make_instruments(
            market_definition=update["mc"][0]["marketDefinition"],
            currency="GBP")
        self.provider.add_bulk(instruments)

        results = []
        for data in on_market_update(instrument_provider=self.provider,
                                     update=update):
            results.append(data)
        result = [r.status for r in results[:8]]
        expected = [InstrumentStatus.PRE_OPEN] * 7 + [InstrumentStatus.CLOSED]
        assert result == expected
    def test_market_bsp(self):
        # Setup
        update = BetfairStreaming.mcm_BSP()
        provider = self.client.instrument_provider()
        for mc in update[0]["mc"]:
            market_def = {**mc["marketDefinition"], "marketId": mc["id"]}
            instruments = make_instruments(market_definition=market_def, currency="GBP")
            provider.add_bulk(instruments)

        for update in update:
            self.client._on_market_update(update)
        result = Counter([type(event).__name__ for event in self.messages])
        expected = {
            "TradeTick": 95,
            "BSPOrderBookDelta": 30,
            "InstrumentStatusUpdate": 9,
            "OrderBookSnapshot": 8,
            "OrderBookDeltas": 2,
        }
        assert result == expected
 def test_market_resub_delta(self):
     self.client._on_market_update(BetfairStreaming.mcm_RESUB_DELTA())
     result = [type(event).__name__ for event in self.messages]
     expected = ["InstrumentStatusUpdate"] * 12 + ["OrderBookDeltas"] * 269
     assert result == expected
 def test_market_update_md(self):
     self.client._on_market_update(BetfairStreaming.mcm_UPDATE_md())
     result = [type(event).__name__ for event in self.messages]
     expected = ["InstrumentStatusUpdate"] * 2
     assert result == expected
 def test_market_heartbeat(self):
     self.client._on_market_update(BetfairStreaming.mcm_HEARTBEAT())
 def test_market_update_live_update(self):
     self.client._on_market_update(BetfairStreaming.mcm_live_UPDATE())
     result = [type(event).__name__ for event in self.messages]
     expected = ["TradeTick", "OrderBookDeltas"]
     assert result == expected
 def test_betfair_ticker(self):
     self.client._on_market_update(BetfairStreaming.mcm_UPDATE_tv())
     ticker: BetfairTicker = self.messages[1]
     assert ticker.last_traded_price == Price.from_str("0.3174603")
     assert ticker.traded_volume == Quantity.from_str("364.45")