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

Historical Data

Getting Started

Introduction

There are two ways to request historical data in your algorithms: direct historical data requests and indirect algorithm warm up.

History Requests

History requests return all of the data you request as a single object. Follow these steps to get some historical data:

  1. Create a new project.
  2. Projects contain files to run backtests, launch research notebooks, perform parameter optimizations, and deploy live trading strategies. You need to create projects in order to create strategies and share your work with other members.

    The process to create a new project depends on if you use the Cloud Platform, Local Platform, or CLI.

  3. In the initializeInitialize method, add an asset.
  4. The Initializeinitialize method is the entry point of your algorithm where you define a series of settings, including security subscriptions, starting cash balances, and warm-up periods. LEAN only calls the Initializeinitialize method one time, at the start of your algorithm.

    var spy = AddEquity("SPY");
    spy = self.add_equity('SPY')
  5. Call the historyHistory method with the asset's Symbol and a lookback period.
  6. Symbol objects are a way to identify or "finger-print" tradable assets so that no further database look-up is required. All QuantConnect and LEAN Algorithm API methods use Symbol objects to identify assets.

    var history = History(spy.Symbol, 5, Resolution.Daily);
    history = self.history(spy.symbol, 5, Resolution.DAILY)
    closehighlowopenvolume
    symboltime
    SPY2025-02-12 16:00:00603.36604.54598.520599.2638247065.0
    2025-02-13 16:00:00609.73609.94603.215604.4336445673.0
    2025-02-14 16:00:00609.70610.99609.080609.9823498431.0
    2025-02-18 16:00:00611.49611.49608.390610.8624030531.0
    2025-02-19 16:00:00612.93613.23609.560610.0426847903.0

Warm Up Periods

Warm-up simulates winding back the clock from the time you deploy the algorithm. In a backest, this is the start date of your algorithm. In live trading, it's the current date. Follow these steps to add a warm-up period to the start of your algorithm:

  1. Create a new project.
  2. The process to create a new project depends on if you use the Cloud Platform, Local Platform, or CLI.

  3. In the initializeInitialize method, set the backtest dates and add an asset.
  4. SetStartDate(2024, 12, 1);
    SetEndDate(2024, 12, 2);
    AddEquity("SPY", Resolution.Daily);
    self.set_start_date(2024, 12, 1)
    self.set_end_date(2024, 12, 2)
    self.add_equity("SPY", Resolution.DAILY)
  5. In the initializeInitialize method, call the set_warm_upSetWarmUp method with the warm-up duration.
  6. SetWarmUp(10, Resolution.Daily);
    self.set_warm_up(10, Resolution.DAILY)
  7. In the on_dataOnData method, log the time and warm-up state.
  8. Log($"IsWarmingUp at {Time}: {IsWarmingUp}");
    self.log(f"self.is_warming_up at {self.time}: {self.is_warming_up}")
    Algorithm starting warm up...
    IsWarmingUp at 11/22/2024 4:00:00 PM: True
    IsWarmingUp at 11/25/2024 4:00:00 PM: True
    IsWarmingUp at 11/26/2024 4:00:00 PM: True
    IsWarmingUp at 11/27/2024 4:00:00 PM: True
    IsWarmingUp at 11/29/2024 1:00:00 PM: True
    Algorithm finished warming up.
    IsWarmingUp at 12/2/2024 4:00:00 PM: False
    Algorithm starting warm up...
    self.is_warming_up at 2024-11-22 16:00:00: True
    self.is_warming_up at 2024-11-25 16:00:00: True
    self.is_warming_up at 2024-11-26 16:00:00: True
    self.is_warming_up at 2024-11-27 16:00:00: True
    self.is_warming_up at 2024-11-29 13:00:00: True
    Algorithm finished warming up.
    self.is_warming_up at 2024-12-02 16:00:00: False

For more information about warm-up, see Warm Up Periods.

Examples

The following examples demonstrate some common practices for historical data.

Example 1: Simple Moving Average

The following example demonstrates weekly-resampled historical data to calculate the 50-week Simple Moving Average to implement an SMA-cross strategy.

public class HistoricalDataAlgorithm : QCAlgorithm
{
    private Symbol _spy;
    private TradeBarConsolidator _consolidator;
    private RollingWindow<decimal> _window = new(50);

    public override void Initialize()
    {
        SetStartDate(2024, 1, 1);
        SetEndDate(2024, 12, 31);
        SetCash(100000);

        // Request SPY data for historical data call and trading.
        _spy = AddEquity("SPY", Resolution.Daily).Symbol;
        // Set up a consolidator to resample historical data to weekly.
        _consolidator = new TradeBarConsolidator(Calendar.Weekly);
        _consolidator.DataConsolidated += (_, updated) => _window.Add(updated.Close);

        // Set a scheduled event to trade SPY with a weekly SMA signal.
        Schedule.On(DateRules.WeekStart(_spy), TimeRules.AfterMarketOpen(_spy, 1), Trade);
    }

    private void Trade()
    {
        // Historical data call to calculate signal.
        var history = History<TradeBar>(_spy, 252, Resolution.Daily);
        // Obtain the weekly close price to calculate the weekly EMA.
        foreach (var bar in history)
        {
            _consolidator.Update(bar);
        }
        // Calculate the current 50-week SMA as a trading signal.
        var sma50 = _window.Average();

        // Trade the SMA cross strategy.
        var price = history.Last().Close;
        if (price > sma50 && !Portfolio[_spy].IsLong)
        {
            SetHoldings(_spy, 1m);
        }
        else if (price < sma50 && !Portfolio[_spy].IsShort)
        {
            SetHoldings(_spy, -1m);
        }
    }
}
class HistoricalDataAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 1, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)
    
        # Request SPY data for historical data call and trading.
        self.spy = self.add_equity("SPY", Resolution.DAILY).symbol
        # Set a scheduled event to trade SPY with a weekly SMA signal.
        self.schedule.on(self.date_rules.week_start(self.spy), self.time_rules.after_market_open(self.spy, 1), self.trade)

    def trade(self) -> None:
        # Historical data call to calculate signal.
        history = self.history(self.spy, 252, Resolution.DAILY)
        # Obtain the weekly close price to calculate the weekly SMA.
        weekly_close = history.unstack(0).close.resample("W").last()
        # Calculate the current 50-week SMA as a trading signal.
        sma50 = weekly_close.rolling(50).mean().iloc[-1, 0]

        # Trade the SMA cross strategy.
        price = self.securities[self.spy].price
        if price > sma50 and not self.portfolio[self.spy].is_long:
            self.set_holdings(self.spy, 1)
        elif price < sma50 and not self.portfolio[self.spy].is_short:
            self.set_holdings(self.spy, -1)

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: