Skip to content
All library documents

Selecting Option Contracts for a Call Butterfly Strategy

Article Strategy library · Author: QuantConnect

Summary

This example demonstrates constructing a call butterfly on an equity option chain. It subscribes to an underlying and its options, then filters the chain to standard contracts within a range of strikes and expirations. On a data update, it skips trading if the portfolio already holds a position or the option market is closed, retrieves available calls, groups them by expiry, and selects contracts from the earliest expiry.

The selected strikes are passed to a call butterfly strategy and submitted as a single order. The example illustrates contract filtering and basic order execution, but it does not explain how strike spacing should be chosen, why the earliest expiry is suitable, or how the position’s risk should be sized. Its date range covers only one day, and the document supplies no backtest results, exit logic, or discussion of fees and liquidity. It is therefore an execution template rather than evidence that the spread has an attractive expected return.

Key ideas

  • The example filters an equity option chain by strike range and expiration.
  • It groups call contracts by expiry and chooses strikes from the earliest available expiry.
  • The chosen contracts form a call butterfly submitted as one strategy order.
  • The example does not specify exit rules, risk sizing, or strike-selection rationale.
  • No performance or transaction-cost evidence is provided.

Tags

Full text
# BasicTemplateOptionEquityStrategyAlgorithm


# BasicTemplateOptionEquityStrategyAlgorithm









This example demonstrates how to execute a Call Butterfly option equity strategy It adds options for a given underlying equity security, and shows how you can prefilter contracts easily based on strikes and expirations

## 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 execute a Call Butterfly option equity strategy
### It adds options for a given underlying equity security, and shows how you can prefilter contracts easily based on strikes and expirations
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="options" />
### <meta name="tag" content="filter selection" />
### <meta name="tag" content="trading and orders" />
class BasicTemplateOptionEquityStrategyAlgorithm(QCAlgorithm):
    underlying_ticker = "GOOG"

    def initialize(self) -> None:
        self.set_start_date(2015, 12, 24)
        self.set_end_date(2015, 12, 24)

        equity = self.add_equity(self.underlying_ticker)
        option = self.add_option(self.underlying_ticker)
        self._option_symbol = option.symbol

        # set our strike/expiry filter for this option chain
        option.set_filter(lambda u: (u.standards_only().strikes(-2, +2)
                                     # Expiration method accepts TimeSpan objects or integer for days.
                                     # The following statements yield the same filtering criteria
                                     .expiration(0, 180)))

    def on_data(self, slice: Slice) -> None:
        if self.portfolio.invested or not self.is_market_open(self._option_symbol):
            return

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

        grouped_by_expiry = dict()
        for contract in [contract for contract in chain if contract.right == OptionRight.CALL]:
            grouped_by_expiry.setdefault(int(contract.expiry.timestamp()), []).append(contract)

        first_expiry = list(sorted(grouped_by_expiry))[0]
        call_contracts = sorted(grouped_by_expiry[first_expiry], key = lambda x: x.strike)
        
        expiry = call_contracts[0].expiry
        lower_strike = call_contracts[0].strike
        middle_strike = call_contracts[1].strike
        higher_strike = call_contracts[2].strike

        option_strategy = OptionStrategies.call_butterfly(self._option_symbol, higher_strike, middle_strike, lower_strike, expiry)
                    
        self.order(option_strategy, 10)

    def on_order_event(self, order_event: OrderEvent) -> None:
        self.log(str(order_event))

```

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.