Option Strategies

Short Call Butterfly

Introduction

The short call butterfly strategy is the combination of a bull call spread and a bear call spread. In the call butterfly, all of the calls should have the same underlying Equity, the same expiration date, and the same strike price distance between the ITM-ATM and OTM-ATM call pairs. The short call butterfly consists of a short ITM call, a short OTM call, and 2 long ATM calls. This strategy profits from high volatility in the underlying Equity price.

Implementation

Follow these steps to implement the short call butterfly strategy:

  1. In the Initialize method, set the start date, end date, cash, and Option universe.
  2. private Symbol _symbol;
    
    public override void Initialize()
    {
        SetStartDate(2017, 2, 1);
        SetEndDate(2017, 3, 5);
        SetCash(500000);
        UniverseSettings.Asynchronous = true;
        var option = AddOption("GOOG", Resolution.Minute);
        _symbol = option.Symbol;
        option.SetFilter(universe => universe.IncludeWeeklys().Strikes(-15, 15).Expiration(0, 31));
    }
    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().strikes(-15, 15).expiration(0, 31))
  3. In the OnData method, select the expiration and strikes of the contracts in the strategy legs.
  4. public override void OnData(Slice slice)
    {
        if (Portfolio.Invested) return;
    
        // Get the OptionChain
        var chain = slice.OptionChains.get(_symbol, null);
        if (chain == null || chain.Count() == 0) return;
    
        // Get the furthest expiry date of the contracts
        var expiry = chain.OrderByDescending(x => x.Expiry).First().Expiry;
        
        // Select the call Option contracts with the furthest expiry
        var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call);
        if (calls.Count() == 0) return;
    
        // Get the strike prices of the all the call Option contracts
        var callStrikes = calls.Select(x => x.Strike).OrderBy(x => x);
    
        // Get the ATM strike price
        var atmStrike = calls.OrderBy(x => Math.Abs(x.Strike - chain.Underlying.Price)).First().Strike;
    
        // Get the strike prices for the contracts not ATM
        var spread = Math.Min(Math.Abs(callStrikes.First() - atmStrike), Math.Abs(callStrikes.Last() - atmStrike));
        var itmStrike = atmStrike - spread;
        var otmStrike = atmStrike + spread;
    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 = sorted(chain, key = lambda x: x.expiry, reverse=True)[0].expiry
        
        # Select the call Option contracts with the furthest expiry
        calls = [i for i in chain if i.expiry == expiry and i.right == OptionRight.CALL]
        if len(calls) == 0: return
    
        # Get the strike prices of the all the call Option contracts
        call_strikes = sorted([x.strike for x in calls])
    
        # Get the ATM strike price
        atm_strike = sorted(calls, key=lambda x: abs(x.strike - chain.underlying.price))[0].strike
    
        # Get the strike prices for the contracts not ATM
        spread = min(abs(call_strikes[0] - atm_strike), abs(call_strikes[-1] - atm_strike))
        itm_strike = atm_strike - spread
        otm_strike = atm_strike + spread
  5. In the OnData method, call the OptionStrategies.ShortButterflyCall method and then submit the order.
  6. var optionStrategy = OptionStrategies.ShortButterflyCall(_symbol, otmStrike, atmStrike, itmStrike, expiry);
    Buy(optionStrategy, 1);
    option_strategy = OptionStrategies.short_butterfly_call(self.symbol, otm_strike, atm_strike, itm_strike, expiry)
    self.buy(option_strategy, 1)

    Option strategies synchronously execute by default. To asynchronously execute Option strategies, set the asynchronous argument to Falsefalse. You can also provide a tag and order properties to the Buy method.

    Buy(optionStrategy, quantity, asynchronous, tag, orderProperties);
    
    self.Buy(option_strategy, quantity, asynchronous, tag, order_properties)
    

Strategy Payoff

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

$$ \begin{array}{rcll} C^{OTM}_T & = & (S_T - K^{OTM})^{+}\\ C^{ITM}_T & = & (S_T - K^{ITM})^{+}\\ C^{ATM}_T & = & (S_T - K^{ATM})^{+}\\ P_T & = & (2\times C^{ATM}_T - C^{OTM}_T - C^{ITM}_T - 2\times C^{ATM}_0 + C^{ITM}_0 + C^{OTM}_0)\times m - fee \end{array} $$ $$ \begin{array}{rcll} \textrm{where} & C^{OTM}_T & = & \textrm{OTM call value at time T}\\ & C^{ITM}_T & = & \textrm{ITM call value at time T}\\ & C^{ATM}_T & = & \textrm{ATM call value at time T}\\ & S_T & = & \textrm{Underlying asset price at time T}\\ & K^{OTM} & = & \textrm{OTM call strike price}\\ & K^{ITM} & = & \textrm{ITM call strike price}\\ & K^{ATM} & = & \textrm{ATM call strike price}\\ & P_T & = & \textrm{Payout total at time T}\\ & C^{ITM}_0 & = & \textrm{ITM call value at position opening (credit received)}\\ & C^{OTM}_0 & = & \textrm{OTM call value at position opening (credit received)}\\ & C^{ATM}_0 & = & \textrm{ATM call value at position opening (debit paid)}\\ & m & = & \textrm{Contract multiplier}\\ & T & = & \textrm{Time of expiration} \end{array} $$

The following chart shows the payoff at expiration:

Strategy payoff decomposition and analysis of short call butterfly

The maximum profit is the net credit received: $C^{ITM}_0 + C^{OTM}_0 - 2\times C^{ATM}_0$. It occurs when the underlying price is less than ITM strike or greater than OTM strike at expiration.

The maximum loss is $K^{ATM} - K^{ITM} + C^{ITM}_0 + C^{OTM}_0 - 2\times C^{ATM}_0$. It occurs when the underlying price is at the same level as when you opened the trade.

If the Option is an American Option, there is a risk of early assignment on the sold contracts.

Example

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

AssetPrice ($)Strike ($)
OTM call4.90767.50
ATM call15.00800.00
ITM call41.00832.50
Underlying Equity at expiration829.08-

Therefore, the payoff is

$$ \begin{array}{rcll} C^{OTM}_T & = & (S_T - K^{OTM})^{+}\\ & = & (767.50-829.08)^{+}\\ & = & 0\\ C^{ITM}_T & = & (S_T - K^{ITM})^{+}\\ & = & (832.50-829.08)^{+}\\ & = & 3.42\\ C^{ATM}_T & = & (S_T - K^{ATM})^{+}\\ & = & (800.00-829.08)^{+}\\ & = & 0\\ P_T & = & (-C^{OTM}_T - C^{ITM}_T + 2\times C^{ATM}_T - 2\times C^{ATM}_0 + C^{ITM}_0 + C^{OTM}_0)\times m - fee\\ & = & (-0-3.42+0\times2+4.90+41.00-15.00\times2)\times100-1.00\times4\\ & = & -1252 \end{array} $$

So, the strategy gains $1,244.

The following algorithm implements a short call butterfly Option strategy:


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: