Skip to content
All library documents

Selecting and Trading Equity Option Contracts by Expiration

Article Strategy library · Author: QuantConnect

Summary

This example shows how to add an equity option chain, filter contracts by expiration, inspect the available contracts, and submit a trade. It uses daily AAPL data, restricts the chain to calls expiring within 60 days, then selects the contract with the nearest expiration when the portfolio has no open investment. The example sets the underlying equity as its benchmark.

The code also logs order events and checks for an option expiration event, with an assertion tied to an expected UTC time. It is an instructional framework example, not a tested trading strategy: it gives no rationale for buying the selected call, contract-selection criteria beyond nearest expiration, or performance evidence. Its narrow date range, single underlying, and one-contract order limit its generality; the expiration assertion also encodes a specific expected event for the example.

Key ideas

  • The option chain is filtered to calls with expirations within a specified window.
  • When not invested, the algorithm chooses the available call with the nearest expiration.
  • The selected contract is purchased with a market order.
  • Order events are logged, and an expected expiration event is checked against a specific UTC time.

Tags

Full text
# BasicTemplateOptionsDailyAlgorithm


# BasicTemplateOptionsDailyAlgorithm









This example demonstrates how to add options for a given underlying equity security. It also shows how you can prefilter contracts easily based on strikes and expirations, and how you can inspect the option chain to pick a specific option contract to trade.

## Source (Apache-2.0)

```python
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from AlgorithmImports import *

### <summary>
### This example demonstrates how to add options for a given underlying equity security.
### It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
### can inspect the option chain to pick a specific option contract to trade.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="options" />
### <meta name="tag" content="filter selection" />
class BasicTemplateOptionsDailyAlgorithm(QCAlgorithm):
    underlying_ticker = "AAPL"

    def initialize(self):
        self.set_start_date(2015, 12, 15)
        self.set_end_date(2016, 2, 1)
        self.set_cash(100000)
        self.option_expired = False

        equity = self.add_equity(self.underlying_ticker, Resolution.DAILY)
        option = self.add_option(self.underlying_ticker, Resolution.DAILY)
        self.option_symbol = option.symbol

        # set our strike/expiry filter for this option chain
        option.set_filter(lambda u: (u.calls_only().expiration(0, 60)))

        # use the underlying equity as the benchmark
        self.set_benchmark(equity.symbol)

    def on_data(self,slice):
        if self.portfolio.invested: return

        chain = slice.option_chains.get(self.option_symbol)
        if not chain:
            return

        # Grab us the contract nearest expiry
        contracts = sorted(chain, key = lambda x: x.expiry)

        # if found, trade it
        if len(contracts) == 0: return
        symbol = contracts[0].symbol
        self.market_order(symbol, 1)

    def on_order_event(self, order_event):
        self.log(str(order_event))

        # Check for our expected OTM option expiry
        if "OTM" in order_event.message:

            # Assert it is at midnight 1/16 (5AM UTC)
            if order_event.utc_time.month != 1 and order_event.utc_time.day != 16 and order_event.utc_time.hour != 5:
                raise AssertionError(f"Expiry event was not at the correct time, {order_event.utc_time}")

            self.option_expired = True

    def on_end_of_algorithm(self):
        # Assert we had our option expire and fill a liquidation order
        if not self.option_expired:
            raise AssertionError("Algorithm did not process the option expiration like expected")

```

Shown in full with attribution under the source's licence. Licence: Apache-2.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.