---
title: "Futures"
description: "Some of the Futures data you can get include prices, open interest, indicators, and contract chain data."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/asset-classes/futures
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/asset-classes/futures.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/20%20Historical%20Data/04%20Asset%20Classes/06%20Futures
modified: 2026-10-30
index: https://www.quantconnect.com/llms.txt
---

# Futures

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Historical Data > Asset Classes > Futures

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

This page explains how to get historical data for Futures. Some of the data you can get include prices, open interest, indicators, and contract chain data.

## Trades

To get historical [trade data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/handling-data.md#02-Trades), 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.

```python
class FutureTradeBarHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Get the Symbol of a security.
        future = self.add_future(Futures.Indices.SP_500_E_MINI)
        symbol = list(self.futures_chain(future.symbol))[0].symbol
        # Get the 5 trailing daily TradeBar objects of the security in DataFrame format.
        history = self.history(TradeBar, symbol, 5, Resolution.DAILY)
```

| expiry | symbol | time | close | high | low | open | volume |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-12 17:00:00 | 6058.75 | 6087.75 | 6055.50 | 6082.25 | 1152801.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-13 17:00:00 | 6051.25 | 6084.75 | 6041.25 | 6077.25 | 1027682.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-16 17:00:00 | 6076.50 | 6090.50 | 6064.75 | 6072.50 | 378263.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 17:00:00 | 6052.00 | 6063.50 | 6040.75 | 6052.75 | 278531.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-18 17:00:00 | 5872.25 | 6074.50 | 5840.00 | 6050.25 | 335048.0 |

```python
# Calculate the daily returns.
daily_returns = history.close.pct_change().iloc[1:]
```

```python
expiry               symbol           time
2024-12-20 13:30:00  ES YOGVNNAOI1OH  2024-12-13 17:00:00   -0.001238
                                      2024-12-16 17:00:00    0.004173
                                      2024-12-17 17:00:00   -0.004032
                                      2024-12-18 17:00:00   -0.029701
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.

```python
# 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](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/handling-data.md#03-Quotes), 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.

```python
class FutureQuoteBarHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Get the Symbol of a security.
        future = self.add_future(Futures.Indices.SP_500_E_MINI)
        symbol = list(self.futures_chain(future.symbol))[0].symbol
        # Get the 5 trailing minute QuoteBar objects of the security in DataFrame format.
        history = self.history(QuoteBar, symbol, 5, Resolution.MINUTE)
```

| expiry | symbol | time | askclose | askhigh | asklow | askopen | asksize | bidclose | bidhigh | bidlow | bidopen | bidsize | close | high | low | open |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-12 17:00:00 | 6058.75 | 6087.75 | 6055.75 | 6082.50 | 19.0 | 6058.50 | 6087.50 | 6055.50 | 6082.25 | 52.0 | 6058.625 | 6087.625 | 6055.625 | 6082.375 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-13 17:00:00 | 6051.50 | 6085.00 | 6041.50 | 6077.50 | 59.0 | 6051.25 | 6084.75 | 6041.25 | 6077.25 | 1.0 | 6051.375 | 6084.875 | 6041.375 | 6077.375 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-16 17:00:00 | 6076.75 | 6090.75 | 6064.75 | 6072.50 | 10.0 | 6076.50 | 6090.50 | 6064.50 | 6072.25 | 7.0 | 6076.625 | 6090.625 | 6064.625 | 6072.375 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 17:00:00 | 6052.25 | 6063.50 | 6041.00 | 6053.00 | 12.0 | 6052.00 | 6063.25 | 6040.50 | 6052.75 | 1.0 | 6052.125 | 6063.375 | 6040.750 | 6052.875 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-18 17:00:00 | 5872.75 | 6074.75 | 5840.25 | 6050.25 | 2.0 | 5872.25 | 6074.50 | 5840.00 | 6050.00 | 1.0 | 5872.500 | 6074.625 | 5840.125 | 6050.125 |

```python
# Calculate the spread at each minute.
spread = history.askclose - history.bidclose
```

```python
expiry               symbol           time
2024-12-20 13:30:00  ES YOGVNNAOI1OH  2024-12-12 17:00:00    0.25
                                      2024-12-13 17:00:00    0.25
                                      2024-12-16 17:00:00    0.25
                                      2024-12-17 17:00:00    0.25
                                      2024-12-18 17:00:00    0.50
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.

```python
# 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
```

## Ticks

To get historical [tick data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/handling-data.md#04-Ticks), 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.

```python
class FutureTickHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Get the Symbol of a security.
        future = self.add_future(Futures.Indices.SP_500_E_MINI)
        symbol = list(self.futures_chain(future.symbol))[0].symbol
        # Get the trailing 2 days of ticks for the security in DataFrame format.
        history = self.history(symbol, timedelta(2), Resolution.TICK)
```

| expiry | symbol | time | askprice | asksize | bidprice | bidsize | lastprice | openinterest | quantity |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | NaN | NaN | NaN | NaN | 6052.75 | NaN | 1.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | 0.0 | 0.0 | 6052.75 | 33.0 | 6052.75 | NaN | 0.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | 6053.0 | 11.0 | 0.00 | 0.0 | 6053.00 | NaN | 0.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | 6053.0 | 10.0 | 0.00 | 0.0 | 6053.00 | NaN | 0.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | 6053.0 | 9.0 | 0.00 | 0.0 | 6053.00 | NaN | 0.0 |

```python
# 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)
```

| expiry | symbol | time | lastprice | quantity |
| --- | --- | --- | --- | --- |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | 6052.75 | 1.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.002 | 6053.00 | 1.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.002 | 6053.00 | 2.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.003 | 6052.75 | 1.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.003 | 6052.75 | 3.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.

```python
# 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](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md) 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.

```python
class SliceHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 1)
        self.set_end_date(2024, 12, 31)
        # Add some securities and datasets.
        self.add_future(Futures.Indices.SP_500_E_MINI)
        # 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
```

## Continuous Contract Prices

To get historical trade, quote, or tick data for the [continuous contract](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/requesting-data/universes.md#03-Continous-Contracts), use the `symbol` property of the `Future` object when you make the history request.

```python
class FutureContinuousContractHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Add the Future and specify the contract rollover settings.
        future = self.add_future(
            Futures.Indices.SP_500_E_MINI,
            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
            contract_depth_offset=0
        )
        # Get the 5 trailing daily TradeBar objects of the continuous contract.
        history = self.history(TradeBar, future.symbol, 5, Resolution.DAILY)
```

| expiry | symbol | time | close | high | low | open | volume |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1899-12-30 | /ES | 2024-12-12 17:00:00 | 6132.582256 | 6161.935651 | 6129.292651 | 6156.368628 | 1152801.0 |
| 1899-12-30 | /ES | 2024-12-13 17:00:00 | 6124.990860 | 6158.899093 | 6114.869000 | 6151.307698 | 1027682.0 |
| 1899-12-30 | /ES | 2024-12-16 17:00:00 | 6150.548558 | 6164.719163 | 6138.655372 | 6146.499814 | 378263.0 |
| 1899-12-30 | /ES | 2024-12-17 17:00:00 | 6125.750000 | 6137.390140 | 6114.362907 | 6126.509140 | 278531.0 |
| 1899-12-30 | /ES | 2024-12-18 17:00:00 | 5939.500000 | 6148.000000 | 5906.500000 | 6124.000000 | 2009987.0 |

```python
# Calculate the daily returns.
daily_returns = history.close.pct_change().iloc[1:]
```

```python
expiry      symbol  time
1899-12-30  /ES     2024-12-13 17:00:00   -0.001238
                    2024-12-16 17:00:00    0.004173
                    2024-12-17 17:00:00   -0.004032
                    2024-12-18 17:00:00   -0.030404
Name: close, dtype: float64
```

## Symbol Changes

To get historical [symbol change data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/handling-data.md#09-Symbol-Changes), call the `history` method with the `SymbolChangedEvent` type and the continuous contract Symbol. This method returns a DataFrame that contains the old and new Symbol for each rollover.

```python
class FutureSymbolChangeEventsHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Add the Future and specify the contract rollover settings.
        future = self.add_future(
            Futures.Indices.SP_500_E_MINI,
            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
            contract_depth_offset=0
        )
        # Get the contract rollovers for the trailing year.
        history = self.history(SymbolChangedEvent, future.symbol, timedelta(365))
```

| expiry | symbol | time | newsymbol | oldsymbol |
| --- | --- | --- | --- | --- |
| 1899-12-30 | /ES | 2024-03-13 | ES YJHOAMPYKQGX | ES YGT6HGVF2SQP |
| 1899-12-30 | /ES | 2024-06-19 | ES YLZ9Z50BJE2P | ES YJHOAMPYKQGX |
| 1899-12-30 | /ES | 2024-09-18 | ES YOGVNNAOI1OH | ES YLZ9Z50BJE2P |
| 1899-12-30 | /ES | 2024-12-18 | ES YQYHC5L1GPA9 | ES YOGVNNAOI1OH |

```python
# Select the dates of each rollover.
dates = list(history.index.levels[2])
```

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.

```python
# Get the rollovers of the continuous contract during 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
```

## Open Interest

To get historical [open interest data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/futures/handling-data.md#06-Futures-Contracts), call the `history` method with the `OpenInterest` type and a security's `Symbol`. This method returns a DataFrame with a single column.

```python
class FutureOpenInterestHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Get the Symbol of a security.
        future = self.add_future(Futures.Indices.SP_500_E_MINI)
        symbol = list(self.futures_chain(future.symbol))[0].symbol
        # Get the 5 trailing daily OpenInterest objects of the security in DataFrame format.
        history = self.history(OpenInterest, symbol, 5, Resolution.DAILY)
```

| expiry | symbol | time | openinterest |
| --- | --- | --- | --- |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-14 19:00:00 | 1631020.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-15 19:00:00 | 1625312.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-16 19:00:00 | 965789.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 19:00:00 | 687472.0 |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-18 19:00:00 | 556365.0 |

```python
# Calculate the daily change in open interest.
oi_delta = history.openinterest.diff().iloc[1:]
```

```python
expiry               symbol           time
2024-12-20 13:30:00  ES YOGVNNAOI1OH  2024-12-15 19:00:00     -5708.0
                                      2024-12-16 19:00:00   -659523.0
                                      2024-12-17 19:00:00   -278317.0
                                      2024-12-18 19:00:00   -131107.0
Name: openinterest, dtype: float64
```

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

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

## Contracts

To get historical Futures contracts, call the `history` method with the `FutureUniverse` type and the continuous contract `Symbol`. The data this method returns contains information on all the currently tradable contracts, not just the contracts that pass your filter. If you pass `flatten=True`, this method returns a DataFrame with columns for the data point attributes.

```python
class FutureContractsHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Add a Future.
        future = self.add_future(Futures.Indices.SP_500_E_MINI)
        # Get the daily contract data over the last two trading days.
        history = self.history(FutureUniverse, future.symbol, 2, flatten=True)
```

| time | symbol | close | high | low | open | openinterest | value | volume |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-12-18 | ES YOGVNNAOI1OH | 6052.000 | 6063.500 | 6040.750 | 6052.750 | 687472.0 | 6052.000 | 278531.0 |
| 2024-12-18 | ES YQYHC5L1GPA9 | 6125.750 | 6138.250 | 6114.250 | 6127.500 | 1902280.0 | 6125.750 | 997849.0 |
| 2024-12-18 | ES YTG30NVEFCW1 | 6185.250 | 6198.750 | 6173.500 | 6184.250 | 5044.0 | 6185.250 | 197.0 |
| 2024-12-18 | ES YVXOP65RE0HT | 6238.250 | 6258.000 | 6229.375 | 6238.250 | 20.0 | 6238.250 | 0.0 |
| 2024-12-18 | ES YYFADOG4CO3L | 6299.125 | 6313.000 | 6057.000 | 6071.500 | 1106.0 | 6299.125 | 0.0 |
| 2024-12-19 | ES YOGVNNAOI1OH | 5872.250 | 6074.500 | 5840.000 | 6050.250 | 556365.0 | 5872.250 | 335048.0 |
| 2024-12-19 | ES YQYHC5L1GPA9 | 5939.500 | 6148.000 | 5906.500 | 6124.000 | 2064361.0 | 5939.500 | 2009987.0 |
| 2024-12-19 | ES YTG30NVEFCW1 | 6001.250 | 6205.000 | 5966.000 | 6181.250 | 5096.0 | 6001.250 | 536.0 |
| 2024-12-19 | ES YVXOP65RE0HT | 6054.250 | 6450.750 | 5934.375 | 6243.375 | 20.0 | 6054.250 | 0.0 |
| 2024-12-19 | ES YYFADOG4CO3L | 6315.000 | 6315.000 | 6315.000 | 6315.000 | 1116.0 | 6315.000 | 10.0 |
| 2024-12-19 | ES Z0WW26QHBBPD | 6171.375 | 6379.625 | 6142.000 | 6368.375 | 0.0 | 6171.375 | 0.0 |

```python
# 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
```

```python
time        symbol
2024-12-18  ES YQYHC5L1GPA9    1902280.0
2024-12-19  ES YQYHC5L1GPA9    2064361.0
Name: openinterest, 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.

```python
# Get the 5 trailing daily FutureUniverse objects in FutureUniverse format.
history = self.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]
```

## Contango

To get historical [contango data for VX Futures](https://www.quantconnect.com/datasets/quantconnect-vixcentral-contango), call the `history` method with the dataset `Symbol`. This method returns a DataFrame that contains the data point attributes.

```python
class VIXContangoHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Add the dataset and save a reference to its Symbol.
        symbol = self.add_data(VIXCentralContango, "VIX", Resolution.DAILY).symbol
        # Get the trailing 7 days of contango data in DataFrame format.
        history = self.history(symbol, 7, Resolution.DAILY)
```

| symbol | time | contango_f2_minus_f1 | contango_f7_minus_f4 | contango_f7_minus_f4_div_3 | f1 | f2 | f3 | f4 | f5 | f6 | f7 | f8 | frontmonth | period |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| VIX.VIXCentralContango | 2024-12-13 | 0.1314 | 0.0498 | 0.0166 | 14.4062 | 16.2991 | 17.1553 | 17.9005 | 18.2460 | 18.5583 | 18.7923 | 18.9500 | 12 | 1 days |
| VIX.VIXCentralContango | 2024-12-14 | 0.1212 | 0.0497 | 0.0166 | 14.5190 | 16.2782 | 17.1250 | 17.9474 | 18.2993 | 18.5750 | 18.8390 | 19.0500 | 12 | 1 days |
| VIX.VIXCentralContango | 2024-12-17 | 0.1299 | 0.0457 | 0.0152 | 14.6997 | 16.6091 | 17.4592 | 18.1963 | 18.4965 | 18.7411 | 19.0282 | 19.1884 | 12 | 1 days |
| VIX.VIXCentralContango | 2024-12-18 | 0.0765 | 0.0389 | 0.0130 | 15.7483 | 16.9531 | 17.6666 | 18.2998 | 18.4996 | 18.7185 | 19.0108 | 19.1500 | 12 | 1 days |

```python
# Calculate the changes in contango.
contango_diff = history.f1.diff().iloc[1:]
```

```python
symbol                  time
VIX.VIXCentralContango  2024-12-14    0.1128
                        2024-12-17    0.1807
                        2024-12-18    1.0486
Name: f1, dtype: float64
```

If you intend to use the data in the DataFrame to create `VIXCentralContango` 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[VIXCentralContango]` method.

```python
# Get the trailing 7 days of contango data in VIXCentralContango format.
history = self.history[VIXCentralContango](symbol, 7, Resolution.DAILY)
# Iterate through each VIXCentralContango object.
for data_point in history:
    t = data_point.end_time
    value = data_point.contango_f_2_minus_f_1
```

## Indicators

To get historical [indicator](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/key-concepts.md) values, call the `indicator_history` method with an indicator and the security's `Symbol`.

```python
class FuturesIndicatorHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Get the Symbol of a security.
        symbol = self.add_future(Futures.Indices.SP_500_E_MINI).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.

```python
# Organize the historical indicator data into a DataFrame to enable pandas wrangling.
history_df = history.data_frame
```

|  | current | rollingsum |
| --- | --- | --- |
| 2024-12-12 17:00:00 | 6150.577121 | 129162.119546 |
| 2024-12-13 17:00:00 | 6154.322490 | 129240.772299 |
| 2024-12-16 17:00:00 | 6162.919815 | 129421.316116 |
| 2024-12-17 17:00:00 | 6169.413410 | 129557.681602 |
| 2024-12-18 17:00:00 | 6166.050570 | 129487.061970 |

```python
# 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](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/automatic-indicators.md#07-Alternative-Price-Fields) instead of the close (or mid-price) of each bar, pass a `selector` argument.

```python
# 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](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/supported-indicators/beta.md)). In this case, pass a list of the `Symbol` objects to the method.

```python
class FuturesMultiAssetIndicatorHistoryAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 12, 19)
        self.set_end_date(2024, 12, 31)
        # Add the target and reference securities.
        target_symbol = self.add_future(Futures.Metals.GOLD).symbol
        reference_symbol = self.add_future(Futures.Indices.SP_500_E_MINI).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()
```

## Examples

The following examples demonstrate some common practices for trading Futures with historical data.

### Example 1: Stock-Gold All-Weather Portfolio

The following algorithm constructs a monthly-rebalanced, risk-parity portfolio using S&P 500 E-Mini and Micro Gold Futures contracts. A risk-parity approach balances the contribution to risk from each asset class, helping reduce overall portfolio drawdowns and improve diversification. The position sizing is determined using 1-year of historical daily returns for the selected Futures universe.

```python
from Portfolio.RiskParityPortfolioOptimizer import RiskParityPortfolioOptimizer

class FuturesHistoricalDataAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(1_000_000)

        # Select the future contracts representing various asset classes to diversify the portfolio.
        self._futures = [self.add_future(
                x,
                fill_forward=True,
                extended_market_hours=True,
                data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
                data_mapping_mode=DataMappingMode.OPEN_INTEREST,
                contract_depth_offset=0
            ) for x in [Futures.Indices.SP_500_E_MINI, Futures.Metals.MICRO_GOLD]]

        # Instantiate the optimizer to perform risk-parity optimization.
        # Risk Parity portfolio can dissipate the risk of each crypto pair to reduce overall drawdown.
        self._optimizer = RiskParityPortfolioOptimizer(0.0, 1.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.after_market_open(self._futures[0].symbol, 1),
            self.rebalance
        )

    def rebalance(self) -> None:
        # Historical data request to get 1-year data for optimization.
        history = self.history([x.symbol for x in self._futures], 253, Resolution.DAILY, extended_market_hours=True, fill_forward=True)\
            .droplevel([0]).unstack(0).close.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(future.mapped, size/2.0) for future, size in zip(self._futures, weights)]
        self.set_holdings(targets, liquidate_existing_holdings=True)
```
