async def listen_for_order_book_snapshots(self,
                                              ev_loop: asyncio.BaseEventLoop,
                                              output: asyncio.Queue):
        """
        Listen for orderbook snapshots by fetching orderbook
        """
        while True:
            try:
                trading_pairs: List[str] = await self.get_trading_pairs()

                for trading_pair in trading_pairs:
                    try:
                        snapshot: Dict[str, any] = await self.get_orderbook(
                            trading_pair)
                        snapshot_timestamp: float = pd.Timestamp(
                            snapshot["timestamp"]).timestamp()
                        snapshot_msg: OrderBookMessage = BitcoinComOrderBook.snapshot_message_from_exchange(
                            add_event_type(EventTypes.OrderbookSnapshot,
                                           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 API rate limits.
                        await asyncio.sleep(5.0)
                    except asyncio.CancelledError:
                        raise
                    except Exception:
                        self.logger().network(
                            f"Unexpected error with WebSocket connection.",
                            exc_info=True,
                            app_warning_msg=
                            f"Unexpected error with WebSocket connection. Retrying in 5 seconds. "
                            f"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().error("Unexpected error.", exc_info=True)
                await asyncio.sleep(5.0)
    async def listen_for_trades(self, ev_loop: asyncio.BaseEventLoop,
                                output: asyncio.Queue):
        """
        Listen for trades using websocket "updateTrades" method
        """
        while True:
            try:
                ws = BitcoinComWebsocket()
                await ws.connect()

                trading_pairs: List[str] = await self.get_trading_pairs()

                for trading_pair in trading_pairs:
                    await ws.subscribe(
                        "subscribeTrades",
                        {
                            "symbol": trading_pair,
                            "limit":
                            1  # we only care about updates, this sets the initial snapshot limit
                        })

                    async for response in ws.on("updateTrades"):
                        if (response["error"] is not None):
                            self.logger().error(response["error"])
                            continue

                        trades = response["data"]["data"]

                        for trade in trades:
                            trade_timestamp: float = pd.Timestamp(
                                trade["timestamp"]).timestamp()
                            trade_msg: OrderBookMessage = BitcoinComOrderBook.trade_message_from_exchange(
                                add_event_type(EventTypes.TradesUpdate, trade),
                                trade_timestamp,
                                metadata={"trading_pair": trading_pair})
                            output.put_nowait(trade_msg)
            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().error("Unexpected error.", exc_info=True)
                await asyncio.sleep(5.0)
            finally:
                await ws.disconnect()
    async def get_tracking_pairs(
            self) -> Dict[str, BitcoinComOrderBookTrackerEntry]:
        trading_pairs: List[str] = await self.get_trading_pairs()
        tracking_pairs: Dict[str, BitcoinComOrderBookTrackerEntry] = {}

        number_of_pairs: int = len(trading_pairs)
        for index, trading_pair in enumerate(trading_pairs):
            try:
                snapshot: Dict[str,
                               any] = await self.get_orderbook(trading_pair)
                snapshot_timestamp: float = pd.Timestamp(
                    snapshot["timestamp"]).timestamp()
                snapshot_msg: OrderBookMessage = BitcoinComOrderBook.snapshot_message_from_exchange(
                    add_event_type(EventTypes.OrderbookSnapshot, snapshot),
                    snapshot_timestamp,
                    metadata={"trading_pair": trading_pair})
                order_book: OrderBook = self.order_book_create_function()
                active_order_tracker: BitcoinComActiveOrderTracker = BitcoinComActiveOrderTracker(
                )
                bids, asks = active_order_tracker.convert_snapshot_message_to_order_book_row(
                    snapshot_msg)
                order_book.apply_snapshot(bids, asks, snapshot_msg.update_id)

                tracking_pairs[trading_pair] = BitcoinComOrderBookTrackerEntry(
                    trading_pair, snapshot_timestamp, order_book,
                    active_order_tracker)
                self.logger().info(
                    f"Initialized order book for {trading_pair}. "
                    f"{index+1}/{number_of_pairs} completed.")
                await asyncio.sleep(0.6)
            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 tracking_pairs
    async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop,
                                          output: asyncio.Queue):
        """
        Listen for orderbook diffs using websocket "updateOrderbook" method
        """
        while True:
            try:
                ws = BitcoinComWebsocket()
                await ws.connect()

                trading_pairs: List[str] = await self.get_trading_pairs()

                for trading_pair in trading_pairs:
                    await ws.subscribe("subscribeOrderbook",
                                       {"symbol": trading_pair})

                    async for response in ws.on("updateOrderbook"):
                        if (response["error"] is not None):
                            self.logger().error(response["error"])
                            continue

                        diff = response["data"]
                        diff_timestamp: float = pd.Timestamp(
                            diff["timestamp"]).timestamp()
                        orderbook_msg: OrderBookMessage = BitcoinComOrderBook.diff_message_from_exchange(
                            add_event_type(EventTypes.OrderbookUpdate, diff),
                            diff_timestamp,
                            metadata={"trading_pair": trading_pair})
                        output.put_nowait(orderbook_msg)

            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().network(
                    f"Unexpected error with WebSocket connection.",
                    exc_info=True,
                    app_warning_msg=
                    f"Unexpected error with WebSocket connection. Retrying in 30 seconds. "
                    f"Check network connection.")
                await asyncio.sleep(30.0)
            finally:
                await ws.disconnect()