Datasets

Equity Options

Introduction

This page explains how to request, manipulate, and visualize historical Equity Options data.

Prerequisites

Working knowledge of C#.

Working knowedge of Python and pandas. If you are not familiar with pandas, see the pandas documentation.

Create Subscriptions

Follow these steps to subscribe to an Equity Option security:

  1. Load the required assembly files and data types.
  2. #load "../Initialize.csx"
    #load "../QuantConnect.csx"
    
    using QuantConnect;
    using QuantConnect.Data;
    using QuantConnect.Data.Market;
    using QuantConnect.Algorithm;
    using QuantConnect.Securities;
    using QuantConnect.Securities.Option;
    using QuantConnect.Research;
  3. Create a QuantBook.
  4. var qb = new QuantBook();
    qb = QuantBook()
  5. Subscribe to the underlying Equity with raw data normalization and save a reference to the Equity Symbol.
  6. var equitySymbol = qb.AddEquity("SPY", dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
    equity_symbol = qb.AddEquity("SPY", dataNormalizationMode=DataNormalizationMode.Raw).Symbol
  7. Call the AddOption method with the underlying Equity Symbol.
  8. var option = qb.AddOption(equitySymbol);
    option = qb.AddOption(equity_symbol)
  9. (Optional) Set a contract filter.
  10. option.SetFilter(-1, 1, 0, 90);
    option.SetFilter(-1, 1, 0, 90)

    The filter determines which contracts the GetOptionHistory method returns. If you don't set a filter, the method returns all of the contracts.

If you want historical data on individual contracts and their OpenInterest, follow these steps to subscribe to the individual Equity Option contracts:

  1. Call the GetOptionsContractList method with the underlying Equity Symbol and a datetimeDateTime.
  2. var startDate = new DateTime(2021, 12, 31);
    var contractSymbols = qb.OptionChainProvider.GetOptionContractList(equitySymbol, startDate);
    start_date = datetime(2021, 12, 31)
    contract_symbols = qb.OptionChainProvider.GetOptionContractList(equity_symbol, start_date)

    This method returns a list of Symbol objects that reference the Option contracts that were trading at the given time.

  3. Select the Symbol of the OptionContract object(s) for which you want to get historical data.
  4. To filter and select contracts, you can use the following properties of each Symbol object:

    PropertyDescription
    ID.DateThe expiration date of the contract.
    ID.StrikePriceThe strike price of the contract.
    ID.OptionRight The contract type. The OptionRight enumeration has the following members:
    ID.OptionStyle The contract style. The OptionStyle enumeration has the following members:
    var contractSymbol = contractSymbols.Where(s => 
        s.ID.OptionRight == OptionRight.Call &&
        s.ID.StrikePrice == 477 &&
        s.ID.Date == new DateTime(2022, 1, 21)).First();
    contract_symbol = [s for s in contract_symbols 
        if s.ID.OptionRight == OptionRight.Call 
            and s.ID.StrikePrice == 477 
            and s.ID.Date == datetime(2022, 1, 21)][0]
  5. Call the AddOptionContract method with an OptionContract Symbol and disable fill-forward.
  6. qb.AddOptionContract(contractSymbol, fillDataForward: false);
    qb.AddOptionContract(contract_symbol, fillDataForward = False)

    Disable fill-forward because there are only a few OpenInterest data points per day.

Get Historical Data

You need a subscription before you can request historical data for Equity Option contracts. On the time dimension, you can request an amount of historical data based on a trailing number of bars, a trailing period of time, or a defined period of time. On the contract dimension, you can request historical data for a single contract, a subset of the contracts you created subscriptions for in your notebook, or all of the contracts in your notebook.

Before you request historical data, call the SetStartDate method with a datetimeDateTime to reduce the risk of look-ahead bias.

qb.SetStartDate(startDate);
qb.SetStartDate(start_date)

If you call the SetStartDate method, the date that you pass to the method is the latest date for which your history requests will return data.

Trailing Number of Bars

To get historical data for a number of trailing bars, call the History method with the contract Symbol object(s) and an integer.

// Slice objects
var singleHistorySlice = qb.History(contractSymbol, 10);
var subsetHistorySlice = qb.History(new[] {contractSymbol}, 10);
var allHistorySlice = qb.History(10);

// TradeBar objects
var singleHistoryTradeBars = qb.History<TradeBar>(contractSymbol, 10);
var subsetHistoryTradeBars = qb.History<TradeBar>(new[] {contractSymbol}, 10);
var allHistoryTradeBars = qb.History<TradeBar>(qb.Securities.Keys, 10);

// QuoteBar objects
var singleHistoryQuoteBars = qb.History<QuoteBar>(contractSymbol, 10);
var subsetHistoryQuoteBars = qb.History<QuoteBar>(new[] {contractSymbol}, 10);
var allHistoryQuoteBars = qb.History<QuoteBar>(qb.Securities.Keys, 10);

// OpenInterest objects
var singleHistoryOpenInterest = qb.History<OpenInterest>(contractSymbol, 400);
var subsetHistoryOpenInterest = qb.History<OpenInterest>(new[] {contractSymbol}, 400);
var allHistoryOpenInterest = qb.History<OpenInterest>(qb.Securities.Keys, 400);
# DataFrame
single_history_df = qb.History(contract_symbol, 10)
single_history_trade_bar_df = qb.History(TradeBar, contract_symbol, 10)
single_history_open_interest_df = qb.History(OpenInterest, contract_symbol, 400)
subset_history_df = qb.History([contract_symbol], 10)
subset_history_trade_bar_df = qb.History(TradeBar, [contract_symbol], 10)
subset_history_open_interest_df = qb.History(OpenInterest, [contract_symbol], 400)
all_history_df = qb.History(qb.Securities.Keys, 10)
all_history_trade_bar_df = qb.History(TradeBar, qb.Securities.Keys, 10)
all_history_open_interest_df = qb.History(OpenInterest, qb.Securities.Keys, 400)

# Slice objects
all_history_slice = qb.History(10)

# TradeBar objects
single_history_trade_bars = qb.History[TradeBar](contract_symbol, 10)
subset_history_trade_bars = qb.History[TradeBar]([contract_symbol], 10)
all_history_trade_bars = qb.History[TradeBar](qb.Securities.Keys, 10) # QuoteBar objects single_history_quote_bars = qb.History[QuoteBar](contract_symbol, 10) subset_history_quote_bars = qb.History[QuoteBar]([contract_symbol], 10) all_history_quote_bars = qb.History[QuoteBar](qb.Securities.Keys, 10) # OpenInterest objects single_history_open_interest = qb.History[OpenInterest](contract_symbol, 400) subset_history_open_interest = qb.History[OpenInterest]([contract_symbol], 400) all_history_open_interest = qb.History[OpenInterest](qb.Securities.Keys, 400)

The preceding calls return the most recent bars, excluding periods of time when the exchange was closed.

Trailing Period of Time

To get historical data for a trailing period of time, call the History method with the contract Symbol object(s) and a TimeSpantimedelta.

// Slice objects
var singleHistorySlice = qb.History(contractSymbol, TimeSpan.FromDays(3));
var subsetHistorySlice = qb.History(new[] {contractSymbol}, TimeSpan.FromDays(3));
var allHistorySlice = qb.History(10); // TradeBar objects var singleHistoryTradeBars = qb.History<TradeBar>(contractSymbol, TimeSpan.FromDays(3));
var subsetHistoryTradeBars = qb.History<TradeBar>(new[] {contractSymbol}, TimeSpan.FromDays(3));
var allHistoryTradeBars = qb.History<TradeBar>(TimeSpan.FromDays(3)); // QuoteBar objects var singleHistoryQuoteBars = qb.History<QuoteBar>(contractSymbol, TimeSpan.FromDays(3), Resolution.Minute);
var subsetHistoryQuoteBars = qb.History<QuoteBar>(new[] {contractSymbol}, TimeSpan.FromDays(3), Resolution.Minute);
var allHistoryQuoteBars = qb.History<QuoteBar>(qb.Securities.Keys, TimeSpan.FromDays(3), Resolution.Minute); // OpenInterest objects var singleHistoryOpenInterest = qb.History<OpenInterest>(contractSymbol, TimeSpan.FromDays(2)); var subsetHistoryOpenInterest = qb.History<OpenInterest>(new[] {contractSymbol}, TimeSpan.FromDays(2)); var allHistoryOpenInterest = qb.History<OpenInterest>(qb.Securities.Keys, TimeSpan.FromDays(2));
# DataFrame
single_history_df = qb.History(contract_symbol, timedelta(days=3))
single_history_trade_bar_df = qb.History(TradeBar, contract_symbol, timedelta(days=3))
single_history_open_interest_df = qb.History(OpenInterest, contract_symbol, timedelta(days=3))
subset_history_df = qb.History([contract_symbol], timedelta(days=3))
subset_history_trade_bar_df = qb.History(TradeBar, [contract_symbol], timedelta(days=3))
subset_history_open_interest_df = qb.History(OpenInterest, [contract_symbol], timedelta(days=3))
all_history_df = qb.History(qb.Securities.Keys, timedelta(days=3))
all_history_trade_bar_df = qb.History(TradeBar, qb.Securities.Keys, timedelta(days=3))
all_history_open_interest_df = qb.History(OpenInterest, qb.Securities.Keys, timedelta(days=3))

# Slice objects
all_history_slice = qb.History(timedelta(days=3))

# TradeBar objects
single_history_trade_bars = qb.History[TradeBar](contract_symbol, timedelta(days=3))
subset_history_trade_bars = qb.History[TradeBar]([contract_symbol], timedelta(days=3))
all_history_trade_bars = qb.History[TradeBar](qb.Securities.Keys, timedelta(days=3))

# QuoteBar objects
single_history_quote_bars = qb.History[QuoteBar](contract_symbol, timedelta(days=3), Resolution.Minute)
subset_history_quote_bars = qb.History[QuoteBar]([contract_symbol], timedelta(days=3), Resolution.Minute)
all_history_quote_bars = qb.History[QuoteBar](qb.Securities.Keys, timedelta(days=3), Resolution.Minute)

# OpenInterest objects
single_history_open_interest = qb.History[OpenInterest](contract_symbol, timedelta(days=2))
subset_history_open_interest = qb.History[OpenInterest]([contract_symbol], timedelta(days=2))
all_history_open_interest = qb.History[OpenInterest](qb.Securities.Keys, timedelta(days=2))

The preceding calls return the most recent bars, excluding periods of time when the exchange was closed.

Defined Period of Time

To get historical data for individual Option contracts during a specific period of time, call the History method with the contract Symbol object(s), a start DateTimedatetime, and an end DateTimedatetime.

var startTime = new DateTime(2021, 12, 1);
var endTime = new DateTime(2021, 12, 31);

// Slice objects
var singleHistorySlice = qb.History(contractSymbol, startTime, endTime);
var subsetHistorySlice = qb.History(new[] {contractSymbol}, startTime, endTime);
var allHistorySlice = qb.History(startTime, endTime); // TradeBar objects var singleHistoryTradeBars = qb.History<TradeBar>(contractSymbol, startTime, endTime);
var subsetHistoryTradeBars = qb.History<TradeBar>(new[] {contractSymbol}, startTime, endTime);
var allHistoryTradeBars = qb.History<TradeBar>(qb.Securities.Keys, startTime, endTime); // QuoteBar objects var singleHistoryQuoteBars = qb.History<QuoteBar>(contractSymbol, startTime, endTime, Resolution.Minute);
var subsetHistoryQuoteBars = qb.History<QuoteBar>(new[] {contractSymbol}, startTime, endTime, Resolution.Minute);
var allHistoryQuoteBars = qb.History<QuoteBar>(qb.Securities.Keys, startTime, endTime, Resolution.Minute); // OpenInterest objects var singleHistoryOpenInterest = qb.History<OpenInterest>(contractSymbol, startTime, endTime); var subsetHistoryOpenInterest = qb.History<OpenInterest>(new[] {contractSymbol}, startTime, endTime); var allHistoryOpenInterest = qb.History<OpenInterest>(qb.Securities.Keys, startTime, endTime);
start_time = datetime(2021, 12, 1)
end_time = datetime(2021, 12, 31)

# DataFrame
single_history_df = qb.History(contract_symbol, start_time, end_time)
single_history_trade_bar_df = qb.History(TradeBar, contract_symbol, start_time, end_time)
single_history_open_interest_df = qb.History(OpenInterest, contract_symbol, start_time, end_time)
subset_history_df = qb.History([contract_symbol], start_time, end_time)
subset_history_trade_bar_df = qb.History(TradeBar, [contract_symbol], start_time, end_time)
subset_history_open_interest_df = qb.History(OpenInterest, [contract_symbol], start_time, end_time)
all_history_df = qb.History(qb.Securities.Keys, start_time, end_time)
all_history_trade_bar_df = qb.History(TradeBar, qb.Securities.Keys, start_time, end_time)
all_history_trade_open_interest_df = qb.History(OpenInterest, qb.Securities.Keys, start_time, end_time)

# Slice objects
all_history_slice = qb.History(start_time, end_time)

# TradeBar objects
single_history_trade_bars = qb.History[TradeBar](contract_symbol, start_time, end_time)
subset_history_trade_bars = qb.History[TradeBar]([contract_symbol], start_time, end_time)
all_history_trade_bars = qb.History[TradeBar](qb.Securities.Keys, start_time, end_time) # QuoteBar objects single_history_quote_bars = qb.History[QuoteBar](contract_symbol, start_time, end_time, Resolution.Minute)
subset_history_quote_bars = qb.History[QuoteBar]([contract_symbol], start_time, end_time, Resolution.Minute)
all_history_quote_bars = qb.History[QuoteBar](qb.Securities.Keys, start_time, end_time, Resolution.Minute) # OpenInterest objects single_history_open_interest = qb.History[OpenInterest](contract_symbol, start_time, end_time) subset_history_open_interest = qb.History[OpenInterest]([contract_symbol], start_time, end_time) all_history_open_interest = qb.History[OpenInterest](qb.Securities.Keys, start_time, end_time)

To get historical data for all of the Option contracts that pass your filter during a specific period of time, call the GetOptionHistory method with the underlying Equity Symbol object, a start DateTimedatetime, and an end DateTimedatetime.

option_history = qb.GetOptionHistory(equity_symbol, end_time-timedelta(days=2), end_time, Resolution.Minute, fillForward=False, extendedMarket=False)

The preceding calls return data that have a timestamp within the defined period of time.

Resolutions

The following table shows the available resolutions and data formats for Equity Option contract subscriptions:

ResolutionTradeBarQuoteBarTrade TickQuote Tick
Tick

Second

Minutegreen checkgreen check
Hourgreen checkgreen check
Dailygreen checkgreen check

Markets

LEAN groups all of the US Equity Option exchanges under Market.USA, so you don't need to pass a Market to the AddOption or AddOptionContract methods.

Wrangle Data

You need some historical data to perform wrangling operations. Run a cell in a Jupyter Notebook with the pandas object as the last line to display the historical data.

The DataFrame that contains historical data for Options contracts has a MultiIndex with levels for the expiry, strike, OptionRight, Symbol, and timestamp. For some of the wrangling operations, you need to drop the first three index levels. To drop the index levels, run:

contract_history.index = contract_history.index.droplevel([0,1,2])
open_interest_history.index = open_interest_history.index.droplevel([0,1,2])
timespan_contract_history.index = timespan_contract_history.index.droplevel([0,1,2])
timespan_open_interest_history.index = timespan_open_interest_history.index.droplevel([0,1,2])

You need some historical data to perform wrangling operations. Use LINQ to wrangle the data and then call the Console.WriteLine method in a Jupyter Notebook to display the data.

Select One Contract

Iterate through the IEnumerable to get the historical data of the contract.

Index the DataFrame with a Symbol to select the historical data of the contract.

To display the price data of the contract, run:

foreach(var bar in contractHistory.TakeLast(5))
{
    Console.WriteLine($"{bar} EndTime: {bar.EndTime}");
}
contract_history.loc[contract_symbol]

The Jupyter Notebook displays the trade and quote data of the contract.

The Jupyter Notebook displays a DataFrame containing the trade and quote data of the contract.

To display the open interest data of the contract, run:

foreach(var openInterest in openInterestHistory.TakeLast(5))
{
    Console.WriteLine($"{openInterest} EndTime: {openInterest.EndTime}");
}
open_interest_history.loc[contract_symbol]

The Jupyter Notebook displays the open interest of the contract.

The Jupyter Notebook displays a DataFrame containing the open interest of the contract.

Select a Property of the Contract

Iterate through the IEnumerable and select a property of the TradeBar or Slice to get the historical values of the property.

Index the DataFrame with a Symbol to select the historical data of the contract and then select a property column to get the historical values of the property.

To display the closing prices of the contract, run:

To display the closing ask prices of the contract, run:

foreach(var x in contractHistory.TakeLast(5))
{
    Console.WriteLine($"{x.Symbol}: Close: {x.Close} EndTime:{x.EndTime}");
}
contract_history.loc[contract_symbol]['askclose']

The Jupyter Notebook displays the closing prices of the contract.

The Jupyter Notebook displays a Series containing the closing ask prices of the contract.

To display the open interest of the contract, run:

open_interest_history.loc[contract_symbol]['openinterest']

The Jupyter Notebook displays a Series containing the open interest of the contract.

Unstack the Dataframe

If you request historical data for multiple contracts, you can transform the DataFrame so that it is a time series of a property value for all of the containing contracts. Select the column that you want to display for each contract and then call the unstack method to transform the DataFrame into the desired format. You can rename the columns of the transformed DataFrame to be the respective OptionsContract Symbols.

To display the closing bid prices of all of the contracts, run:

df = timespan_contract_history.copy()
df = df['bidclose'].unstack(level=0)
df.columns = [Symbol.GetAlias(SecurityIdentifier.Parse(x), equity.Symbol) for x in df.columns]
df

The Jupyter Notebook displays a DataFrame that contains the closing bid prices of the contracts and has the Symbol of each OptionsContract as the column indices.

To display the open interest of all of the contracts, run:

df = timespan_open_interest_history.copy()
df = df['openinterest'].unstack(level=0)
df.columns = [Symbol.GetAlias(SecurityIdentifier.Parse(x), equity.Symbol) for x in df.columns]
df

The Jupyter Notebook displays a DataFrame that contains the open interest of the contracts and has the Symbol of each OptionsContract as the column indices.

If you unstack the DataFrame that is returned from the GetAllData method instead of the History method, the DataFrame contains a NaN column that represents the underlying Equity.

Plot Data

Jupyter Notebooks don't currently support libraries to plot historical data, but we are working on adding the functionality. Until we add the functionality, use Python to plot historical Equity Options data.

You need to get some historical Equity Options data to plot it. You can use many of the supported plotting libraries to visualize data in various formats. For example, you can plot candlestick and line charts.

Candlestick Chart

Follow these steps to plot candlestick charts:

  1. Call the History method with an OptionContract Symbol and a timedelta.
  2. history = qb.History(contract_symbol, timedelta(1))
  3. Drop the first four index levels of the DataFrame that returns.
  4. history.index = history.index.droplevel([0,1,2,3])
  5. Import the plotly library.
  6. import plotly.graph_objects as go
  7. Call the Candlestick constructor with the timestamp and price series.
  8. candlestick = go.Candlestick(x=history.index,
                                 open=history['open'],
                                 high=history['high'],
                                 low=history['low'],
                                 close=history['close'])
  9. Call the Layout constructor with some titles.
  10. layout = go.Layout(title=go.layout.Title(text=f'{symbol.Value} OHLC'),
                       xaxis_title='Date',
                       yaxis_title='Price',
                       xaxis_rangeslider_visible=False)
  11. Call the Figure constructor with the Candlestick and Layout.
  12. fig = go.Figure(data=[candlestick], layout=layout)
  13. Call the show method.
  14. fig.show()

    The Jupyter Notebook displays a candlestick chart of the Option contract's price.

Candlestick shart of a contract's price

Line Chart

Follow these steps to plot line charts using built-in methods:

  1. Call the History method with the OpenInterest class, OptionContract Symbols, and a timedelta.
  2. history = qb.History(OpenInterest, selected_symbols, timedelta(days=30))
  3. Drop the first three index levels of DataFrame that returns.
  4. history.index = history.index.droplevel([0,1,2])
  5. Select the open interest property and then call the unstack method.
  6. open_interests = history['openinterest'].unstack(level=0)
  7. Rename the columns to the Symbol of each contract.
  8. open_interests.columns = [
        Symbol.GetAlias(SecurityIdentifier.Parse(x), equity.Symbol)
            for x in open_interests.columns]
  9. Call the plot method with a title.
  10. open_interests.plot(title="Open Interest")
  11. Call the show method.
  12. plt.show()

    The Jupyter Notebook displays a line chart of open interest data.

line chart of open interest

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: