🚀 AI One-Click Generation of quantconnect Strategy Code

How to Access and Use the Security Object in QuantConnect via self.securities

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

Problem Description

How do I get the current price and other data for a specific stock in my universe?

Solution

To access current price and asset data in QuantConnect, you primarily use the on_data(self, slice) event handler. There are two distinct ways to access this data depending on your needs:

  1. Using the slice object: Best for reacting to new data arriving at that specific moment (e.g., the close of a minute bar).
  2. Using self.securities: Best for accessing the last known state of an asset (price, holdings, margin) anywhere in your algorithm, even if no new data arrived in the current time step.

Complete Strategy Example

The following code demonstrates how to access Price (Close), Open, High, Low, Volume, and Bid/Ask data using both methods.

# region imports
from AlgorithmImports import *
# endregion

class DataAccessAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2023, 1, 1)
        self.set_end_date(2023, 1, 5)
        self.set_cash(100000)

        # Add an equity and keep a reference to the Symbol
        # Extended Market Hours is set to True to potentially see pre/post market data
        equity = self.add_equity("SPY", Resolution.MINUTE, extended_market_hours=True)
        self.spy_symbol = equity.symbol

    def on_data(self, slice: Slice):
        """
        OnData is the primary event handler for financial data.
        The 'slice' object contains all data for the current moment in time.
        """

        # ---------------------------------------------------------
        # METHOD 1: Accessing data via the 'slice' object
        # ---------------------------------------------------------
        # This is the preferred method to ensure you are acting on NEW data.
        
        # Check if TradeBar data (OHLCV) exists for this symbol in this slice
        if self.spy_symbol in slice.bars:
            trade_bar = slice.bars[self.spy_symbol]
            
            current_close = trade_bar.close
            current_open = trade_bar.open
            current_high = trade_bar.high
            current_low = trade_bar.low
            current_volume = trade_bar.volume
            
            self.log(f"Slice - Close: {current_close}, Vol: {current_volume}")

        # Check if QuoteBar data (Bid/Ask) exists (requires high resolution or tick data)
        if self.spy_symbol in slice.quote_bars:
            quote_bar = slice.quote_bars[self.spy_symbol]
            
            ask_price = quote_bar.ask.close
            bid_price = quote_bar.bid.close
            
            self.log(f"Slice - Bid: {bid_price}, Ask: {ask_price}")

        # ---------------------------------------------------------
        # METHOD 2: Accessing data via 'self.securities'
        # ---------------------------------------------------------
        # This accesses the global state of the security. 
        # It returns the last known value, even if the asset didn't trade in this specific slice.
        
        security = self.securities[self.spy_symbol]
        
        # Get the current price (usually the last trade or last quote depending on asset type)
        last_known_price = security.price
        
        # Access holdings information
        is_invested = security.invested
        quantity_held = security.holdings.quantity
        unrealized_profit = security.holdings.unrealized_profit
        
        # Example logic: Buy if price is below specific value and not invested
        if last_known_price > 0 and not is_invested:
            self.log(f"Securities State - Price: {last_known_price}")
            self.set_holdings(self.spy_symbol, 1.0)

    def on_end_of_day(self, symbol):
        # You can also access self.securities here, outside of OnData
        price = self.securities[symbol].price
        self.log(f"End of Day Price for {symbol}: {price}")

Key Data Access Methods

1. The slice Object (Event-Driven)

The slice object represents a "slice" of time. It contains dictionaries for different data types.

  • slice.bars[symbol]: Returns a TradeBar object (Open, High, Low, Close, Volume). Used for Equities, Futures, Crypto.
  • slice.quote_bars[symbol]: Returns a QuoteBar object (Bid, Ask, BidSize, AskSize). Used for Forex, Options, and Crypto.
  • slice[symbol]: A dynamic helper that returns the default data type for that asset.

Note: Always check if symbol in slice.bars: before accessing to avoid "KeyError" exceptions, as data might not exist for every single minute (e.g., if there were no trades).

2. The self.securities Object (State-Based)

The self.securities dictionary holds the entire state of your universe.

  • self.securities[symbol].price: The most recent price. If no trade occurred in the current minute, it holds the price from the previous minute.
  • self.securities[symbol].close: Same as price.
  • self.securities[symbol].holdings: Access portfolio data like quantity, average_price, and total_sale_volume.

Q&A

Q: What is the difference between slice[symbol].Close and self.securities[symbol].Close?
A: slice[symbol] contains data only if a trade occurred during that specific time interval. If the stock was illiquid and didn't trade for a minute, slice will not contain that symbol. self.securities[symbol].Close always returns the most recent known closing price, carrying forward the previous value if necessary.

Q: How do I get the Bid and Ask prices?
A: You must ensure you are subscribed to a resolution that provides quotes (Tick, Second, or Minute). In on_data, access slice.quote_bars[symbol].bid.close and slice.quote_bars[symbol].ask.close.

Q: Why do I get a KeyError when doing slice[symbol]?
A: This happens when there is no data for that symbol in the current time step. Always wrap your data access in a check: if slice.contains_key(symbol): or if symbol in slice.bars:.

Q: How do I get historical data (e.g., yesterday's close)?
A: on_data only provides the current moment. To get past data, use the History request in initialize or inside on_data:

# Get last 10 days of daily data
history = self.history(self.spy_symbol, 10, Resolution.DAILY)
yesterday_close = history['close'].iloc[-1]