---
title: "Individual Contracts"
description: "Request Index 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/index-options/requesting-data/individual-contracts
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index-options/requesting-data/individual-contracts.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/03%20Securities/99%20Asset%20Classes/09%20Index%20Options/01%20Requesting%20Data/02%20Individual%20Contracts
modified: 2026-10-29
index: https://www.quantconnect.com/llms.txt
---

# Individual Contracts

[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) > [Index Options](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index-options.md) > [Requesting Data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index-options/requesting-data.md) > Individual Contracts

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

## Introduction

The `add_option_contract` method enables you to add an individual Option contract to your algorithm. To check which contracts are currently available to add to your algorithm, use the `option_chain` method. If you want to subscribe to a set of contracts instead of individual contracts one-by-one, see [Universes](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index-options/requesting-data/universes.md).

## Create Subscriptions

Before you can subscribe to an Index Option contract, you must configure the underlying Index and get the contract `symbol`.

```python
class BasicIndexOptionAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self._underlying = self.add_index("SPX").symbol
        self._contract_symbol = None

    def on_data(self, data):
        if self._contract_symbol:
            return
        chain = self.option_chain(self._underlying, flatten=True).data_frame
        expiry = chain.expiry.min()
        self._contract_symbol = chain[
            (chain.expiry == expiry) &
            (chain.right == OptionRight.CALL) &
            (chain.delta < 0.7) &
            (chain.delta > 0.3)
        ].sort_values('openinterest').index[-1]
        self.add_option_contract(self._contract_symbol)
```

### Configure the Underlying Index

In most cases, you should [subscribe to the underlying Index](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index/requesting-data.md#02-Create-Subscriptions) before you subscribe to an Index Option contract.

```python
self._underlying = self.add_index("SPX").symbol
```

### Get Contract Symbols

To subscribe to an Option contract, you need the contract `Symbol`. The preferred method to getting Option contract `Symbol` objects is to use the `option_chain` method. This method returns an `OptionChain` object, which represent an entire chain of Option contracts for a single underlying security. You can even format the chain data into a DataFrame where each row in the DataFrame represents a single contract. With the chain, sort and filter the data to find the specific contract(s) you want to trade.

```python
# Get the contracts available to trade (in DataFrame format).
#   Option A: Standard contracts.
chain = self.option_chain(
    Symbol.create_canonical_option(self._underlying, Market.USA, "?SPX"), flatten=True
).data_frame

#  Option B: Weekly contracts.
#chain = self.option_chain(
#    Symbol.create_canonical_option(self._underlying, "SPXW", Market.USA, "?SPXW"), flatten=True
#).data_frame

# Select a contract.
expiry = chain.expiry.min()
self._contract_symbol = chain[
    # Select call contracts with the closest expiry.
    (chain.expiry == expiry) &
    (chain.right == OptionRight.CALL) &
    # Select contracts with a 0.3-0.7 delta.
    (chain.delta < 0.7) &
    (chain.delta > 0.3)
    # Select the contract with the largest open interest.
].sort_values('openinterest').index[-1]
```

Alternatively, you can create a Index Option contract `Symbol` object directly parsing its OSI ticker using the `SymbolRepresentation.parse_option_ticker_osi` method.

```python
# Create the contract Symbol for the SPX Call 5650 3 Sept 2024.
self._contract_symbol = SymbolRepresentation.parse_option_ticker_osi('SPXW 240903C05650000', SecurityType.INDEX_OPTION, OptionStyle.EUROPEAN, Market.USA)
```

### Subscribe to Contracts

To create an Index Option contract subscription, pass the contract `Symbol` to the `add_index_option_contract` method. Save a reference to the contract `Symbol` so you can easily access the contract in the [OptionChain](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index-options/handling-data.md#04-Option-Chains) that LEAN passes to the `on_data` method. To override the default [pricing model](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/pricing.md) of the Option, [set a pricing model](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/pricing.md#03-Set-Models).

```python
option = self.add_index_option_contract(self._contract_symbol)
option.price_model = OptionPriceModels.black_scholes()
```

The `add_index_option_contract` method creates a subscription for a single Index Option contract and adds it to your **user-defined** universe. To create a dynamic universe of Index Option contracts, add an [Index Option universe](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/index-options.md).

### Warm Up Contract Prices

If you subscribe to an Index Option contract with `add_index_option_contract`, you'll need to wait until the next `Slice` to receive data and trade the contract. To trade the contract in the same time step you subscribe to the contract, set the current price of the contract in a [security initializer](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#07-Set-Security-Initializer).

```python
self.settings.seed_initial_prices = True
```

### Supported Assets

To view the supported assets in the US Index Options dataset, see [Supported Assets](https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/algoseek/us-index-options.md#09-Supported-Assets).

## Resolutions

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

| Resolution | TradeBar | QuoteBar | Trade Tick | Quote Tick |
| --- | --- | --- | --- | --- |
| `TICK` | Not supported | Not supported | Not supported | Not supported |
| `SECOND` | Supported in live trading only⚠︎ | Supported in live trading only⚠︎ | Not supported | Not supported |
| `MINUTE` | Supported✓ | Supported✓ | Not supported | Not supported |
| `HOUR` | Supported✓ | Supported✓ | Not supported | Not supported |
| `DAILY` | Supported✓ | Supported✓ | Not supported | Not supported |

⚠︎ Supported in live trading only.

The default resolution for Index Option subscriptions is `Resolution.MINUTE`. To change the resolution, pass a `resolution` argument to the `add_index_option_contract` method.

```python
self.add_index_option_contract(self._contract_symbol, Resolution.HOUR)
```

Minute is the densest resolution of historical Options data, but the live stream provides second resolution. To trade on the denser data in live mode and still backtest the same algorithm, set the resolution from `live_mode`:

```python
resolution = Resolution.SECOND if self.live_mode else Resolution.MINUTE
self.add_index_option_contract(self._contract_symbol, resolution)
```

Second resolution data isn't available in [history requests](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/history-requests.md) or [warm-up periods](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/warm-up-periods.md), so request Minute or a coarser resolution for those.

To create custom resolution periods, see [Consolidating Data](https://www.quantconnect.com/docs/v2/writing-algorithms/consolidating-data/getting-started.md).

## Supported Markets

The only market available for Index Options is `Market.USA`. You don't need to pass a `market` argument to the `add_index_option_contract` method because the contract `Symbol` already contains the market.

## Fill Forward

Fill forward means if there is no data point for the current [slice](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md), LEAN uses the previous data point. Fill forward is the default data setting. If you disable fill forward, you may get [stale fills](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/trade-fills/key-concepts.md#06-Stale-Fills) or you may see trade volume as zero.

To disable fill forward for a security, set the `fill_forward` argument to false when you create the security subscription.

```python
self.add_index_option_contract(self._contract_symbol, fill_forward=False)
```

## Margin and Leverage

LEAN models buying power and margin calls to ensure your algorithm stays within the margin requirements. Options are already leveraged products, so you can't change their leverage.

## Data Normalization

The data normalization mode doesn't affect the data that LEAN passes to `on_data` or the data from [history request](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/history-requests.md). If you change the data normalization mode, it won't change the outcome.

## Remove Subscriptions

To remove a contract subscription that you created with `add_index_option_contract`, call the `remove_option_contract` method. This method is an alias for `remove_security`.

```python
self.remove_option_contract(self._contract_symbol)
```

The `remove_option_contract` method cancels your open orders for the contract and liquidates your holdings.

## Properties

The `add_index_option_contract` method returns an `Option` object, which have the following properties:

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

## Helper Methods

The `Option` object provides methods you can use for basic calculations. These methods require the underlying price. To get the `Option` object and the `Security` object for its underlying in any function, use the Option `symbol` to access the value in the `securities` object.

```python
option = self.securities[self._contract_symbol]
underlying = self.securities[self._contract_symbol.underlying]
underlying_price = underlying.price
```

To get the Option [payoff](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/glossary.md#23-payoff), call the `get_pay_off` method.

```python
pay_off = option.get_pay_off(underlying_price)
```

To get the Option [intrinsic value](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/glossary.md#17-intrinsic-value), call the `get_intrinsic_value` method.

```python
intrinsic_value = option.get_intrinsic_value(underlying_price)
```

To get the Option [out-of-the-money amount](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/glossary.md#22-out-of-the-money-amount), call the `out_of_the_money_amount` method.

```python
otm_amount = option.out_of_the_money_amount(underlying_price)
```

To check whether the Option can be automatic exercised, call the `is_auto_exercised` method.

```python
is_auto_exercised = option.is_auto_exercised(underlying_price)
```

## Exceptions and Edge Cases

The following sections explain exceptions and edge cases with subscribing to individual Option contracts.

### Manually Creating Option Symbol Objects

To subscribe to an Option contract, you need the contract `Symbol`. To get Index Option contract `Symbol` objects, call the `create_option` or `option_chain` methods. If you use the `create_option` method, you need to know the specific contract details.

```python
# Standard contracts
self._contract_symbol = Symbol.create_option(self._underlying, Market.USA,
    OptionStyle.EUROPEAN, OptionRight.CALL, 3650, datetime(2022, 6, 17))

# Weekly contracts
self._weekly_contract_symbol = Symbol.create_option(self._underlying, "SPXW", Market.USA,
    OptionStyle.EUROPEAN, OptionRight.CALL, 3650, datetime(2022, 6, 17))
```

### Default Underlying Subscription Settings

If you subscribe to an Index Option contract but don't have a subscription to the underlying Index, LEAN automatically subscribes to the underlying Index and sets its [fill forward](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/index/requesting-data.md#05-Fill-Forward) property to match that of the Index Option contract. In this case, you still need the Index `symbol` to subscribe to Index Option contracts. If you don't have access to it, create it.

```python
self._underlying = Symbol.create("SPX", SecurityType.INDEX, Market.USA)
```

### Overriding the Initial Implied Volatility Guess

To override the [initial guess of implied volatility](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/pricing.md#96-What-Is-Implied-Volatility3F), set and warm up the underlying [volatility model](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/volatility/key-concepts.md).

## Examples

The following examples demonstrate common practices for requesting individual index option contract data.

### Example 1: 5-Minute Option Chain

The following example shows how to update the Option chain every five minutes. The custom `OptionChainManager` class implements the selection logic and manages the contract subscriptions.

```python
class OptionChainFullExample(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 10, 31)
        self.set_cash(500000)
        self.universe_settings.asynchronous = True
        self.universe_settings.minimum_time_in_universe = timedelta(minutes=0)

        # Seed the last price to ensure filtering using the underlying price is available immediately.
        self.settings.seed_initial_prices = True

        # Request the index underlying data for filtering.
        spx = self.add_index("SPX").symbol
        # Create the 5-minute option chain manager on SPXW weekly index option.
        self._chain_manager = {
            Symbol.create_canonical_option(spx, "SPXW", Market.USA, "?SPXW"): OptionChainManager(-10, 10, 0, 1)
        }
        # Populate the updated option chain immediately to trade with.
        self._populate_option_chain()

        # Set schedule event to populate the option chain at market open, since the option contracts are updating daily.
        self.schedule.on(
            self.date_rules.every_day(spx), self.time_rules.after_market_open(spx, 1), self._populate_option_chain
        )
        # Set a scheduled event to filter the closed ATM calls every 5 minutes.
        self.schedule.on(self.date_rules.every_day(spx), self.time_rules.every(timedelta(minutes=5)), self._filter)

    def _populate_option_chain(self) -> None:
        # The contract list is updated daily, so we can get it and apply
        # the expiration filter as soon as the market opens.
        for symbol, manager in self._chain_manager.items():
            manager.set_chain(self.option_chain(symbol), self.time)
        self._filter()

    def _filter(self) -> None:
        for symbol, manager in self._chain_manager.items():
            manager.select(self, symbol)

    def on_data(self, slice: Slice) -> None:
        for symbol, _ in self._chain_manager.items():
            # Only trade on updated data.
            chain = slice.option_chains.get(symbol)
            if not chain:
                continue

            # Filter the closest ATM call contract and trade.
            expiry = min([x.expiry for x in chain])
            contracts = [
                x for x in chain
                if x.expiry == expiry and x.right == OptionRight.CALL and self.securities[x.symbol].is_tradable
            ]
            if not contracts:
                continue
            atm_call = sorted(contracts, key=lambda x: abs(chain.underlying.price-x.strike))[0]
            if not self.portfolio[atm_call.symbol].invested:
                self.market_order(atm_call.symbol, 1)

class OptionChainManager:
    _chain = []
    _symbols = set([])

    def __init__(self, min_strike: int, max_strike: int, min_expiry: int, max_expiry: int) -> None:
        self._min_strike = min_strike
        self._max_strike = max_strike
        self._min_expiry = min_expiry
        self._max_expiry = max_expiry

    def set_chain(self, chain:OptionChain, time: datetime) -> None:
        # Filter the expiry daily only since contract list is updated daily.
        self._chain = [x for x in chain if self._min_expiry <= (x.expiry - time).days <= self._max_expiry]

    def select(self, algorithm: QCAlgorithm, symbol: Symbol) -> None:
        if not self._chain:
            return
        if symbol.is_canonical():
            symbol = symbol.underlying

        # Filter the contracts with strike range spread between the preset level.
        strikes = sorted(set(x.strike for x in self._chain))
        spot = algorithm.securities[symbol].price
        atm = sorted(strikes, key=lambda x: abs(spot-x))[0]
        index = strikes.index(atm)
        min_strike = strikes[max(0, index + self._min_strike)]
        max_strike = strikes[min(len(strikes) - 1, index + self._max_strike)]
        symbols = set(x.symbol for x in self._chain if min_strike <= x.strike <= max_strike)

        # Remove subscriptions if the contracts are not being ATM anymore.
        for symbol in self._symbols - symbols:
            if algorithm.remove_option_contract(symbol):
                self._symbols.remove(symbol)
        # Request data of the newly identified ATM contracts.
        for symbol in symbols - self._symbols:
            self._symbols.add(symbol)
            algorithm.add_option_contract(symbol)
```
