async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue): while True: try: trading_pairs_full_list: List[str] = await self.get_trading_pairs() trading_pairs_partial_lists: List[List[str]] = [ trading_pairs_full_list[m: m + IDEX_WS_TRADING_PAIRS_SUBSCRIPTION_LIMIT] for m in range(0, len(trading_pairs_full_list), IDEX_WS_TRADING_PAIRS_SUBSCRIPTION_LIMIT)] for trading_pairs in trading_pairs_partial_lists: async with websockets.connect(IDEX_WS_URL) as ws: ws: websockets.WebSocketClientProtocol = ws await self._send_handshake(ws) async for raw_message in self._inner_messages(ws): decoded: Dict[str, Any] = ujson.loads(raw_message) request: str = decoded.get("request") diff_messages: List[Dict[str, Any]] = [] # after response from handshake, send subscribe message if request == "handshake": await self._send_subscribe(ws, trading_pairs, decoded) continue event: str = decoded.get("event") payload: Dict[str, Any] = ujson.loads(decoded["payload"]) # payload is stringified json if event == "market_orders": orders: List[str, Any] = payload["orders"] market: str = payload["market"] diff_messages = [{**o, "event": event, "market": market} for o in orders] elif event == "market_cancels": cancels: List[str, Any] = payload["cancels"] market: str = payload["market"] diff_messages = [{**c, "event": event, "market": market} for c in cancels] elif event == "market_trades": trades: List[str, Any] = payload["trades"] diff_messages = [{**t, "event": event} for t in trades] else: # ignore message if event is not recognized continue for diff_message in diff_messages: ob_message: IDEXOrderBookMessage = IDEXOrderBook.diff_message_from_exchange( diff_message) output.put_nowait(ob_message) except asyncio.CancelledError: raise except Exception: self.logger().network( f"Error getting order book diff messages.", exc_info=True, app_warning_msg=f"Error getting order book diff messages. Check network connection." ) await asyncio.sleep(30.0)
async def listen_for_order_book_snapshots(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue): await self._get_tracking_pair_done_event.wait() while True: try: trading_pairs: List[str] = await self.get_trading_pairs() async with aiohttp.ClientSession() as client: for trading_pair in trading_pairs: try: snapshot: Dict[str, Any] = await self.get_snapshot( client, trading_pair) snapshot_timestamp: float = time.time() snapshot_msg: IDEXOrderBookMessage = IDEXOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp, {"market": trading_pair}) output.put_nowait(snapshot_msg) self.logger().debug( f"Saved order book snapshot for {trading_pair} at {snapshot_timestamp}" ) await asyncio.sleep(5.0) except asyncio.CancelledError: raise except Exception: self.logger().network( f"Error getting snapshot for {trading_pair}.", exc_info=True, app_warning_msg= f"Error getting snapshot for {trading_pair}. Check network connection." ) await asyncio.sleep(5.0) this_hour: pd.Timestamp = pd.Timestamp.utcnow().replace( minute=0, second=0, microsecond=0) next_hour: pd.Timestamp = this_hour + pd.Timedelta(hours=1) delta: float = next_hour.timestamp() - time.time() await asyncio.sleep(delta) except asyncio.CancelledError: raise except Exception: self.logger().network( f"Unexpected error listening for order book snapshot.", exc_info=True, app_warning_msg= f"Unexpected error listening for order book snapshot. Check network connection." ) await asyncio.sleep(5.0)
async def get_tracking_pairs(self) -> Dict[str, OrderBookTrackerEntry]: # Get the currently active markets async with aiohttp.ClientSession() as client: trading_pairs: List[str] = await self.get_trading_pairs() retval: Dict[str, IDEXOrderBookTrackerEntry] = {} number_of_pairs: int = len(trading_pairs) token_info: Dict[str, Dict[str, Any]] = await self.get_all_token_info() for index, trading_pair in enumerate(trading_pairs): try: snapshot: Dict[str, any] = await self.get_snapshot( client, trading_pair) snapshot_msg: IDEXOrderBookMessage = IDEXOrderBook.snapshot_message_from_exchange( msg=snapshot, timestamp=None, metadata={"market": trading_pair}) quote_asset_symbol, base_asset_symbol = trading_pair.split( "_") base_asset: Dict[str, Any] = token_info[base_asset_symbol] quote_asset: Dict[str, Any] = token_info[quote_asset_symbol] idex_active_order_tracker: IDEXActiveOrderTracker = IDEXActiveOrderTracker( base_asset=base_asset, quote_asset=quote_asset) bids, asks = idex_active_order_tracker.convert_snapshot_message_to_order_book_row( snapshot_msg) snapshot_timestamp: float = idex_active_order_tracker.latest_snapshot_timestamp idex_order_book: OrderBook = self.order_book_create_function( ) idex_order_book.apply_snapshot(bids, asks, snapshot_timestamp) retval[trading_pair] = IDEXOrderBookTrackerEntry( trading_pair, snapshot_timestamp, idex_order_book, idex_active_order_tracker) self.logger().info( f"Initialized order book for {trading_pair}. " f"{index+1}/{number_of_pairs} completed.") await asyncio.sleep(1.0) except Exception: self.logger().error( f"Error initializing order book for {trading_pair}.", exc_info=True) await asyncio.sleep(5) self._get_tracking_pair_done_event.set() return retval