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

Option Strategies

Short Box Spread

Introduction

A Short Box Spread is the inverse of a box spread, as well as the combination of a bear call spread and a bull put spread. It consists of buying an OTM call at strike A, selling an ITM put at strike A, buying an OTM put and strike B<A, and selling an ITM call at strike B, where all of the contracts have the same expiry date. This strategy serves as an delta-neutral arbitration from Option mispricing. Note that it only attains a true profit when the risk-free return is greater than the risk-free interest rate.

Implementation

Follow these steps to implement the short box spread strategy:

  1. In the initialize method, set the start date, set the end date, subscribe to the underlying Equity, and create an Option universe.
  2. Select Language:
    def initialize(self) -> None:
        self.set_start_date(2017, 4, 1)
        self.set_end_date(2017, 4, 30)
        self.set_cash(100000)
    
        self.universe_settings.asynchronous = True
        option = self.add_option("GOOG", Resolution.MINUTE)
        self._symbol = option.symbol
        option.set_filter(lambda universe: universe.include_weeklys().box_spread(30, 5))

    The box_spread filter narrows the universe down to just the four contracts you need to form a short box spread.

  3. In the on_data method, select the strike and expiry of the contracts in 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
    
        # Select an expiry date and ITM & OTM strike prices
        expiry = max([x.expiry for x in chain])
        contracts = [x for x in chain if x.expiry == expiry]
        lower_strike = min([x.strike for x in contracts])
        higher_strike = max([x.strike for x in contracts])
  5. In the on_data method, select the contracts and place the orders.
  6. Approach A: Call the OptionStrategies.short_box_spread method with the details of each leg and then pass the result to the buy method.

    Select Language:
    short_box_spread = OptionStrategies.short_box_spread(self._symbol, higher_strike, lower_strike, expiry)
    self.buy(short_box_spread, 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:
    # Select the call and put contracts
    itm_call = [x for x in chain if x.right == OptionRight.CALL and x.expiry == expiry and x.strike == lower_strike][0]
    otm_call = [x for x in chain if x.right == OptionRight.CALL and x.expiry == expiry and x.strike == higher_strike][0]
    itm_put = [x for x in chain if x.right == OptionRight.PUT and x.expiry == expiry and x.strike == higher_strike][0]
    otm_put = [x for x in chain if x.right == OptionRight.PUT and x.expiry == expiry and x.strike == lower_strike][0]
        
    legs = [
        Leg.create(itm_call.symbol, -1),
        Leg.create(itm_put.symbol, -1),
        Leg.create(otm_call.symbol, 1),
        Leg.create(otm_put.symbol, 1),
    ]
    self.combo_market_order(legs, 1)

Strategy Payoff

This is a fixed payoff, delta-neutral strategy. The payoff is

CITMT=(STK)+COTMT=(STK+)+PITMT=(K+ST)+POTMT=(KST)+PayoffT=(CITMT0CITMT+PITMT0PITMTCOTMT0+COTMTPOTMT0+POTMT)×mfee=(KK++CITMT0+PITMT0COTMT0POTMT0)×mfee
whereCITMT=ITM Call value at time TCOTMT=OTM Call value at time TPITMT=ITM Put value at time TPOTMT=OTM Put value at time TST=Underlying asset price at time TK+=Higher strike priceK=Lower strike pricePayoffT=Payout total at time TCITMT0=ITM Call price when the trade opened (debit paid)COTMT0=OTM Call price when the trade opened (credit received)PITMT0=ITM Put price when the trade opened (debit paid)POTMT0=OTM Put price when the trade opened (credit received)m=Contract multiplierT=Time of expiration

The following chart shows the payoff at expiration:

short box spread strategy payoff

The payoff is only dependent on the strike price and the initial asset prices.

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 algorithm:

AssetPrice ($)Strike ($)
ITM Call23.00810.00
ITM Put23.80857.50
OTM Call1.85857.50
OTM Put2.75810.00
Underlying Equity at expiration843.25-

Therefore, the payoff is

PayoffT=(KK++CITM0+PITM0COTM0POTM0)×mfee=(810.00857.50+23.00+23.801.852.75)×1001.00×4=534.00

So, the strategy loses $534.

The following algorithm implements a short box spread Option strategy:

Select Language:
class ProtectiveCollarOptionStrategy(QCAlgorithm):
    def initialize(self) -> None:
        self.SetStartDate(2017, 4, 1)
        self.SetEndDate(2017, 4, 30)
        self.SetCash(100000)

        self.UniverseSettings.Asynchronous = True
        self.equity_symbol = self.AddEquity("GOOG").Symbol

        option = self.AddOption("GOOG", Resolution.Minute)
        self.option_symbol = option.Symbol
        option.set_filter(lambda universe: universe.include_weeklys().box_spread(30, 5))

        self.invest_ever = False

    def on_data(self, slice: Slice) -> None:
        if self.invest_ever: return

        # Get the OptionChain
        chain = slice.option_chains.get(self.option_symbol, None)
        if not chain: return

        # Select an expiry date
        expiry = sorted(chain, key = lambda x: x.expiry)[-1].expiry

        # Select the strike prices of the contracts
        ordered_contracts = sorted(chain, key = lambda x: x.strike)
        higher_strike = ordered_contracts[-1].strike
        lower_strike = ordered_contracts[0].strike

        box_spread = OptionStrategies.short_box_spread(self.option_symbol, higher_strike, lower_strike, expiry)
        self.buy(box_spread, 1)

        self.invest_ever = True

    def on_end_of_day(self, symbol: Symbol) -> None:
        if symbol == self.equity_symbol:
            self.Log(f"{self.time}::{symbol}::{self.securities[symbol].price}")

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: