AuthorJing Wu2019-01-07


A Butterfly Spread strategy involves trading four option contracts with the same expiration but three different strike prices. There are four kinds of Butterfly Spread:

 Name  Strategy
 Long butterfly spread with calls  Buy 1 ITM call, sell 2 ATM call, buy 1 OTM call
 Long butterfly spread with puts  Buy 1 ITM put, sell 2 ATM put, buy 1 OTM put
 Short butterfly spread with calls  Sell 1 ITM call, buy 2 ATM call, sell 1 OTM call
 Short butterfly spread with puts  Buy 1 ITM put, sell 2 ATM put, buy 1 OTM put

A Butterfly Spread consists of three legs with a total of four options. In this tutorial, we use the Long Butterfly Spread as an example: long one ITM call, short two ATM calls and long one OTM call. All the calls have the same expiration. On the other hand, the middle strike is halfway between the lower and the higher strikes.

The aim of a Butterfly Spread strategy is for a trader to profit from marginal price changes in the underlying stock in either direction.

price = np.arange(800,1100,1)
# Suppose the undelying price at time 0 is 935
k_itm = 915 # the strike price of ITM call
k_otm = 955 # the strike price of OTM call
k_atm = 935 # the strike price of ATM call
premium_itm = 45 # the premium of ITM call
premium_otm = 15 # the premium of OTM call
premium_atm = 25 # the premium of ATM call
# payoff for the long ITM call position
payoff_itm_long = [max(-premium_itm, i-k_itm-premium_itm) for i in price]
# payoff for the long OTM call position
payoff_otm_long = [max(-premium_otm, i-k_otm-premium_otm) for i in price]
# payoff for the 2 short ATM call position
payoff_atm_short = [min(2*premium_atm, -2*(i-k_atm-premium_atm)) for i in price]
# payoff for Butterfly Spread Strategy
payoff = np.sum([payoff_itm_long,payoff_otm_long,payoff_atm_short], axis=0)
plt.plot(price, payoff_itm_long, label = 'Long ITM Call')
plt.plot(price, payoff_otm_long, label = 'Long OTM Call')
plt.plot(price, payoff_atm_short, label = 'Short 2 ATM Call')
plt.plot(price, payoff, label = 'Long Call Butterfly Spread')
plt.legend(fontsize = 20)
plt.xlabel('Stock Price at Expiry',fontsize = 15)
plt.ylabel('payoff',fontsize = 15)
plt.title('Long Call Butterfly Spread Payoff',fontsize = 20)

butterfly spread strategy payoff


Step 1: Initialize your algorithm including setting the start date and the end date, setting the cash and implement a coarse selection of option contract. SetFilter(-9, 9, 30, 60) helps us choose the contracts which expire in 30 to 60 days. For the strike parameter, the first parameter is the minimum strike rank relative to market price,  the second parameter is the maximum strike rank relative to market price. The rank of ATM contract is 0. Here we need to choose 2 numbers which are symmetrical with 0 to get strike prices for both ITM and OTM contracts.

def Initialize(self):
    self.SetStartDate(2017, 4, 1)
    self.SetEndDate(2017, 5, 30)
    equity = self.AddEquity("GOOG")
    option = self.AddOption("GOOG")
    self.symbol = option.Symbol
    option.SetFilter(-9, 9, 30, 60)
    # use the underlying equity GOOG as the benchmark

Step 2: Second we need to choose an expiration date for all the contracts, then filter out all the call options that expire on that date.

chain = slice.OptionChains.get(self.symbol)
# 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 call options from the contracts expires on that date
calls = [i for i in chain if i.Expiry == expiry and i.Right == OptionRight.Call]

Step 3: Sort the call options by their strike price in ascending order. Then choose the ATM option to be the one with the smallest absolute difference between the strike price and the underlying asset price. The OTM option is the last one in the call options list with the highest strike price. The corresponding ITM option is the first one in the list with the lowest strike price.

# sorted the contracts according to their strike prices
calls = sorted(calls, key=lambda x: x.Strike)
# choose ATM call
atm_call = sorted(calls, key=lambda x: abs(chain.Underlying.Price - x.Strike))[0].Symbol
# choose OTM call
otm_call = calls[-1].Symbol
# choose ITM call
itm_call = calls[0].Symbol

Step 4: Purchase 1 ITM call option and 1 OTM call option, then sell 2 ATM call option.

self.Sell(atm_call, 2)
self.Buy(itm_call, 1)
self.Buy(otm_call, 1)


From the following algorithm, at time 0, the GOOG share price is $832.8. We purchase 1 OTM call option with strike price $855, 1 ITM call option with strike price $810 and sell 2 ATM options with strike prices at 835. At the expiry 05/19/2017, the share price is $930 and so the long positions of the ITM option and the OTM option are exercised: we buy 100 GOOG shares at $810 and buy another 100 shares at $855. At the same time, the 2 short positions of the ATM option are also exercised: we sell 200  GOOG shares to the option holder at $835. After the expiration date, we don't hold any shares of the underlying. Since the stock price had a sharp increase during the life of options, we fail to profit from a Long Call Butterfly Spread.


Backtest using SetFilter

Backtest using OptionChainProvider

QuantConnect Logo

Try the world leading quantitative analysis platform today

Sign Up

Previous: Protective Collar Next: Long Strangle