book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

Asset Classes

US Equities

Introduction

This page explains how to get historical data for US Equities. Some of the data you can get include prices, fundamentals, corporate actions, and universe selection data.

Trades

To get historical trade data, call the history method with the TradeBar type and a security's Symbol. This method returns a DataFrame with columns for the open, high, low, close, and volume.

Select Language:
class USEquityTradeBarHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Get the Symbol of a security.
        symbol = self.add_equity('SPY').symbol
        # Get the 5 trailing daily TradeBar objects of the security in DataFrame format. 
        history = self.history(TradeBar, symbol, 5, Resolution.DAILY)
closehighlowopenvolume
symboltime
SPY2024-12-12 16:00:00604.33607.160604.33606.6424962360.0
2024-12-13 16:00:00604.21607.100602.82606.3829250856.0
2024-12-16 16:00:00606.79607.775605.22606.0033686372.0
2024-12-17 16:00:00604.29605.160602.89604.2238527534.0
2024-12-18 16:00:00586.28606.400585.89604.0080642184.0
# Calculate the daily returns.
daily_returns = history.close.pct_change().iloc[1:]
symbol  time               
SPY     2024-12-13 16:00:00   -0.000199
        2024-12-16 16:00:00    0.004270
        2024-12-17 16:00:00   -0.004120
        2024-12-18 16:00:00   -0.029804
Name: close, dtype: float64

If you intend to use the data in the DataFrame to create TradeBar objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of TradeBar objects instead of a DataFrame, call the history[TradeBar] method.

# Get the 5 trailing daily TradeBar objects of the security in TradeBar format. 
history = self.history[TradeBar](symbol, 5, Resolution.DAILY)
# Iterate through the TradeBar objects and access their volumes.
for trade_bar in history:
    t = trade_bar.end_time
    volume = trade_bar.volume

Quotes

To get historical quote data, call the history method with the QuoteBar type and a security's Symbol. This method returns a DataFrame with columns for the open, high, low, close, and size of the bid and ask quotes. The columns that don't start with "bid" or "ask" are the mean of the quote prices on both sides of the market.

Select Language:
class USEquityQuoteBarHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Get the Symbol of a security.
        symbol = self.add_equity('SPY').symbol
        # Get the 5 trailing minute QuoteBar objects of the security in DataFrame format. 
        history = self.history(QuoteBar, symbol, 5, Resolution.MINUTE)
askcloseaskhighasklowaskopenasksizebidclosebidhighbidlowbidopenbidsizeclosehighlowopen
symboltime
SPY2024-12-18 15:56:00588.65590.44588.60590.4210700.0588.61590.40588.56590.38700.0588.630590.420588.580590.400
2024-12-18 15:57:00588.37588.92588.25588.65100.0588.34588.89588.24588.61100.0588.355588.905588.245588.630
2024-12-18 15:58:00588.13588.50588.08588.37100.0588.11588.47588.06588.34500.0588.120588.485588.070588.355
2024-12-18 15:59:00587.93588.34587.70588.138000.0587.92588.31587.68588.11100.0587.925588.325587.690588.120
2024-12-18 16:00:00586.33587.95585.89587.93200.0586.30587.93585.88587.9274700.0586.315587.940585.885587.925
# Calculate the spread at each minute.
spread = history.askclose - history.bidclose
symbol  time               
SPY     2024-12-18 15:56:00    0.04
        2024-12-18 15:57:00    0.03
        2024-12-18 15:58:00    0.02
        2024-12-18 15:59:00    0.01
        2024-12-18 16:00:00    0.03
dtype: float64

If you intend to use the data in the DataFrame to create QuoteBar objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of QuoteBar objects instead of a DataFrame, call the history[QuoteBar] method.

# Get the 5 trailing minute QuoteBar objects of the security in QuoteBar format. 
history = self.history[QuoteBar](symbol, 5, Resolution.MINUTE)
# Iterate through each QuoteBar and calculate the dollar volume on the bid.
for quote_bar in history:
    t = quote_bar.end_time
    bid_dollar_volume = quote_bar.last_bid_size * quote_bar.bid.close

Request second or minute resolution data. Otherwise, the history request won't return any data.

Ticks

To get historical tick data, call the history method with a security's Symbol and Resolution.TICK. This method returns a DataFrame that contains data on bids, asks, and last trade prices.

Select Language:
class USEquityTickHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Get the Symbol of a security.
        symbol = self.add_equity('SPY').symbol
        # Get the trailing 2 days of ticks for the security in DataFrame format.
        history = self.history(symbol, timedelta(2), Resolution.TICK)
askpriceasksizebidpricebidsizeexchangelastpricequantity
symboltime
SPY2024-12-17 09:30:00.0002140.000.0604.171000.0NASDAQ604.170.0
2024-12-17 09:30:00.000214604.191900.00.000.0ARCA604.190.0
2024-12-17 09:30:00.001110NaNNaNNaNNaNNYSE604.19100.0
2024-12-17 09:30:00.001480NaNNaNNaNNaNARCA604.1969.0
2024-12-17 09:30:00.0014820.000.0604.171000.0NASDAQ604.170.0
# Select the rows in the DataFrame that represent trades. Drop the bid/ask columns since they are NaN.
trade_ticks = history[history.quantity > 0].dropna(axis=1)
exchangelastpricequantity
symboltime
SPY2024-12-17 09:30:00.001110NYSE604.19100.0
2024-12-17 09:30:00.001480ARCA604.1969.0
2024-12-17 09:30:00.001483ARCA604.19100.0
2024-12-17 09:30:00.001483ARCA604.19231.0
2024-12-17 09:30:00.001564NASDAQ604.19100.0

If you intend to use the data in the DataFrame to create Tick objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of Tick objects instead of a DataFrame, call the history[Tick] method.

# Get the trailing 2 days of ticks for the security in Tick format. 
history = self.history[Tick](symbol, timedelta(2), Resolution.TICK)
# Iterate through each quote tick and calculate the quote size.
for tick in history:
    if tick.tick_type == TickType.Quote:
        t = tick.end_time
        size = max(tick.bid_size, tick.ask_size)

Ticks are a sparse dataset, so request ticks over a trailing period of time or between start and end times.

Slices

To get historical Slice data, call the history method without passing any Symbol objects. This method returns Slice objects, which contain data points from all the datasets in your algorithm. If you omit the resolution argument, it uses the resolution that you set for each security and dataset when you created the subscriptions.

Select Language:
class SliceHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 1)
        # Add some securities and datasets.
        self.add_equity('SPY')
        # Get the historical Slice objects over the last 5 days for all the subcriptions in your algorithm.
        history = self.history(5, Resolution.DAILY)
        # Iterate through each historical Slice.
        for slice_ in history:
            # Iterate through each TradeBar in this Slice.
            for symbol, trade_bar in slice_.bars.items():
                close = trade_bar.close

Fundamentals

To get historical fundamental data, call the history method with the Fundamental type and an asset's Symbol. This method returns a DataFrame with columns for the data point attributes.

Select Language:
class USEquityFundamentalHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 27)
        # Get the Symbol of an asset.
        symbol = self.add_equity('AAPL').symbol
        # Get the 3 trailing daily Fundamental objects of the asset in DataFrame format. 
        history = self.history(Fundamental, symbol, 3, Resolution.DAILY)
adjustedpriceassetclassificationcompanyprofilecompanyreferencedollarvolumeearningratiosearningreportsfinancialstatementshasfundamentaldatamarketmarketcapoperationratiospricefactorpricescalefactorsecurityreferencesplitfactorvaluationratiosvaluevolume
symboltime
AAPL2024-12-17250.764283QuantConnect.Data.Fundamental.AssetClassificationQuantConnect.Data.Fundamental.CompanyProfileQuantConnect.Data.Fundamental.CompanyReference1.140352e+10QuantConnect.Data.Fundamental.EarningRatiosQuantConnect.Data.Fundamental.EarningReportsQuantConnect.Data.Fundamental.FinancialStatementsTrueusa3587438272590QuantConnect.Data.Fundamental.OperationRatios0.9989020.998902QuantConnect.Data.Fundamental.SecurityReference1.0QuantConnect.Data.Fundamental.ValuationRatios251.0445425121
2024-12-18253.201603QuantConnect.Data.Fundamental.AssetClassificationQuantConnect.Data.Fundamental.CompanyProfileQuantConnect.Data.Fundamental.CompanyReference1.196673e+10QuantConnect.Data.Fundamental.EarningRatiosQuantConnect.Data.Fundamental.EarningReportsQuantConnect.Data.Fundamental.FinancialStatementsTrueusa3587438272590QuantConnect.Data.Fundamental.OperationRatios0.9989020.998902QuantConnect.Data.Fundamental.SecurityReference1.0QuantConnect.Data.Fundamental.ValuationRatios253.4847209742
2024-12-19247.777567QuantConnect.Data.Fundamental.AssetClassificationQuantConnect.Data.Fundamental.CompanyProfileQuantConnect.Data.Fundamental.CompanyReference1.284373e+10QuantConnect.Data.Fundamental.EarningRatiosQuantConnect.Data.Fundamental.EarningReportsQuantConnect.Data.Fundamental.FinancialStatementsTrueusa3587438272590QuantConnect.Data.Fundamental.OperationRatios0.9989020.998902QuantConnect.Data.Fundamental.SecurityReference1.0QuantConnect.Data.Fundamental.ValuationRatios248.0551778802
# Get the Current Ratio of each row.
current_ratios = history.apply(lambda row: row.operationratios.current_ratio.value, axis=1)
symbol  time      
AAPL    2024-12-24    0.867313
        2024-12-25    0.867313
        2024-12-27    0.867313
dtype: float64

To avoid consuming unnecessary computational resources populating the DataFrame, you can instead request Fundamental objects. To get a list of Fundamental objects, call the history[Fundamental] method.

# Get the 3 trailing daily Fundamental objects of an asset in Fundamental format. 
history = self.history[Fundamental](symbol, 3, Resolution.DAILY)
# Iterate through each Fundamental object and access its properites.
for fundamental in history:
    symbol = fundamental.symbol
    pe_ratio = fundamental.valuation_ratios.pe_ratio

Splits

To get historical split data, call the history method with the Split type and an asset's Symbol. This method returns a DataFrame with columns for the reference price, split factor, and split type. Splits are a sparse dataset, so use a time period history request since most days have no data.

Select Language:
class USEquitySplitHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 1)
        # Get the Symbol of an asset.
        symbol = self.add_equity('AAPL').symbol
        # Get the splits that occured for the stock over the last 5 years in DataFrame format. 
        history = self.history(Split, symbol, timedelta(5*365))
referencepricesplitfactortypevalue
symboltime
AAPL2020-08-280.000.2500.00
2020-08-31499.230.251499.23

In the preceding DataFrame, the type column represents the SplitType enumeration, where 0=SplitType.WARNING and 1=SplitType.SPLIT_OCCURRED.

# Select the prices where splits occurred.
split_prices = history[history.type == SplitType.SPLIT_OCCURRED].value
symbol  time      
AAPL    2020-08-31    499.23
Name: value, dtype: float64

If you intend to use the data in the DataFrame to create Split objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of Split objects instead of a DataFrame, call the history[Split] method.

# Get the splits that occured for a stock over the last 5 years in Split format. 
history = self.history[Split](symbol, timedelta(5*365))
# Iterate through each Split object.
for split in history:
    # Select the time when each split occurred.
    if split.type == SplitType.SPLIT_OCCURRED:
        t = split.end_time

Dividends

To get historical dividend data, call the history method with the Dividend type and an asset's Symbol. This method returns a DataFrame with columns for the dividend payment and reference price. Dividends are a sparse dataset, so use a time period history request since most days have no data.

Select Language:
class USEquityDividendHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 1)
        # Get the Symbol of an asset.
        symbol = self.add_equity('AAPL').symbol
        # Get the dividends that the stock paid over the last 2 years in DataFrame format. 
        history = self.history(Dividend, symbol, timedelta(2*365))
distributionreferencepricevalue
symboltime
AAPL2022-12-230.17132.230.17
2023-02-100.23150.870.23
2023-05-120.24173.750.24
2023-08-110.24177.970.24
2023-11-100.24182.410.24
# Calculate the mean dividend payment.
mean_dividend = history.distribution.mean()

If you intend to use the data in the DataFrame to create Dividend objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of Dividend objects instead of a DataFrame, call the history[Dividend] method.

# Get the dividends that a stock paid over the last 2 years in Dividend format. 
history = self.history[Dividend](symbol, timedelta(2*365))
# Iterate through each Dividend object.
for dividend in history:
    distribution = dividend.distribution

Symbol Changes

To get historical symbol change data, call the history method with the SymbolChangedEvent type and an asset's Symbol. This method returns a DataFrame with columns for the old symbol and new symbol during each change.

Select Language:
class USEquitySymbolChangedEventHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 1)
        # Get the Symbol of an asset.
        symbol = self.add_equity('META').symbol
        # Get the symbol changes of the stock over the last 10 years in DataFrame format. 
        history = self.history(SymbolChangedEvent, symbol, timedelta(10*365))
newsymbololdsymbol
symboltime
META2022-06-09METAFB
# Select the dates of each ticker change.
dates = list(history.index.levels[1])

If you intend to use the data in the DataFrame to create SymbolChangedEvent objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of SymbolChangedEvent objects instead of a DataFrame, call the history[SymbolChangedEvent] method.

# Get the symbol changes of a stock over the last 10 years in SymbolChangedEvent format. 
history = self.history[SymbolChangedEvent](symbol, timedelta(10*365))
# Iterate through each SymbolChangedEvent object.
for symbol_changed_event in history:
    t = symbol_changed_event.end_time
    old_symbol = symbol_changed_event.old_symbol
    new_symbol = symbol_changed_event.new_symbol

Delistings

To get historical delisting data, call the history method with the Delisting type and an asset's Symbol. This method returns a DataFrame with columns for the old symbol and new symbol during each change. Delistings are a sparse dataset, so use a time period history request since most days have no data.

Select Language:
class USEquityDelistingHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 1)
        # Get the Symbol of an asset.
        symbol = self.add_equity('BBBY').symbol
        # Get the deslistings of the asset over the last 10 years in DataFrame format.
        history = self.history(Delisting, symbol, timedelta(10*365))
type
symboltime
BBBY2023-05-020
2023-05-031

In the preceding DataFrame, the type column represents the DelistingType enumeration, where 0=DelistingType.WARNING and 1=DelistingType.DELISTED.

# Select the rows in the DataFrame that represent deslist warnings.
warnings = history[history.type == DelistingType.WARNING].type
symbol  time      
BBBY    2023-05-02    0
Name: type, dtype: int64

If you intend to use the data in the DataFrame to create Delisting objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of Delisting objects instead of a DataFrame, call the history[Delisting] method.

# Get the deslistings of an asset over the last 10 years in Delisting format. 
history = self.history[Delisting](symbol, timedelta(10*365))
# Iterate through each Deslisting object and access the warning dates.
for deslisting in history:
    if deslisting.type == DelistingType.WARNING:
        warning_date = deslisting.end_time

Universes

To get historical universe data, call the history method with the Universe object. This method returns a DataFrame with columns for the data point attributes.

Select Language:
class USEquityUniverseHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 23)
        # Add a universe of US Equities based on the constituents of an ETF.
        universe = self.add_universe(self.universe.etf('SPY'))
        # Get 5 days of history for the universe.
        history = self.history(universe, timedelta(5), flatten=True)
lastupdateperiodsharesheldweight
timesymbol
2024-12-19A RPTMYV3VC57P2024-12-171 days3682327.00.000777
AAPL R735QTJ8XC9X2024-12-171 days191633535.00.075065
ABBV VCY032R250MD2024-12-171 days22256743.00.006032
ABNB XK8H247DY6W52024-12-171 days5536841.00.001131
ABT R735QTJ8XC9X2024-12-171 days21919703.00.003837
..................
2024-12-21XYL V18KR26TE3XH2024-12-191 days2947931.00.000569
YUM R735QTJ8XC9X2024-12-191 days3412693.00.000737
ZMH S6ZZPKTVDY052024-12-191 days2471688.00.000433
ZBRA R735QTJ8XC9X2024-12-191 days625772.00.000400
ZTS VDRJHVQ4FNFP2024-12-191 days5484351.00.001486
# Select the 2 assets with the smallest weights in the ETF each day.
daily_smallest = history.groupby('time').apply(lambda x: x.nsmallest(2, 'weight')).reset_index(level=1, drop=True).weight
time        symbol            
2024-12-19  AMTMW YM37RIGZUD0L    0.000053
            NWSVV VHJF6S7EZRL1    0.000068
2024-12-20  AMTMW YM37RIGZUD0L    0.000051
            NWSVV VHJF6S7EZRL1    0.000069
2024-12-21  AMTMW YM37RIGZUD0L    0.000048
            NWSVV VHJF6S7EZRL1    0.000069
Name: weight, dtype: float64

To get the data in the format of the objects that you receive in your universe filter function instead of a DataFrame, use flatten=False. This call returns a Series where the values are lists of the universe data objects.

# Get the historical universe data over the last 30 days in a Series where
# the values in the series are lists of the universe selection objects.
history = self.history(universe, timedelta(30), flatten=False)
# Iterate through each day of universe selection.
for (universe_symbol, end_time), constituents in history.items():
    # Select the 10 largest assets in the ETF on this day.
    largest = sorted(constituents, key=lambda c: c.weight)[-10:]

Alternative Data

To get historical alternative data, call the history method with the dataset Symbol. This method returns a DataFrame that contains the data point attributes.

Select Language:
class USEquityAlternativeDataHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Get the Symbol of an asset.
        symbol = self.add_equity('GME').symbol
        # Add the alternative dataset and save a reference to its Symbol.
        dataset_symbol = self.add_data(QuiverWallStreetBets, symbol).symbol
        # Get the trailing 5 days of QuiverWallStreetBets data for the asset in DataFrame format.
        history = self.history(dataset_symbol, 5, Resolution.DAILY)
datementionsranksentiment
symboltime
GME.QuiverWallStreetBets2024-12-152024-12-142480.74245
2024-12-162024-12-151136-0.51600
2024-12-172024-12-168530.13987
2024-12-182024-12-1717320.08564
2024-12-192024-12-1841170.61682
# Calculate the changes in sentiment.
sentiment_diff = history.sentiment.diff().iloc[1:]
symbol                    time      
GME.QuiverWallStreetBets  2024-12-16   -1.25845
                          2024-12-17    0.65587
                          2024-12-18   -0.05423
                          2024-12-19    0.53118
Name: sentiment, dtype: float64

If you intend to use the data in the DataFrame to create alternativeDataClass objects, request that the history request returns the data type you need. Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame. To get a list of dataset objects instead of a DataFrame, call the history[alternativeDataClass] method.

# Get the trailing 5 days of QuiverWallStreetBets data for an asset in QuiverWallStreetBets format. 
history = self.history[QuiverWallStreetBets](dataset_symbol, 5, Resolution.DAILY)
# Iterate through each QuiverWallStreetBets object.
for data_point in history:
    t = data_point.end_time
    sentiment = data_point.sentiment

Some alternative datasets provide multiple entries per asset per time step. For example, the True Beats dataset provides EPS and revenue predictions for several upcoming quarters per asset per day. In this case, to organize the data into a DataFrame, set the flatten argument to True.

Select Language:
class USEquityTrueBeatsHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 1, 3)
        # Get the ExtractAlphaTrueBeats data for AAPL on 01/02/2024 organized in a flat DataFrame.
        aapl = self.add_equity("AAPL", Resolution.DAILY)
        aapl.true_beats = self.add_data(ExtractAlphaTrueBeats, aapl.symbol).symbol
        history = self.history(
            aapl.true_beats, datetime(2024, 1, 2), datetime(2024, 1, 3), Resolution.DAILY, flatten=True
        )
analystestimatescountannualearningsmetricendexpectedreportdateexpertbeatfiscalquarterfiscalyearmanagementbeatquarterlytimetrendbeattruebeat
timesymbol
2024-01-02 12:30:00AAPL.ExtractAlphaTrueBeats28False02023-12-312024-01-25-0.0012414.020230.013694True2024-01-02 12:30:000.0168990.029352
AAPL.ExtractAlphaTrueBeats29True02024-09-302024-10-24NaNNaN2024NaNFalse2024-01-02 12:30:00NaN-0.020608
AAPL.ExtractAlphaTrueBeats24False02024-03-312024-04-25NaN1.02024NaNTrue2024-01-02 12:30:00NaN-0.016578
AAPL.ExtractAlphaTrueBeats24False0NaTNaTNaN2.02024NaNTrue2024-01-02 12:30:00NaN0.011859
AAPL.ExtractAlphaTrueBeats26False0NaTNaTNaN3.02024NaNTrue2024-01-02 12:30:00NaN0.017517
..........................................
AAPL.ExtractAlphaTrueBeats11False0NaTNaTNaN1.02025NaNTrue2024-01-02 12:30:00NaN-0.009165
AAPL.ExtractAlphaTrueBeats11False0NaTNaTNaN2.02025NaNTrue2024-01-02 12:30:00NaN-0.020219
AAPL.ExtractAlphaTrueBeats11False0NaTNaTNaN3.02025NaNTrue2024-01-02 12:30:00NaN-0.042210
AAPL.ExtractAlphaTrueBeats1False0NaTNaTNaN4.02025NaNTrue2024-01-02 12:30:00NaN0.000000
AAPL.ExtractAlphaTrueBeats10True0NaTNaTNaNNaN2026NaNFalse2024-01-02 12:30:00NaN-0.001965
# Calculate the mean TrueBeat estimate for each day.
mean_true_beats_by_day = history.drop('time', axis=1).groupby('time').apply(lambda g: g.truebeat.mean())
time
2024-01-02 12:30:00   -0.007034
dtype: float64

For information on historical data for other alternative datasets, see the documentation in the Dataset Market.

Indicators

To get historical indicator values, call the indicator_history method with an indicator and the security's Symbol.

Select Language:
class USEquityIndicatorHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Get the Symbol of a security.
        symbol = self.add_equity('SPY').symbol
        # Get the 21-day SMA values of the security for the last 5 trading days. 
        history = self.indicator_history(SimpleMovingAverage(21), symbol, 5, Resolution.DAILY)

To organize the data into a DataFrame, use the data_frame property of the result.

# Organize the historical indicator data into a DataFrame to enable pandas wrangling.
history_df = history.data_frame
currentrollingsum
2024-12-12 16:00:00599.18666712582.92
2024-12-13 16:00:00599.52095212589.94
2024-12-16 16:00:00600.16095212603.38
2024-12-17 16:00:00601.04381012621.92
2024-12-18 16:00:00600.95476212620.05
# Get the maximum of the SMA values.
sma_max = history_df.current.max()

The indicator_history method resets your indicator, makes a history request, and updates the indicator with the historical data. Just like with regular history requests, the indicator_history method supports time periods based on a trailing number of bars, a trailing period of time, or a defined period of time. If you don't provide a resolution argument, it defaults to match the resolution of the security subscription.

To make the indicator_history method update the indicator with an alternative price field instead of the close (or mid-price) of each bar, pass a selector argument.

Select Language:
# Get the historical values of an indicator over the last 30 days, applying the indicator to the security's volume.
history = self.indicator_history(indicator, symbol, timedelta(30), selector=Field.VOLUME)

Some indicators require the prices of two securities to compute their value (for example, Beta). In this case, pass a list of the Symbol objects to the method.

Select Language:
class USEquityMultiAssetIndicatorHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Add the target and reference securities.
        target_symbol = self.add_equity('AAPL').symbol
        reference_symbol = self.add_equity('SPY').symbol
        # Create a 21-period Beta indicator.
        beta = Beta("", target_symbol, reference_symbol, 21)
        # Get the historical values of the indicator over the last 10 trading days.
        history = self.indicator_history(beta, [target_symbol, reference_symbol], 10, Resolution.DAILY)
        # Get the average Beta value.
        beta_avg = history.data_frame.mean()

Short Availability

To get historical values for the borrow fee rate, borrow rebate rate, or shortable quantity of a US Equity, call the fee_rate, rebate_rate, or shortable_quantity methods of its shortable provider.

Select Language:
class USEquityShortAvailabilityHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        # Add an asset and save a reference to its Equity object.
        security = self.add_equity('SPY')
        # Overwrite the default shortable provider to one that provides data.
        security.set_shortable_provider(InteractiveBrokersShortableProvider())
        # Select a time in the past.
        t = self.time - timedelta(30)
        # Pass the time argument to shortable provider to get historical values.
        fee_rate = security.shortable_provider.fee_rate(security.symbol, t)
        rebate_rate = security.shortable_provider.rebate_rate(security.symbol, t)
        shortable_quantity = security.shortable_provider.shortable_quantity(security.symbol, t)

For more information about security initializers, see Set Security Initializer.

Examples

The following examples demonstrate some common practices for trading using historical requests.

Example 1: Mean-Variance Portfolio

The following algorithm constructs a monthly rebalance mean-variance portfolio using the top 20 liquid equities. The position sizing can be optimized by 1-year historical daily return of the universe members.

Select Language:
from Portfolio.MaximumSharpeRatioPortfolioOptimizer import MaximumSharpeRatioPortfolioOptimizer

class HistoricalRequestAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2020, 4, 1)
        self.set_end_date(2020, 9, 30)
        
        # Monthly renewal of the top 20 liquid universe to trade popular stocks.
        self.universe_settings.schedule.on(self.date_rules.month_start())
        self._universe = self.add_universe(self.universe.dollar_volume.top(20))

        # Instantiate the optimizer to perform mean-variance optimization.
        # Mean-variance optimization will not consider a risk-free rate, so we use 0.
        self._optimizer = MaximumSharpeRatioPortfolioOptimizer(0.0, 1.0, 0.0)

        # Set a scheduled event to rebalance the portfolio at the start of every month.
        self.schedule.on(
            self.date_rules.month_start(), 
            self.time_rules.at(9, 31),
            self.rebalance
        )

    def rebalance(self) -> None:
        # Historical data request to get 1-year data for optimization.
        symbols = self._universe.selected
        history = self.history(symbols, 253, Resolution.DAILY).close.unstack(0).dropna()
        # Daily return on the universe members to calculate the optimized weights.
        returns = history.pct_change().dropna()

        # Calculate the optimized weights.
        weights = self._optimizer.optimize(returns)

        # Rebalance the portfolio according to the optimized weights.
        targets = [PortfolioTarget(symbol, size) for symbol, size in zip(symbols, weights)]
        self.set_holdings(targets, liquidate_existing_holdings=True)

Other Examples

For more examples, see the following algorithms:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: