---
title: "US Equity Option Universe"
description: "US Equity Option Universe dataset from QuantConnect."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/quantconnect/us-equity-option-universe
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/quantconnect/us-equity-option-universe.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/14%20Datasets/02%20QuantConnect/22%20US%20Equity%20Option%20Universe
modified: 2026-10-30
index: https://www.quantconnect.com/llms.txt
---

# US Equity Option Universe

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Datasets > [QuantConnect](https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/quantconnect.md) > US Equity Option Universe

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

## Introduction

The US Equity Option Universe dataset by QuantConnect lists the available US Equity Options contracts and the current Implied Volatility and Greeks. The data covers 4,000 Symbols, starts in January 2012, and is delivered on a daily update frequency. To create this dataset, we use [our implementation](https://www.quantconnect.com/research/16977/greeks-and-iv-implementation/p1) of the forward tree pricing model, which accounts for the interest rate, dividend payments, and daily closing prices. The values in this dataset are the same values you can get from daily [indicators](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/greeks-and-implied-volatility/indicators.md) with mirror Options.

This dataset depends on the [US Equity Security Master](https://www.quantconnect.com/datasets/quantconnect-us-equity-security-master) dataset because the US Equity Security Master dataset contains information on splits, dividends, and symbol changes of the underlying security.

This dataset `does not` contain market data. For market data, see [US Equity Options by AlgoSeek](https://www.quantconnect.com/datasets/algoseek-us-equity-options).

For more information about the US Equity Option Universe dataset, including CLI commands and pricing, see the [dataset listing](https://www.quantconnect.com/datasets/quantconnect-us-equity-option-universe).

## About the Provider

QuantConnect was founded in 2012 to serve quants everywhere with the best possible algorithmic trading technology. Seeking to disrupt a notoriously closed-source industry, QuantConnect takes a radically open-source approach to algorithmic trading. Through the QuantConnect web platform, more than 50,000 quants are served every month.

## Getting Started

The following snippet demonstrates how to request data from the US Equity Options Universe dataset:

```python
option = self.add_option("GOOG")
self.option_symbol = option.symbol
option.set_filter(lambda universe: universe.delta(0.4, 0.6))
```

## Data Summary

The following table describes the dataset properties:

| Property | Value |
| --- | --- |
| Start Date | January 2012 |
| Asset Coverage | 4,000 Symbols |
| Data Density | Dense |
| Resolution | Daily |
| Timezone | New York |

## Requesting Data

To add US Equity Options Universe data to your algorithm, call the `add_option` method. Save a reference to the Equity Option `Symbol` so you can access the data later in your algorithm. To define which contracts should be in your universe, call the `set_filter` method of the Option object.

The `add_option` method provides a daily stream of Option chain data. To get the most recent daily chain, call the `option_chain` method with the underlying Equity Symbol. The `option_chain` method returns data on all the tradable contracts, not just the contracts that pass your universe filter.

```python
class USEquityOptionsDataAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2020, 6, 1)
        self.set_end_date(2021, 6, 1)
        self.set_cash(100000)
        self.universe_settings.asynchronous = True
        option = self.add_option("GOOG")
        self.option_symbol = option.symbol
        # Set our strike/expiry filter for this option chain
        option.set_filter(self._option_filter)
        # Get the entire Option chain for the current day.
        chain = self.option_chain(option.symbol.underlying, flatten=True).data_frame

    def _option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
        # Contracts can be filtered by greeks, implied volatility, open interest:
        return universe \
            .delta(0.5, 1.5) \
            .gamma(0.0001, 0.0006) \
            .vega(0.01, 1.5) \
            .theta(-2.0, -0.5) \
            .rho(0.5, 3.0) \
            .implied_volatility(1, 3) \
            .open_interest(100,500)
```

The Equity resolution must be less than or equal to the Equity Option resolution. For example, if you set the Equity resolution to minute, then you must set the Equity Option resolution to minute, hour, or daily.

For more information about creating US Equity Option Universes, see [Equity Options](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity-options.md).

## Accessing Data

For information about accessing US Equity Options Universe data, see [Equity Options](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity-options.md).

## Historical Data

You can get historical US Equity Options Universe data in an algorithm and the Research Environment.

### Historical Data In Algorithms

To get historical US Equity Options Universe data in an algorithm, call the `history` method with the canonical Equity Option `Symbol`. This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter. If there is no data in the period you request, the history result is empty.

```python
# DataFrame
history_df = self.history(self.option_symbol, timedelta(3), flatten=True)

# OptionUniverse objects
history = self.history[OptionUniverse](self.option_symbol, timedelta(3))
```

For more information about historical Equity Options Universe data in algorithms, see [Historical Data](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity-options.md#10-Historical-Data).

### Historical Data In Research

To get historical US Equity Options Universe data in the Research Environment, call the `history` method with the canonical Option `Symbol`. This method returns data on all of the tradable contracts, not just the contracts that pass your universe filter.

```python
qb = QuantBook()
option = qb.add_option("GOOG")
history = qb.history(option.symbol, datetime(2020, 6, 1), datetime(2020, 6, 5), flatten=True)
```

For more information about historical Equity Options Universe data in the Research Environment, see [Universes](https://www.quantconnect.com/docs/v2/research-environment/datasets/equity-options/universes.md).

## Supported Assets

To view the supported assets in the US Equity Options Universe dataset, see the [Data Explorer](https://www.quantconnect.com/datasets/algoseek-us-equity-options/explorer).

## Example Applications

The US Equity Options Universe dataset enables you to accurately design Option strategies. Examples include the following strategies:

- Buying put Options to hedge against downward price movement in positive Equity positions
- Exploiting arbitrage opportunities that arise when the price of Option contracts deviate from their theoretical value

### Classic Algorithm Example

The following example algorithm subscribes to Google put options that fall within delta range between -1 and -0.95, open interest range between 10 and 1000, and expire within seven days. Within this Option chain, the algorithm holds the put Option contract that has the minimum delta (closest to -1) during market hour to hedge the underlying intra-day movement completely. It avoid volatility from sentiment and only earns from inter-day movement from longer-term factors. When the contract expires, the algorithm rolls over to the next contract that meets this criteria.

```python
from AlgorithmImports import *

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

        # Asynchronous can use computational resources efficiently
        self.universe_settings.asynchronous = True
        # Subscribe to the underlying for the underlying position
        # Set the data normalization mode to raw for strike price comparability
        self.equity = self.add_equity("GOOG", data_normalization_mode=DataNormalizationMode.RAW).symbol
        # Requesting option data and filter for the hedge candidates
        option = self.add_option(self.equity)
        option.set_filter(self.option_filter)
        self.option_symbol = option.symbol

        # Set scheduled event to buy a hedge option contract at market open to eliminate the intra-day movement
        self.schedule.on(
            self.date_rules.every_day(self.equity),
            self.time_rules.after_market_open(self.equity, 1),
            self.buy_hedge_contract
        )

        # Set a scheduled event to sell the hedge contract before market close, since we want to earn from inter-day movement
        # Leave 2 minutes contingency to fill
        self.schedule.on(
            self.date_rules.every_day(self.equity),
            self.time_rules.before_market_close(self.equity, 2),
            self.sell_hedge_contract
        )

        self.hedge = None

    def option_filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
        # Select the contracts with delta very close to -1 and high open interest
        # This can effectively hedge most of the price change of the underlying and ensure the liquidity
        # Make sure the contract is expiring close for its tradbility
        return universe.puts_only().expiration(2, 7).delta(-1, -0.95).open_interest(10, 1000)

    def buy_hedge_contract(self) -> None:
        chain = self.current_slice.option_chains.get(self.option_symbol)
        if chain:
            # Order the underlying if not hold, the order size should match the option contract
            # Order only if option chain data ready for hedging
            if not self.portfolio[self.equity].invested:
                self.market_order(self.equity, self.securities[self.option_symbol].symbol_properties.contract_multiplier)

            # Get the contract with delta closest to -1 (lowest possible delta)
            contract = sorted(chain, key=lambda x: x.greeks.delta)[0]
            self.hedge = contract.symbol
            # Buy 1 deep ITM put with delta close to -1 to eliminate the intraday movement
            self.market_order(self.hedge, 1)

    def sell_hedge_contract(self) -> None:
        # Check if any hedge contract position, if so, liquidate before market close to expose to underlying overnight movement
        if self.hedge:
            self.liquidate(self.hedge)
            self.hedge = None
```

### Framework Algorithm Example

The following example algorithm demonstrating a Gamma Scalping strategy through framework algorithm. It filters NVDA options with expiration between 30 to 90 days and open interest between 50 and 1000, due to liquidity concern and lower Gamma fluctuation. Assuming a significant upward trend is expecting, it orders a long straddle strategy from the strike price with Delta-neutral and the highest Gamma to earn the highest profit from upward underlying movement.

```python
from AlgorithmImports import *

class USEquityOptionsUniverseFrameworkAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)
        # Asynchronous can use computational resources efficiently
        self.universe_settings.asynchronous = True

        # Universe selection that select based on liquidity of the option contracts (by open interest)
        self.add_universe_selection(EquityOptionsUniverseSelectionModel())
        # Custom alpha model that use Delta and Gamma to signal insights
        self.add_alpha(OptionDeltaGammaAlphaModel())
        # To maintain long-short size equal, use a PCM that order a single contract
        self.set_portfolio_construction(SingleSharePortfolioConstructionModel())

class EquityOptionsUniverseSelectionModel(OptionUniverseSelectionModel):
    def __init__(self) -> None:
        # Daily update with the select_option_chain_symbols function
        super().__init__(timedelta(1), self.select_option_chain_symbols)

    def select_option_chain_symbols(self, dt: datetime) -> List[Symbol]:
        # Select only NVDA options as our focus, which is a highly traded volatile equity with great upward momentum
        return [Symbol.create("NVDA", SecurityType.OPTION, Market.USA)]

    def filter(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
        # To ensure the liquidity and tradability, make sure the option is not 0-DTE and have a fair open interest
        # A longer TTM will have lower Gamma thus more stable in the local delta-neutral position
        return universe.expiration(30, 90).open_interest(50, 1000)

class OptionDeltaGammaAlphaModel(AlphaModel):
    def __init__(self) -> None:
        # A day count variable to control the alpha model only trade once a day
        self._day = -1

    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
        insights = []

        if self._day != slice.time.day:
            # We open position for each option underlying as separate bet
            for _, chain in slice.option_chains.items():
                # For theta-neutral, select the same expiry for both call and put
                expiry = min(x.expiry for x in chain)
                contracts = [x for x in chain if x.expiry == expiry]

                # Calculate delta and gamma per strike price group for later filtering, ensure both call and put available for option strategy
                delta_gamma_symbols = []
                strikes = set(x.strike for x in contracts if len([y for y in contracts if y.strike == x.strike]) == 2)
                for strike in strikes:
                    # Get both call and put for their aggregated delta and gamma
                    call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == strike, contracts))
                    put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == strike, contracts))
                    delta_gamma_symbols.append((call.greeks.delta + put.greeks.delta, call.greeks.gamma + put.greeks.gamma, call.symbol, put.symbol))

                if len(delta_gamma_symbols) == 0:
                    continue

                # We want a delta-neutral position, so it is likely to be ATM (like a long straddle)
                # Less than 2d.p. difference is non-significant, which we can risk for better reward
                # Assuming the market direction is up in most scenario, we try to get the strike providing max overall Gamma
                # Make sure the aggregated gamma to be positive to bet on large uptrend
                # So it will earn more when the price really go up higher and higher, but locally immune for small noise
                filtered = [item for item in delta_gamma_symbols if round(item[0], 2) <= 0.01 and item[1] > 0]
                if len(filtered) == 0:
                    continue
                selected = sorted(filtered, key=lambda x: x[1], reverse=True)[0]

                # Provide trade signal and roll the day count to let the position stay for the whole day
                selected_call = selected[2]
                selected_put = selected[3]
                insights.extend([
                    Insight.price(selected_call, Expiry.END_OF_DAY, InsightDirection.UP),
                    Insight.price(selected_put, Expiry.END_OF_DAY, InsightDirection.UP)
                ])
                self._day = slice.time.day

        return insights

class SingleSharePortfolioConstructionModel(PortfolioConstructionModel):
    def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]:
        targets = []
        for insight in insights:
            if algorithm.securities[insight.symbol].is_tradable:
                # Use a whole number target to order the exact number of share for size-matching
                targets.append(PortfolioTarget(insight.symbol, insight.direction))
        return targets
```

## Data Point Attributes

The US Equity Options Universe dataset provides `OptionFilterUniverse`, `OptionUniverse`, and `OptionChain` objects.

### OptionFilterUniverse Attributes

`OptionFilterUniverse` objects have the following attributes:

*Members of `QuantConnect.Securities.OptionFilterUniverse` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Securities.OptionFilterUniverse&language=python*

### OptionUniverse Attributes

`OptionUniverse` objects have the following attributes:

*Members of `QuantConnect.Data.UniverseSelection.OptionUniverse` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.UniverseSelection.OptionUniverse&language=python*

### OptionChain Attributes

`OptionChain` objects have the following attributes:

*Members of `QuantConnect.Data.Market.OptionChain` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Data.Market.OptionChain&language=python*
