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

Futures

Universes

Introduction

This page explains how to request historical data for a universe of Futures contracts.

Create Subscriptions

Follow these steps to subscribe to a Futures universe:

  1. Create a QuantBook.
  2. Select Language:
    qb = QuantBook()
  3. Call the add_future method with a ticker, resolution, and contract rollover settings.
  4. Select Language:
    future = qb.add_future(
        Futures.Indices.SP_500_E_MINI, 
        Resolution.MINUTE,
        data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
        data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
        contract_depth_offset=0
    )

    To view the available tickers in the US Futures dataset, see Supported Assets.

    If you omit any of the arguments after the ticker, see the following table for their default values:

    ArgumentDefault Value
    resolutionResolution.MINUTE
    data_normalization_modeDataNormalizationMode.ADJUSTED
    data_mapping_modeDataMappingMode.OpenInterest
    contract_depth_offset0

Contract Price History

The contract filter determines which Futures contracts are in your universe each trading day. The default filter doesn't select any contracts. To change the filter, call the set_filter method.

Select Language:
# Set the contract filter to select contracts that expire within 180 days.
future.set_filter(0, 180)

To get the prices and volumes for all of the Futures contracts that pass your filter during a specific period of time, call the future_history method with the Symbol of the continuous Futures contract, a start datetime, and an end datetime.

Select Language:
# Set the contract filter to select contracts that expire within 180 days.
history = qb.future_history(
    future.Symbol, datetime(2025, 4, 1), datetime(2025, 4, 3), Resolution.MINUTE, 
    fill_forward=False, extended_market_hours=False
)

The future_history method returns a FutureHistory object. To get each Slice in the FutureHistory object, iterate through it.

Select Language:
for slice_ in history:
    for continuous_contract_symbol, chain in slice_.futures_chains.items(): 
        for contract in chain:
            pass

To convert the FutureHistory object to a DataFrame that contains the trade and quote information of each contract, use the data_frame property.

history.data_frame
askcloseaskhighasklowaskopenasksizebidclosebidhighbidlowbidopenbidsizeclosehighlowopenvolume
expirysymboltime
2025-06-20ES YTG30NVEFCW12025-04-01 09:31:005631.505639.755631.505639.0019.05631.255639.505631.255638.7524.05631.255639.755631.255638.7511661.0
2025-04-01 09:32:005629.005634.005628.005631.5023.05628.755633.755627.755631.251.05629.005633.755627.755631.257613.0
2025-04-01 09:33:005636.255638.255628.255629.0041.05636.005638.005628.005628.7510.05636.005638.005628.255629.006543.0
......................................................
2025-09-19ES YVXOP65RE0HT2025-04-02 16:58:005631.255638.505630.005637.251.05629.005636.005627.255635.002.05634.005635.005634.005635.003.0
2025-04-02 16:59:005625.755636.005624.005631.251.05623.505632.755620.755629.002.05627.005627.005627.005627.001.0
2025-04-02 17:00:005633.255634.505625.755625.751.05630.505632.005623.505623.501.05628.755628.755626.755626.7536.0

To get the expiration dates of all the contracts in a FutureHistory object, call the get_expiry_dates method.

Select Language:
expiries = history.get_expiry_dates()

Continuous Price History

To get historical trade, quote, or tick data for the continuous contract, use the symbol property of the Future object when you make the history request.

Select Language:
# Get the daily TradeBar objects of the continuous contract. 
history = qb.history(TradeBar, future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1), Resolution.DAILY)
closehighlowopenvolume
expirysymboltime
1899-12-30/ES2025-01-02 17:00:005972.2368306037.8103775926.5875546020.4081661496415.0
2025-01-03 17:00:006038.0625836049.6640565986.3603645997.4574251009229.0
2025-01-06 17:00:006081.4420066121.7949576056.9780296085.9817131207465.0
2025-01-07 17:00:006007.2934576098.8442165987.3691876095.3133331543464.0
2025-01-08 17:00:006007.2934576024.4434625969.2103596006.5368391436052.0
..................
2025-03-25 17:00:005832.0000005837.2500005809.5000005826.000000842430.0
2025-03-26 17:00:005754.7500005834.5000005743.0000005824.0000001269497.0
2025-03-27 17:00:005741.2500005779.7500005720.0000005742.7500001287285.0
2025-03-28 17:00:005602.5000005731.2500005602.2500005723.5000001595221.0
2025-03-31 17:00:005644.5000005672.7500005533.7500005563.5000001766518.0

Daily Prices History

To get daily data on all the tradable contracts for a given date, call the history method with the FutureUniverse type and the continuous contract Symbol. If you pass flatten=True, this method returns a DataFrame with columns for the data point attributes. The result contains the entire Futures chain for each trading day, not the subset of contracts that pass your universe filter. The daily Futures chains contain the prices, volume, and open interest.

Select Language:
# Get the daily contract objects during Q1 2025. 
history = qb.history(FutureUniverse, future.symbol, datetime(2025, 1, 1), datetime(2025, 4, 1), flatten=True)
closehighlowopenopeninterestvaluevolume
timesymbol
2025-01-03ES YQYHC5L1GPA95920.0005985.0005874.7505967.7502068557.05920.0001496415.0
ES YTG30NVEFCW15975.7506037.5005930.0006018.7507388.05975.7501305.0
ES YVXOP65RE0HT6030.2506030.2506000.0006017.750393.06030.25013.0
ES YYFADOG4CO3L6086.6256185.7505938.8756133.3751152.06086.6250.0
ES Z0WW26QHBBPD6139.0006187.3756113.3756187.3750.06139.0000.0
...........................
2025-03-29ES Z0WW26QHBBPD5750.0005750.0005750.0005750.0006.05750.0001.0
ES Z3EHQP0U9ZB50.0000.0000.0000.0000.00.0000.0
2025-04-01ES YTG30NVEFCW15644.5005672.7505533.7505563.5002082053.05644.5001766518.0
ES YVXOP65RE0HT5691.7505719.7505580.0005612.0007042.05691.750632.0
ES YYFADOG4CO3L5735.0005821.1255617.7505654.2502540.05735.0000.0
# Select the contract with the largest open interest each day.
most_oi = history.groupby('time').apply(lambda x: x.nlargest(1, 'openinterest')).reset_index(level=1, drop=True).openinterest
time        symbol         
2025-01-03  ES YQYHC5L1GPA9    2068557.0
2025-01-04  ES YQYHC5L1GPA9    2068557.0
2025-01-07  ES YQYHC5L1GPA9    2048207.0
2025-01-08  ES YQYHC5L1GPA9    2058863.0
2025-01-09  ES YQYHC5L1GPA9    2047807.0
                                 ...    
2025-03-26  ES YTG30NVEFCW1    2086227.0
2025-03-27  ES YTG30NVEFCW1    2064932.0
2025-03-28  ES YTG30NVEFCW1    2070698.0
2025-03-29  ES YTG30NVEFCW1    2064619.0
2025-04-01  ES YTG30NVEFCW1    2082053.0
Name: openinterest, Length: 62, dtype: float64

If you intend to use the data in the DataFrame to create FutureUniverse 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 FutureUniverse objects instead of a DataFrame, call the history[FutureUniverse] method.

# Get the 5 trailing daily FutureUniverse objects in FutureUniverse format. 
history = qb.history[FutureUniverse](future.symbol, 5, Resolution.DAILY)
# Iterate through the FutureUniverse objects and access their volumes.
for future_universe in history:
    t = future_universe.end_time
    most_oi = sorted(future_universe, key=lambda contract: contract.open_interest)[-1]

The method represents each contract with an FutureUniverse object, which have the following properties:

Examples

The following examples demonstrate some common practices for applying the Futures dataset.

Example 1: 5-Minute Candlestick Plot

The following example studies the candlestick pattern of the ES Future. To study the short term pattern, we consolidate the data into 5 minute bars and plot the 5-minute candlestick plot.

Select Language:
# Import plotly library for plotting.
import plotly.graph_objects as go

# Create a QuantBook
qb = QuantBook()

# Request the continuous future historical data.
# Use raw normalization mode to fairly compare the actual bid and ask dollar volume.
future = qb.add_future(Futures.Indices.SP_500_E_MINI)
history = qb.history(
    future.symbol, 
    start=datetime(2024, 7, 1), 
    end=datetime(2025, 1, 1), 
    resolution=Resolution.MINUTE, 
    fill_forward=True, 
    extended_market_hours=True, 
    data_mapping_mode=DataMappingMode.OPEN_INTEREST, 
    data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO, 
    contract_depth_offset=0
)

# Drop level 0, 1 index (Symbol index) from the DataFrame
history = history.droplevel([0, 1])

# Select the required columns to obtain the 5-minute OHLC data.
history = history[["open", "high", "low", "close"]].resample("5T").agg({
    "open": "first",
    "high": "max",
    "low": "min",
    "close": "last"
})

# Crete the Candlestick chart using the 5-minute windows.
candlestick = go.Candlestick(
    x=history.index,
    open=history['open'],
    high=history['high'],
    low=history['low'],
    close=history['close']
)
# Create a Layout as the plot settings.
layout = go.Layout(
    title=go.layout.Title(text=f'{future.symbol} OHLC'),
    xaxis_title='Date',
    yaxis_title='Price',
    xaxis_rangeslider_visible=False
)
# Create the Figure.
fig = go.Figure(data=[candlestick], layout=layout)
# Display the plot.
fig.show()
ES continuous contract candlestick plot.

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: