async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue): while True: try: trading_pairs: List[str] = await self.get_trading_pairs() for trading_pair in trading_pairs: async with websockets.connect(BITFINEX_WS_URI) as ws: payload: Dict[str, Any] = { "event": "subscribe", "channel": "book", "prec": "P0", "symbol": convert_to_exchange_trading_pair(trading_pair), } await ws.send(ujson.dumps(payload)) await asyncio.wait_for(ws.recv(), timeout=self.MESSAGE_TIMEOUT ) # response await asyncio.wait_for(ws.recv(), timeout=self.MESSAGE_TIMEOUT ) # subscribe info raw_snapshot = await asyncio.wait_for( ws.recv(), timeout=self.MESSAGE_TIMEOUT) # snapshot snapshot = self._prepare_snapshot( trading_pair, [ BookStructure(*i) for i in ujson.loads(raw_snapshot)[1] ]) snapshot_timestamp: float = time.time() snapshot_msg: OrderBookMessage = BitfinexOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp) output.put_nowait(snapshot_msg) async for raw_msg in self._get_response(ws): msg = self._parse_raw_update(trading_pair, raw_msg) if msg is not None: output.put_nowait(msg) except Exception as err: self.logger().error(err) self.logger().network( "Unexpected error with WebSocket connection.", exc_info=True, app_warning_msg= "Unexpected error with WebSocket connection. " f"Retrying in {int(self.MESSAGE_TIMEOUT)} seconds. " "Check network connection.") await asyncio.sleep(5)
def _transform_message_from_exchange( self, msg) -> Optional[BitfinexOrderBookMessage]: order_book_message: BitfinexOrderBookMessage = BitfinexOrderBook.diff_message_from_exchange( msg, time.time()) if any([ order_book_message.type_heartbeat, order_book_message.event_auth, order_book_message.event_info, ]): # skip unneeded events and types return return order_book_message
async def get_new_order_book(self, trading_pair: str) -> OrderBook: async with aiohttp.ClientSession() as client: snapshot: Dict[str, any] = await self.get_snapshot(client, trading_pair) snapshot_timestamp: float = time.time() snapshot_msg: OrderBookMessage = BitfinexOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp ) active_order_tracker: BitfinexActiveOrderTracker = BitfinexActiveOrderTracker() bids, asks = active_order_tracker.convert_snapshot_message_to_order_book_row(snapshot_msg) order_book = self.order_book_create_function() order_book.apply_snapshot(bids, asks, snapshot_msg.update_id) return order_book
async def get_tracking_pairs(self) -> Dict[str, OrderBookTrackerEntry]: result: Dict[str, OrderBookTrackerEntry] = {} trading_pairs: List[str] = await self.get_trading_pairs() number_of_pairs: int = len(trading_pairs) async with aiohttp.ClientSession() as client: for idx, trading_pair in enumerate(trading_pairs): try: snapshot: Dict[str, Any] = await self.get_snapshot(client, trading_pair) snapshot_timestamp: float = time.time() snapshot_msg: OrderBookMessage = BitfinexOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp ) order_book: OrderBook = self.order_book_create_function() active_order_tracker: BitfinexActiveOrderTracker = BitfinexActiveOrderTracker() order_book.apply_snapshot( snapshot_msg.bids, snapshot_msg.asks, snapshot_msg.update_id ) result[trading_pair] = BitfinexOrderBookTrackerEntry( trading_pair, snapshot_timestamp, order_book, active_order_tracker ) self.logger().info( f"Initialized order book for {trading_pair}. " f"{idx+1}/{number_of_pairs} completed." ) await asyncio.sleep(self.STEP_TIME_SLEEP) except IOError: 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." ) except Exception: self.logger().error( f"Error initializing order book for {trading_pair}. ", exc_info=True ) return result
async def listen_for_order_book_snapshots(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue): while True: trading_pairs: List[str] = await self.get_trading_pairs() try: 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: OrderBookMessage = BitfinexOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp) output.put_nowait(snapshot_msg) self.logger().debug( f"Saved order book snapshot for {trading_pair}" ) await asyncio.sleep( self.TIME_SLEEP_BETWEEN_REQUESTS) except asyncio.CancelledError: raise except Exception as err: self.logger().error("Listening snapshots", err) self.logger().network( "Unexpected error with HTTP connection.", exc_info=True, app_warning_msg= "Unexpected error with HTTP connection. " f"Retrying in {self.TIME_SLEEP_BETWEEN_REQUESTS} sec." "Check network connection.") await asyncio.sleep( self.TIME_SLEEP_BETWEEN_REQUESTS) 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 as err: self.logger().error("Listening snapshots", err) self.logger().error("Unexpected error", exc_info=True) await asyncio.sleep(self.TIME_SLEEP_BETWEEN_REQUESTS)
async def listen_for_trades(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue): while True: try: trading_pairs: List[str] = await self.get_trading_pairs() for trading_pair in trading_pairs: async with websockets.connect(BITFINEX_WS_URI) as ws: payload: Dict[str, Any] = { "event": "subscribe", "channel": "trades", "symbol": convert_to_exchange_trading_pair(trading_pair), } await ws.send(ujson.dumps(payload)) await asyncio.wait_for(ws.recv(), timeout=self.MESSAGE_TIMEOUT ) # response await asyncio.wait_for(ws.recv(), timeout=self.MESSAGE_TIMEOUT ) # subscribe info await asyncio.wait_for(ws.recv(), timeout=self.MESSAGE_TIMEOUT ) # snapshot async for raw_msg in self._get_response(ws): msg = self._prepare_trade(raw_msg) if msg: msg_book: OrderBookMessage = BitfinexOrderBook.trade_message_from_exchange( msg, metadata={"symbol": f"{trading_pair}"}) output.put_nowait(msg_book) except Exception as err: self.logger().error(err) self.logger().network( "Unexpected error with WebSocket connection.", exc_info=True, app_warning_msg= "Unexpected error with WebSocket connection. " f"Retrying in {int(self.MESSAGE_TIMEOUT)} seconds. " "Check network connection.") await asyncio.sleep(5)