book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

Option Strategies

Short Put Butterfly

Introduction

Short Put butterfly is the combination of a bull put spread and a bear put spread. In this strategy, all the puts have the same underlying stock, the same expiration date, and the strike price distance of ITM-ATM and OTM-ATM put pairs are the same. The short put butterfly strategy consists of selling an ITM put, selling an OTM put, and buying 2 ATM puts. This strategy profits from a drastic change in underlying price.

Implementation

Follow these steps to implement the short put butterfly strategy:

  1. In the initialize method, set the start date, end date, cash, and Option universe.
  2. Select Language:
    def initialize(self) -> None:
        self.set_start_date(2017, 2, 1)
        self.set_end_date(2017, 3, 5)
        self.set_cash(500000)
    
        self.universe_settings.asynchronous = True
        option = self.add_option("GOOG", Resolution.MINUTE)
        self._symbol = option.symbol
        option.set_filter(lambda universe: universe.include_weeklys().put_butterfly(30, 5))

    The put_butterfly filter narrows the universe down to just the three contracts you need to form a short put butterfly.

  3. In the on_data method, select the contracts of the strategy legs.
  4. Select Language:
    def on_data(self, slice: Slice) -> None:
        if self.portfolio.invested:
            return
    
        # Get the OptionChain
        chain = slice.option_chains.get(self._symbol, None)
        if not chain:
            return
    
        # Get the furthest expiry date of the contracts
        expiry = max([x.expiry for x in chain])
        
        # Select the call Option contracts with the furthest expiry
        puts = [i for i in chain if i.expiry == expiry and i.right == OptionRight.PUT]
        if len(puts) == 0:
            return
    
        # Select the ATM, ITM and OTM contracts from the remaining contracts
        atm_put = sorted(puts, key=lambda x: abs(x.strike - chain.underlying.price))[0]
        itm_put = sorted(puts, key=lambda x: x.strike)[-2]
        otm_put = [x for x in puts if x.strike == atm_put.strike * 2 - itm_put.strike][0]
  5. In the on_data method, place the orders.
  6. Approach A: Call the OptionStrategies.short_butterfly_put method with the details of each leg and then pass the result to the buy method.

    Select Language:
    option_strategy = OptionStrategies.short_butterfly_put(self._symbol, itm_put.strike, atm_put.strike, otm_put.strike, expiry)
    self.buy(option_strategy, 1)

    Approach B: Create a list of Leg objects and then call the combo_market_order, combo_limit_order, or combo_leg_limit_order method.

    Select Language:
    legs = [
        Leg.create(atm_put.symbol, 2),
        Leg.create(itm_put.symbol, -1),
        Leg.create(otm_put.symbol, -1)
    ]
    self.combo_market_order(legs, 1)

Strategy Payoff

The short put butterfly is a limited-reward-limited-risk strategy. The payoff is

POTMT=(KOTMST)+PITMT=(KITMST)+PATMT=(KATMST)+PT=(2×PATMTPOTMTPITMT2×PATM0+PITM0+POTM0)×mfee
wherePOTMT=OTM put value at time TPITMT=ITM put value at time TPATMT=ATM put value at time TST=Underlying asset price at time TKOTM=OTM put strike priceKITM=ITM put strike priceKATM=ATM put strike pricePT=Payout total at time TPITM0=ITM put value at position opening (credit received)POTM0=OTM put value at position opening (credit received)PATM0=ATM put value at position opening (debit paid)m=Contract multiplierT=Time of expiration

The following chart shows the payoff at expiration:

Strategy payoff decomposition and analysis of short put butterfly

The maximum profit is the net credit received, PITM0+POTM02×PATM0. It occurs when the underlying price is below the ITM strike or above the OTM strike at expiration.

The maximum loss is KATMKOTM2×PATM0+PITM0+POTM0. It occurs when the underlying price at expiration is at the same price as when you opened the trade.

If the Option is American Option, there is a risk of early assignment on the contracts you sell.

Example

The following table shows the price details of the assets in the short put butterfly algorithm:

AssetPrice ($)Strike ($)
ITM put37.80832.50
ATM put14.70800.00
OTM put5.70767.50
Underlying Equity at expiration829.08-

Therefore, the payoff is

POTMT=(KOTMST)+=(829.08832.50)+=0PITMT=(KITMST)+=(829.08767.50)+=61.58PATMT=(KATMST)+=(829.08800.00)+=29.08PT=(POTMTPITMT+2×PATMT2×PATM0+PITM0+POTM0)×mfee=(61.580+29.08×2+5.70+37.8014.70×2)×1001.00×4=1064

So, the strategy gains $1,064.

The following algorithm implements a short put butterfly Option strategy:

Select Language:
class PutButterflyStrategy(QCAlgorithm): 
    def initialize(self) -> None:
        self.set_start_date(2017, 2, 1)
        self.set_end_date(2017, 3, 6)
        self.set_cash(500000)

        option = self.add_option("GOOG", Resolution.MINUTE)
        self.symbol = option.symbol
        option.set_filter(self.universe_func)

    def universe_func(self, universe: OptionFilterUniverse) -> OptionFilterUniverse:
        return universe.include_weeklys().put_butterfly(30, 5)

    def on_data(self, data: Slice) -> None:
        # avoid extra orders
        if self.portfolio.invested: return

        # Get the OptionChain of the self.symbol
        chain = data.option_chains.get(self.symbol, None)
        if not chain: return

        # sorted the optionchain by expiration date and choose the furthest date
        expiry = sorted(chain, key = lambda x: x.expiry, reverse=True)[0].expiry
        
        # filter the put options from the contracts which expire on the furthest expiration date in the option chain.
        puts = [i for i in chain if i.expiry == expiry and i.right == OptionRight.PUT]
        if len(puts) == 0: return

        # sort the put options with the same expiration date according to their strike price.
        put_strikes = sorted([x.strike for x in puts])

        # get at-the-money strike
        atm_strike = sorted(puts, key=lambda x: abs(x.strike - chain.underlying.price))[0].strike

        # Get the distance between lowest strike price and ATM strike, and highest strike price and ATM strike. 
        # Get the lower value as the spread distance as equidistance is needed for both side.
        spread = min(abs(put_strikes[0] - atm_strike), abs(put_strikes[-1] - atm_strike))

        # select the strike prices for forming the option legs
        itm_strike = atm_strike + spread
        otm_strike = atm_strike - spread

        option_strategy = OptionStrategies.short_butterfly_put(self.symbol, itm_strike, atm_strike, otm_strike, expiry)
        # We open a position with 1 unit of the option strategy
        self.buy(option_strategy, 1)
        # self.sell(option_strategy, 1) if short put butterfly

Other Examples

For more examples, see the following algorithms:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: