def test_track_single_book_apply_snapshot(self):
        snapshot_data = [
            NdaxOrderBookEntry(*[
                93617617, 1, 1626788175000, 0, 37800.0, 1, 37750.0, 1, 0.015, 0
            ]),
            NdaxOrderBookEntry(*[
                93617617, 1, 1626788175000, 0, 37800.0, 1, 37751.0, 1, 0.015, 1
            ])
        ]
        snapshot_msg = NdaxOrderBook.snapshot_message_from_exchange(
            msg={"data": snapshot_data},
            timestamp=1626788175000,
            metadata={
                "trading_pair": self.trading_pair,
                "instrument_id": self.instrument_id
            })
        self.simulate_queue_order_book_messages(snapshot_msg)

        with self.assertRaises(asyncio.TimeoutError):
            # Allow 5 seconds for tracker to process some messages.
            self.tracking_task = self.ev_loop.create_task(
                asyncio.wait_for(
                    self.tracker._track_single_book(self.trading_pair), 2.0))
            self.ev_loop.run_until_complete(self.tracking_task)

        self.assertEqual(
            0, self.tracker.order_books[self.trading_pair].snapshot_uid)
Exemple #2
0
    def test_get_order_book_data(self, mock_api):
        self.mocking_assistant.configure_http_request_mock(mock_api)
        self.simulate_trading_pair_ids_initialized()
        mock_response: List[List[Any]] = [
            # mdUpdateId, accountId, actionDateTime, actionType, lastTradePrice, orderId, price, productPairCode, quantity, side
            [93617617, 1, 1626788175416, 0, 37813.22, 1, 37750.6, 1, 0.014698, 0]
        ]
        self.mocking_assistant.add_http_response(mock_api, 200, mock_response)

        results = self.ev_loop.run_until_complete(
            asyncio.gather(self.data_source.get_order_book_data(self.trading_pair)))
        result = results[0]

        self.assertTrue("data" in result)
        self.assertGreaterEqual(len(result["data"]), 0)
        self.assertEqual(NdaxOrderBookEntry(*mock_response[0]), result["data"][0])
    async def get_order_book_data(
            self,
            trading_pair: str,
            domain: Optional[str] = None,
            throttler: Optional[AsyncThrottler] = None) -> Dict[str, any]:
        """Retrieves entire orderbook snapshot of the specified trading pair via the REST API.

        Args:
            trading_pair (str): Trading pair of the particular orderbook.
            domain (str): The label of the variant of the connector that is being used.
            throttler (AsyncThrottler): API-requests throttler to use.

        Returns:
            Dict[str, any]: Parsed API Response.
        """
        if not len(self._trading_pair_id_map) > 0:
            await self.init_trading_pair_ids(domain)
        params = {
            "OMSId": 1,
            "InstrumentId": self._trading_pair_id_map[trading_pair],
            "Depth": 200,
        }

        throttler = throttler or self._get_throttler_instance()
        async with throttler.execute_task(CONSTANTS.ORDER_BOOK_URL):
            async with self._shared_client.get(
                    f"{ndax_utils.rest_api_url(domain) + CONSTANTS.ORDER_BOOK_URL}",
                    params=params) as response:
                status = response.status
                if status != 200:
                    raise IOError(
                        f"Error fetching OrderBook for {trading_pair} at {CONSTANTS.ORDER_BOOK_URL}. "
                        f"HTTP {status}. Response: {await response.json()}")

                response_ls: List[Any] = await response.json()
                orderbook_entries: List[NdaxOrderBookEntry] = [
                    NdaxOrderBookEntry(*entry) for entry in response_ls
                ]
                return {
                    "data": orderbook_entries,
                    "timestamp": int(time.time() * 1e3)
                }
Exemple #4
0
    def test_delete_sell_order_book_entry_always_has_zero_amount(self):
        entries = [
            NdaxOrderBookEntry(mdUpdateId=1,
                               accountId=1,
                               actionDateTime=1627935956059,
                               actionType=2,
                               lastTradePrice=42211.51,
                               orderId=1,
                               price=41508.19,
                               productPairCode=5,
                               quantity=1.5,
                               side=1)
        ]
        content = {"data": entries}
        message = NdaxOrderBookMessage(message_type=OrderBookMessageType.DIFF,
                                       content=content,
                                       timestamp=time.time())
        asks = message.asks

        self.assertEqual(1, len(asks))
        self.assertEqual(41508.19, asks[0].price)
        self.assertEqual(0.0, asks[0].amount)
        self.assertEqual(1, asks[0].update_id)
    async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop,
                                          output: asyncio.Queue):
        """
        Listen for orderbook diffs using WebSocket API.
        """
        if not len(self._trading_pair_id_map) > 0:
            await self.init_trading_pair_ids(self._domain, self._throttler,
                                             self._shared_client)

        while True:
            try:
                ws_adaptor: NdaxWebSocketAdaptor = await self._create_websocket_connection(
                )
                for trading_pair in self._trading_pairs:
                    payload = {
                        "OMSId": 1,
                        "Symbol":
                        convert_to_exchange_trading_pair(trading_pair),
                        "Depth": 200
                    }
                    async with self._throttler.execute_task(
                            CONSTANTS.WS_ORDER_BOOK_CHANNEL):
                        await ws_adaptor.send_request(
                            endpoint_name=CONSTANTS.WS_ORDER_BOOK_CHANNEL,
                            payload=payload)
                async for raw_msg in ws_adaptor.iter_messages():
                    payload = NdaxWebSocketAdaptor.payload_from_raw_message(
                        raw_msg)
                    msg_event: str = NdaxWebSocketAdaptor.endpoint_from_raw_message(
                        raw_msg)
                    if msg_event in [
                            CONSTANTS.WS_ORDER_BOOK_CHANNEL,
                            CONSTANTS.WS_ORDER_BOOK_L2_UPDATE_EVENT
                    ]:
                        msg_data: List[NdaxOrderBookEntry] = [
                            NdaxOrderBookEntry(*entry) for entry in payload
                        ]
                        msg_timestamp: int = int(time.time() * 1e3)
                        msg_product_code: int = msg_data[0].productPairCode

                        content = {"data": msg_data}
                        msg_trading_pair: Optional[str] = None

                        for trading_pair, instrument_id in self._trading_pair_id_map.items(
                        ):
                            if msg_product_code == instrument_id:
                                msg_trading_pair = trading_pair
                                break

                        if msg_trading_pair:
                            metadata = {
                                "trading_pair": msg_trading_pair,
                                "instrument_id": msg_product_code,
                            }

                            order_book_message = None
                            if msg_event == CONSTANTS.WS_ORDER_BOOK_CHANNEL:
                                order_book_message: NdaxOrderBookMessage = NdaxOrderBook.snapshot_message_from_exchange(
                                    msg=content,
                                    timestamp=msg_timestamp,
                                    metadata=metadata)
                            elif msg_event == CONSTANTS.WS_ORDER_BOOK_L2_UPDATE_EVENT:
                                order_book_message: NdaxOrderBookMessage = NdaxOrderBook.diff_message_from_exchange(
                                    msg=content,
                                    timestamp=msg_timestamp,
                                    metadata=metadata)
                            self._last_traded_prices[
                                order_book_message.
                                trading_pair] = order_book_message.last_traded_price
                            await output.put(order_book_message)

            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().network(
                    "Unexpected error with WebSocket connection.",
                    exc_info=True,
                    app_warning_msg=
                    "Unexpected error with WebSocket connection. Retrying in 30 seconds. "
                    "Check network connection.")
                if ws_adaptor:
                    await ws_adaptor.close()
                await self._sleep(30.0)