Problem Description
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:
- Subscription: Use
self.add_cryptoto subscribe to the asset. - Access: In
on_data(self, slice), access theslice.quote_barsdictionary. - Properties: Retrieve the
bidandaskobjects from the bar, which containopen,high,low, andcloseproperties. Usually,closeis 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 theQuoteBarobjects for the current time step. It is distinct fromslice.bars(which containsTradeBardata, i.e., actual executed trades).quote_bar.bid/quote_bar.ask: These properties return aBarobject 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.