---
title: "Universes"
description: "Request Equity Options data in your algorithm to receive a feed of contract prices in the OnData method."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/requesting-data/universes
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/requesting-data/universes.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/03%20Securities/99%20Asset%20Classes/02%20Equity%20Options/01%20Requesting%20Data/01%20Universes
modified: 2026-10-31
index: https://www.quantconnect.com/llms.txt
---

# Universes

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Securities > [Asset Classes](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes.md) > [Equity Options](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options.md) > [Requesting Data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/requesting-data.md) > Universes

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

## Introduction

The `add_option` method enables you to select a basket of Option contracts for an underlying Equity. To form your universe of contracts, you can filter them down by their strike price and expiry or you can choose to a subset of the contracts that form popular [Option strategies](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies.md). If you want to subscribe to individual contracts one-by-one instead of a set of contracts, see [Individual Contracts](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/requesting-data/individual-contracts.md).

## Create Universes

To add a universe of Equity Option contracts, in the `initialize` method, call the `add_option` method. This method returns an `Option` object, which has a `set_filter` method you can call to filter the set of tradable contract down to just the contracts you want.

```python
class BasicOptionAlgorithm(QCAlgorithm):

    def initialize(self):
        self.universe_settings.asynchronous = True
        option = self.add_option("SPY")
        option.set_filter(self._filter)
        self._symbol = option.symbol

    def _filter(self, universe):
        return universe.expiration(0, 7).delta(0.35, 0.75)

    def on_data(self, data):
        chain = data.option_chains.get(self._symbol)
        if chain:
            contract = sorted(chain, key=lambda x: (x.expiry, x.greeks.delta))[0]
```

For more information about the `add_option` method, see [Create Universes](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity-options.md#02-Create-Universes).

## Filter by Investment Strategy

[Options trading strategies](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies.md) consist of simultaneously buying or selling one or more Option contracts of the same underlying Equity with different features.

```python
# Example 1: Select a Straddle
option.set_filter(lambda option_filter_universe: option_filter_universe.straddle(30))

# Example 2: Select the contracts (including weeklys) that expire in the next 30 days that form an Iron Condor
option.set_filter(lambda option_filter_universe: option_filter_universe.strikes(-20, 20).expiration(0, 30).iron_condor(30, 5, 10))

# Example 3: Select the 0DTE contracts that form an Strangle
option.set_filter(lambda option_filter_universe: option_filter_universe.expiration(0, 0).strangle(30, 5, -10))
```

The following table describes the filter methods of the `OptionFilterUniverse` class that select contracts for Option strategies:

`naked_call(min_days_till_expiry: int, strike_from_atm: float)`

Selects a call contract to form [Naked Call](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/naked-call.md), [Covered Call](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/covered-call.md), or [Protective Call](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/protective-call.md) Option strategies.

`naked_put(min_days_till_expiry: int, strike_from_atm: float)`

Selects a put contract to form [Naked Put](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/naked-put.md), [Covered Put](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/covered-put.md), or [Protective Put](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/protective-put.md) Option strategies.

`call_spread(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)`

Selects two call contracts to form [Bull Call Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bull-call-spread.md) or [Bear Call Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bear-call-spread.md) Option strategies.

`put_spread(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)`

Selects two put contracts to form [Bull Put Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bull-put-spread.md) or [Bear Put Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bear-put-spread.md) Option strategies.

`call_calendar_spread(strike_from_atm: int, min_near_days_till_expiry: int, min_far_days_till_expiry: int)`

Selects two call contracts to form [Long Call Calendar Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-call-calendar-spread.md) or [Short Call Calendar Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-call-calendar-spread.md) Option strategies.

`put_calendar_spread(strike_from_atm: int, min_near_days_till_expiry: int, min_far_days_till_expiry: int)`

Selects two put contracts to form [Long Put Calendar Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-put-calendar-spread.md) or [Short Put Calendar Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-put-calendar-spread.md) Option strategies.

`strangle(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)`

Selects two contracts to form [Long Strangle](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-strangle.md) or [Short Strangle](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-strangle.md) Option strategies.

`straddle(min_days_till_expiry: int)`

Selects two contracts to form [Long Straddle](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-straddle.md) or [Short Straddle](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-straddle.md) Option strategies.

`protective_collar(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)`

Selects two contracts to form [Protective Collar](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/protective-collar.md) Option strategies.

`conversion(min_days_till_expiry: int, strike_from_atm: float)`

Selects two contracts to form [Conversion](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/conversion.md) or [Reverse Conversion](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/reverse-conversion.md) Option strategies.

`call_butterfly(min_days_till_expiry: int, strike_spread: float)`

Selects three contracts to form [Long Call Butterfly](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-call-butterfly.md) or [Short Call Butterfly](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-call-butterfly.md) Option strategies.

`put_butterfly(min_days_till_expiry: int, strike_spread: float)`

Selects three contracts to form [Long Put Butterfly](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-put-butterfly.md) or [Short Put Butterfly](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-put-butterfly.md) Option strategies.

`iron_butterfly(min_days_till_expiry: int, strike_spread: float)`

Selects four contracts to form [Long Iron Butterfly](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-iron-butterfly.md) or [Short Iron Butterfly](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-iron-butterfly.md) Option strategies.

`iron_condor(min_days_till_expiry: int, near_strike_spread: float, far_strike_spread: float)`

Selects four contracts to form [Long Iron Condor](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-iron-condor.md) or [Short Iron Condor](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-iron-condor.md) Option strategies.

`box_spread(min_days_till_expiry: int, strike_spread: float)`

Selects four contracts to form [Box Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-box-spread.md) or [Short Box Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-box-spread.md) Option strategies.

`jelly_roll(strike_from_atm: float, min_near_days_till_expiry: int, min_far_days_till_expiry: int)`

Selects four contracts to form [Jelly Roll](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-jelly-roll.md) or [Short Jelly Roll](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/short-jelly-roll.md) Option strategies.

`call_ladder(min_days_till_expiry: int, higher_strike_from_atm: float, middle_strike_from_atm: float, lower_strike_from_atm: float)`

Selects four contracts to form [Bear Call Ladder](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bear-call-ladder.md) or [Bull Call Ladder](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bull-call-ladder.md) Option strategies.

`put_ladder(min_days_till_expiry: int, higher_strike_from_atm: float, middle_strike_from_atm: float, lower_strike_from_atm: float)`

Selects four contracts to form [Bear Put Ladder](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bear-put-ladder.md) or [Bull Put Ladder](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bull-put-ladder.md) Option strategies.

The preceding methods return an `OptionFilterUniverse`, so you can chain the methods together.

## Filter by Implied Volatility and Greeks

Option price models compute the theoretical price of Option contracts, their implied volatility, and their Greek values. Theoretical prices can help you detect undervalued and overvalued contracts, implied volatility can provide you insight into the upcoming volatility of the underlying security, and Greek values can help you hedge your portfolio.

```python
# Example 1: Select the contracts with delta between 0.25 and 0.75
option.set_filter(lambda option_filter_universe: option_filter_universe.delta(0.25, 0.75))

# Example 2: Select the contracts (including weeklys) that expire in the next 90 days with implied volatility below 20%
option.set_filter(lambda option_filter_universe: option_filter_universe.iv(0, 20).expiration(0, 90))

# Example 3: Select the contracts (including weeklys) that expire in the next 30 days with implied volatility below 20% that forms an Iron Condor
option.set_filter(lambda option_filter_universe: option_filter_universe.iv(0, 20).expiration(0, 30).iron_condor(30, 5, 10))
```

The following table describes the filter methods of the `OptionFilterUniverse` class that select contract for a range of implied volatility, Greek values, and open interest:

`iv(min: float, max: float)`
`implied_volatility(min: float, max: float)`

Selects a contract with [implied volatility](https://www.quantconnect.com/learning/articles/introduction-to-options/historical-volatility-and-implied-volatility#implied-volatility) within the range you set.

`d(min: float, max: float)`
`delta(min: float, max: float)`

Selects a contract with [delta](https://www.quantconnect.com/learning/articles/introduction-to-options/the-greek-letters#delta) within the range you set.

`g(min: float, max: float)`
`gamma(min: float, max: float)`

Selects a contract with [gamma](https://www.quantconnect.com/learning/articles/introduction-to-options/the-greek-letters#gamma) within the range you set.

`r(min: float, max: float)`
`rho(min: float, max: float)`

Selects a contract with [rho](https://www.quantconnect.com/learning/articles/introduction-to-options/the-greek-letters#rho) within the range you set.

`v(min: float, max: float)`
`vega(min: float, max: float)`

Selects a contract with [vega](https://www.quantconnect.com/learning/articles/introduction-to-options/the-greek-letters#vega) within the range you set.

`t(min: float, max: float)`
`theta(min: float, max: float)`

Selects a contract with [theta](https://www.quantconnect.com/learning/articles/introduction-to-options/the-greek-letters#theta) within the range you set.

`oi(min: int, max: int)`
`open_interest(min: float, max: float)`

Selects a contract with open interest within the range you set.

The preceding methods return an `OptionFilterUniverse`, so you can chain the methods together.

To perform thorough filtering on the `OptionFilterUniverse`, define an isolated filter method.

```python
# Select the put contracts with the lowest strike price.
option.set_filter(self._contract_selector)

def _contract_selector(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
    return option_filter_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)
```

## Filter by Other Contract Properties

To set a contract filter, in the `initialize` method, call the `set_filter` method of the `Option` object.

```python
# Select contracts that have a strike price within 1 strike level above and below the underlying price
option.set_filter(min_strike=-1, max_strike=1)

# Select contracts that expire within 30 days
option.set_filter(min_expiry=timedelta(days=0), maxExpiry=timedelta(days=30))

# Select contracts that have a strike price within 1 strike level and expire within 30 days
option.set_filter(min_strike=-1, max_strike=1, min_expiry=timedelta(days=0), maxExpiry=timedelta(days=30))

# Select call contracts
option.set_filter(lambda option_filter_universe: option_filter_universe.calls_only())
```

The following table describes the available filter techniques:

`set_filter(minStrike: int, maxStrike: int)`

Selects the contracts that have a strike price within a minimum and maximum strike level relative to the underlying price. For example, say the underlying price is $302 and there are strikes at every $5. If you set `m_strike` to -1 and `max_strike` to 1, LEAN selects the contracts that have a strike of $300 or $305. This filter runs [asynchronously](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/settings.md#09-Asynchronous-Selection) by default.

`set_filter(minExpiry: timedelta, maxExpiry: timedelta)`

Selects the contracts that expire within the range you set. This filter runs [asynchronously](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/settings.md#09-Asynchronous-Selection) by default.

`set_filter(minStrike: int, maxStrike: int, minExpiry: timedelta, maxExpiry: timedelta)`

Selects the contracts that expire and have a strike within the range you set. This filter runs [asynchronously](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/settings.md#09-Asynchronous-Selection) by default.

`set_filter(universeFunc: Callable[[OptionFilterUniverse], OptionFilterUniverse])`

Selects the contracts that a function selects.

The same filter methods are available on [`OptionChain`](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/handling-data.md#04-Option-Chains) objects, so you can reuse them to narrow down a chain you receive during the algorithm.

The following table describes the filter methods of the `OptionFilterUniverse` class:

`strikes(min_strike: int, max_strike: int)`

Selects contracts that are within `m_strike` strikes below the underlying price and `max_strike` strikes above the underlying price.

`calls_only()`

Selects call contracts.

`puts_only()`

Selects put contracts.

`standards_only()`

Selects standard contracts.

`weeklys_only()`

Selects weekly contracts.

`front_month()`

Selects the front month contract.

`back_months()`

Selects the non-front month contracts.

`back_month()`

Selects the back month contracts.

`expiration(min_expiryDays: int, max_expiryDays: int)`

Selects contracts that expire within a range of dates relative to the current day.

`contracts(contracts: list[Symbol])`

Selects a list of contracts.

`contracts(contract_selector: Callable[[list[Symbol]], list[Symbol]])`

Selects contracts that a selector function selects.

The preceding methods return an `OptionFilterUniverse`, so you can chain the methods together.

```python
# Example 1: Select the front month call contracts
option.set_filter(lambda option_filter_universe: option_filter_universe.calls_only().front_month())

# Example 2: Select the contracts (including weeklys) that expire in the next 90 days
option.set_filter(lambda option_filter_universe: option_filter_universe.strikes(-20, 20).expiration(0, 90))
```

Some of the preceding filter methods only set an internal enumeration in the `OptionFilterUniverse` that it uses later on in the filter process. This subset of filter methods don't immediately reduce the number of contract `Symbol` objects in the `OptionFilterUniverse`.

## Default Filter

By default, LEAN subscribes to the Option contracts that have the following characteristics:

- Standard and weeklys
- Within 1 strike price of the underlying asset price
- Expire within 35 days

To adjust the universe of contracts, set a filter. The filter usually runs at the first bar of every day. When the filter selects a contract that isn't currently in your universe, LEAN adds the new contract data to the next `Slice` that it passes to the `on_data` method.

## Historical Data

To get historical chains for an Equity Option, see [Historical Data](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/equity-options.md#10-Historical-Data).

## Examples

### Example 1: Selecting for 0DTE Contracts

**0DTE Options** are Option contracts that expire on the same day you trade them. To create an universe with 0DTE Options, call the `set_filter` method with expiration set. In order to trade with the contracts with most liquidity, limit the strike range from 10 strikes above and below the current price level.

```python
class EquityOptionAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        option = self.add_option("SPY")
        # Filter for 0-DTE contracts within +/-10 strike range.
        # They have the highest volatility but low premium, providing sufficient liquidity and higher profit margin.
        option.set_filter(lambda u: u.expiration(0, 0).strikes(-10, 10))
```

### Example 2: Straddle

You can also create an universe that return the option contracts that form an [option strategy](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies.md) . In this example, we demonstrate filtering for a [long straddle](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/long-straddle.md) strategy that expires 30 days later.

```python
class EquityOptionAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        option = self.add_option("SPY")
        self._symbol = option.symbol
        # Using straddle() method, it will only return the best-matched ATM call and put contracts expiring after 30 days.
        # It provides better accuracy in filtering, and subscribe only to the needed contracts to save computation resources.
        option.set_filter(lambda u: u.straddle(30))

    def on_data(self, slice: Slice) -> None:
        # Only wants the option chain of the selected symbol.
        chain = slice.option_chains.get(self._symbol)
        if not self.portfolio.invested and chain:
            # There should only be 1 expiry and 1 strike from the 2 contracts returned, getting from either contract is fine.
            expiry = list(chain)[0].expiry
            strike = list(chain)[0].strike

            # Forms a long straddle option strategy using abstraction method ensure accuracy.
            long_straddle = OptionStrategies.straddle(self._symbol, strike, expiry)
            self.buy(long_straddle, 1)
```

### Example 3: Custom Selector

Using a custom selection function, you can filter the option universe to obtain the contracts that you need without subscribing the redundants. This can ensure the accuracy of the filter, as well as avoiding unnecessary subscriptions that drag the algorithm computational performance. In this example, we try to obtain a put contract that expires 30 days later that is $5 below the current underlying price and a call contract that expires 60 days later that is $10 above the current underlying price.

```python
class EquityOptionAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        # Seed the price with last known price to ensure the underlying price data is available on initial option contract filtering.
        self.settings.seed_initial_prices = True
        self.underlying = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.RAW)
        # Subscribe to underlying data for ATM calculation using the update underlying price.
        # Set data normalization mode to raw is required to ensure strike price and underlying price is comparable.
        option = self.add_option(self.underlying.symbol)
        option.set_filter(lambda u: u.contracts(self.selection))

    def selection(self, contracts: List[Symbol]) -> List[Symbol]:
        selected = []

        # Select the best-match put contracts that expires 30 days later that is $5 below the current underlying price.
        # We should first filter the hard requirement, then sort the reminders for faster computation.
        puts = [x for x in contracts
            if x.id.option_right == OptionRight.PUT and \
            x.id.date >= self.time + timedelta(30) and \
            x.id.strike_price <= self.underlying.price - 5
        ]
        if len(puts) > 0:
            expiry = min(x.id.date for x in puts)
            put = sorted([x for x in puts if x.id.date == expiry],
                key=lambda x: x.id.strike_price,
                reverse=True)[0]
            selected.append(put)

        # Select the best-match call contract that expires 60 days later that is $10 above the current underlying price.
        calls = [x for x in contracts
            if x.id.option_right == OptionRight.CALL and \
            x.id.date >= self.time + timedelta(60) and \
            x.id.strike_price >= self.underlying.price + 10
        ]
        if len(calls) > 0:
            expiry = min(x.id.date for x in calls)
            call = sorted([x for x in calls if x.id.date == expiry],
                key=lambda x: x.id.strike_price)[0]
            selected.append(call)

        return selected
```
