Create an “Iron Butterfly” option strategy#

The “Iron Butterfly” is a popular investment strategy for a low-volatility environment.

The strategy on this page shorts volatility, capturing the volatility risk premium while hedging against large movements in the underlying asset.

INSERT NOTE ABOUT DATA ENTITLEMENTS

Environment#

import datetime as dtm
import numpy as np
import pandas as pd

import sigtech.framework as sig

env = sig.init()

Learn more: Set up the SigTech framework environment.

Define the investment universe#

Define the volatility product that will form the investment universe.

The strategy invests in the S&P 500 Index (SPX) and takes cash settlements rather than reinvesting the proceeds.

First, define some constants:

straddle_dir = 'SHORT'
strangle_dir = 'LONG'
maturity = '1M'
delta_strangle = 0.05
option_grp = sig.obj.get('SPX INDEX OTC OPTION GROUP')
START_DATE = dtm.datetime(2023, 1, 1)
END_DATE = dtm.datetime(2024, 1, 1)

Create the strategy#

The iron butterfly option strategy shorts volatility, capturing the volatility risk premium. It is composed of two strategies:

  • A short straddle at-the-money

  • A long strangle out-of-the-money

The goal is for the premium gains from the short straddle to outweigh the cost of the long strangle.

From the point of the strikes of the strangles, the strategy is market-neutral.

Define the Straddle:

atm_straddle = sig.Straddle(
    start_date=START_DATE,
    end_date=END_DATE,
    currency="USD",
    group_name=option_grp.name,
    strike_type='SPOT',
    maturity=maturity,
    rolling_frequencies=[maturity],
    target_quantity=-1 if straddle_dir == 'SHORT' else 1,
    ticker=f'{straddle_dir} SPX OTC STRADDLE ATM'
)

The Strangle will be + / - 5% out-of-the-money on each leg:

oom_strangle = sig.Strangle(
    start_date=START_DATE,
    end_date=END_DATE,
    currency="USD",
    group_name=option_grp.name,
    strike_type='Delta',
    call_strike=delta_strangle,
    put_strike=-1 * delta_strangle,
    maturity=maturity,
    rolling_frequencies=[maturity],
    target_quantity=1 if strangle_dir == 'LONG' else -1,
    ticker=f'{strangle_dir} SPX OTC STRANGLE {delta_strangle}',
)

Store both the straddle and the strangle strategy objects in a list:

strategies = [atm_straddle, oom_strangle]

Construct the portfolio#

To combine the strangle and straddle, use the sig.BasketStrategy class.

Create a custom roll table for the straddle and strangle options, to be used for rebalancing the basket strategy:

roll_ds = sig.schedules.SchedulePeriodic(
    start_date=START_DATE,
    end_date=END_DATE,
    holidays=option_grp.holidays,
    bdc=sig.infra.cal.BDC_FOLLOWING,
    frequency='1M',
).all_data_dates()[1:]

The basket strategy creates long-only strategies with fixed weights, rebalanced according to a set frequency. The custom roll table helps with portfolio rebalancing by synchronizing the basket rebalancing date with the option roll date:

basket_strategy = sig.BasketStrategy(
    start_date=START_DATE,
    end_date=END_DATE,
    currency='USD',
    constituent_names=[
        strategy.name for strategy in strategies
    ],
    # List of constituents weights expressed as floats.
    weights=[1/len(strategies)]*len(strategies),
    rebalance_dates=roll_ds,
    ticker=f'IRON BUTTERFLY'
)

Generate a performance report#

Create a report to show performance metrics, charts, and a calendar:

Learn more: Performance Analytics

strategies.append(basket_strategy)
sig.PerformanceReport(
    strategies,
    cash=sig.CashIndex.from_currency('USD')
).report()