async def get_tracking_pairs(self) -> Dict[str, OrderBookTrackerEntry]: auth: aiohttp.BasicAuth = aiohttp.BasicAuth( login=conf.coinalpha_order_book_api_username, password=conf.coinalpha_order_book_api_password) client_session: aiohttp.ClientSession = await self.get_client_session() response: aiohttp.ClientResponse = await client_session.get( self.SNAPSHOT_REST_URL, auth=auth) timestamp: float = time.time() if response.status != 200: raise EnvironmentError( f"Error fetching order book tracker snapshot from {self.SNAPSHOT_REST_URL}." ) binary_data: bytes = await response.read() order_book_tracker_data: Dict[str, Tuple[ pd.DataFrame, pd.DataFrame]] = pickle.loads(binary_data) retval: Dict[str, OrderBookTrackerEntry] = {} for trading_pair, (bids_df, asks_df) in order_book_tracker_data.items(): order_book: BinanceOrderBook = BinanceOrderBook() order_book.apply_numpy_snapshot(bids_df.values, asks_df.values) retval[trading_pair] = OrderBookTrackerEntry( trading_pair, timestamp, order_book) return retval
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() ws_path: str = "/".join([ f"{trading_pair.lower()}@depth" for trading_pair in trading_pairs ]) stream_url: str = f"{DIFF_STREAM_URL}/{ws_path}" async with websockets.connect(stream_url) as ws: ws: websockets.WebSocketClientProtocol = ws async for raw_msg in self._inner_messages(ws): msg = ujson.loads(raw_msg) order_book_message: OrderBookMessage = BinanceOrderBook.diff_message_from_exchange( msg, time.time()) output.put_nowait(order_book_message) except asyncio.CancelledError: raise except Exception: self.logger().error( "Unexpected error with WebSocket connection. Retrying after 30 seconds...", exc_info=True) await asyncio.sleep(30.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, OrderBookTrackerEntry] = {} number_of_pairs: int = len(trading_pairs) for index, trading_pair in enumerate(trading_pairs): try: snapshot: Dict[str, Any] = await self.get_snapshot( client, trading_pair, 1000) snapshot_timestamp: float = time.time() snapshot_msg: OrderBookMessage = BinanceOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp, metadata={"trading_pair": trading_pair}) order_book: OrderBook = self.order_book_create_function() order_book.apply_snapshot(snapshot_msg.bids, snapshot_msg.asks, snapshot_msg.update_id) retval[trading_pair] = OrderBookTrackerEntry( trading_pair, snapshot_timestamp, order_book) self.logger().info( f"Initialized order book for {trading_pair}. " f"{index+1}/{number_of_pairs} completed.") # Each 1000 limit snapshot costs 10 requests and Binance rate limit is 20 requests per second. await asyncio.sleep(1.0) except Exception: self.logger().error( f"Error getting snapshot for {trading_pair}. ", exc_info=True) await asyncio.sleep(5) return retval
async def listen_for_order_book_snapshots(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue): while True: try: async with aiohttp.ClientSession() as client: for trading_pair in self._trading_pairs: try: snapshot: Dict[str, Any] = await self.get_snapshot(client, trading_pair) snapshot_timestamp: float = time.time() snapshot_msg: OrderBookMessage = BinanceOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp, metadata={"trading_pair": trading_pair} ) output.put_nowait(snapshot_msg) self.logger().debug(f"Saved order book snapshot for {trading_pair}") # Be careful not to go above Binance's API rate limits. await asyncio.sleep(5.0) except asyncio.CancelledError: raise except Exception: self.logger().error("Unexpected error.", exc_info=True) 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().error("Unexpected error.", exc_info=True) await asyncio.sleep(5.0)
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, 1000) snapshot_timestamp: float = time.time() snapshot_msg: OrderBookMessage = BinanceOrderBook.snapshot_message_from_exchange( snapshot, snapshot_timestamp, metadata={"trading_pair": trading_pair} ) order_book = self.order_book_create_function() order_book.apply_snapshot(snapshot_msg.bids, snapshot_msg.asks, snapshot_msg.update_id) return order_book