🚀 AI One-Click Generation of quantconnect Strategy Code

How to Get Historical Bid/Ask Data Using slice.quote_bars in QuantConnect

quantconnect | Published on: 2025/12/3
The following content is generated by EasyQuant .

Problem Description

How can I get the latest bid and ask price for a cryptocurrency?

Solution

To access the latest bid and ask prices for a cryptocurrency in QuantConnect, you need to utilize the QuoteBar data. When you subscribe to a cryptocurrency using add_crypto, the LEAN engine provides both TradeBars (transaction prices) and QuoteBars (bid/ask prices) in the on_data event.

Here is the specific logic:

  1. Subscription: Use self.add_crypto to subscribe to the asset.
  2. Access: In on_data(self, slice), access the slice.quote_bars dictionary.
  3. Properties: Retrieve the bid and ask objects from the bar, which contain open, high, low, and close properties. Usually, close is used for the "latest" price.

Complete Algorithm Example

# region imports
from AlgorithmImports import *
# endregion

class CryptoBidAskAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2023, 1, 1)
        self.set_end_date(2023, 1, 2)
        self.set_cash(10000)

        # Subscribe to Bitcoin data
        # Note: Quote data is generally available for Minute, Second, and Tick resolutions
        self._crypto = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.COINBASE).symbol

    def on_data(self, slice: Slice):
        # Check if the QuoteBar exists for our symbol in the current time slice
        if self._crypto in slice.quote_bars:
            quote_bar = slice.quote_bars[self._crypto]
            
            # Access Bid and Ask objects
            # Each has .open, .high, .low, .close properties
            latest_bid = quote_bar.bid.close
            latest_ask = quote_bar.ask.close
            
            # Calculate spread
            spread = latest_ask - latest_bid
            
            self.log(f"Time: {self.time} | Bid: {latest_bid} | Ask: {latest_ask} | Spread: {spread}")
            
            # Example: Buy if spread is tight (arbitrary logic for demonstration)
            if spread < 10 and not self.portfolio.invested:
                self.set_holdings(self._crypto, 1)

        # Alternatively, you can access the data directly via the chain if needed, 
        # but slice.quote_bars is the standard way for the current moment.

Key Components

  • slice.quote_bars: This dictionary contains the QuoteBar objects for the current time step. It is distinct from slice.bars (which contains TradeBar data, i.e., actual executed trades).
  • quote_bar.bid / quote_bar.ask: These properties return a Bar object representing the OHLC of the bid or ask side for that period.
  • Resolution: Ensure you select a resolution that supports quotes (Tick, Second, or Minute). Daily resolution often defaults to TradeBars only depending on the data source.

Q&A

Q: What happens if I try to access slice.quote_bars but the data isn't there?
A: If you try to access a key that doesn't exist in the dictionary, Python will raise a KeyError. Always check if symbol in slice.quote_bars: before accessing the data, as some time slices might contain trade data but no new quote updates, or vice versa.

Q: Can I get the size (volume) of the bid and ask?
A: Yes. The QuoteBar object also contains last_bid_size and last_ask_size properties, representing the size of the last quote tick in that bar.

Q: Does this work for Equities as well?
A: Yes, but you must ensure you have subscribed to high-resolution data (Minute/Second/Tick) and that the specific data feed provides NBBO (National Best Bid and Offer) or exchange-specific quotes. For equities, add_equity is used, but the retrieval method via slice.quote_bars remains the same.