Option Strategies

Long Box Spread

Introduction

A long Box Spread is the combination of a bull call spread and a bear put spread. It consist of buying an ITM call at strike $A$, selling an OTM put at strike $A$, buying an ITM put at strike $B < A$, and selling an OTM 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 long box spread strategy:

  1. In the Initializeinitialize method, set the start date, set the end date, subscribe to the underlying Equity, and create an Option universe.
  2. private Symbol _symbol;
    
    public override void Initialize()
    {
        SetStartDate(2017, 4, 1);
        SetEndDate(2017, 4, 30);
        SetCash(100000);
    
        UniverseSettings.Asynchronous = true;
        var option = AddOption("GOOG", Resolution.Minute);
        _symbol = option.Symbol;
        option.SetFilter(universe => universe.IncludeWeeklys().BoxSpread(30, 5));
    }
    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 BoxSpreadbox_spread filter narrows the universe down to just the four contracts you need to form a box spread.

  3. In the OnDataon_data method, select the expiry and strikes of the contracts in the strategy legs.
  4. public override void OnData(Slice slice)
    {
        if (Portfolio.Invested) return;
    
        // Get the OptionChain
        if (!slice.OptionChains.TryGetValue(_symbol, out var chain))
        {
            return;
        }
    
        // Select an expiry date and ITM & OTM strike prices
        var expiry = chain.Max(x => x.Expiry);
        var contracts = chain.Where(x => x.Expiry == expiry).ToList();
        var higherStrike = contracts.Max(x => x.Strike);
        var lowerStrike = contracts.Min(x => x.Strike);
    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 OnDataon_data method, select the contracts and place the order.
  6. Approach A: Call the OptionStrategies.BoxSpreadOptionStrategies.box_spread method with the details of each leg and then pass the result to the Buybuy method.

    var boxSpread = OptionStrategies.BoxSpread(_symbol, higherStrike, lowerStrike, expiry);
    Buy(boxSpread, 1);
    box_spread = OptionStrategies.box_spread(self._symbol, higher_strike, lower_strike, expiry)
    self.buy(box_spread, 1)

    Approach B: Create a list of Leg objects and then call the Combo Market Ordercombo_market_order, Combo Limit Ordercombo_limit_order, or Combo Leg Limit Ordercombo_leg_limit_order method.

    // Select the call and put contracts
    var itmCall = contracts.Single(x => x.Strike == lowerStrike && x.Right == OptionRight.Call);
    var otmCall = contracts.Single(x => x.Strike == higherStrike && x.Right == OptionRight.Call);
    var itmPut = contracts.Single(x => x.Strike == higherStrike && x.Right == OptionRight.Put);
    var otmPut = contracts.Single(x => x.Strike == lowerStrike && x.Right == OptionRight.Put);
    
    var legs = new List<Leg>()
    {
        Leg.Create(itmCall.Symbol, 1),
        Leg.Create(itmPut.Symbol, 1),
        Leg.Create(otmCall.Symbol, -1),
        Leg.Create(otmPut.Symbol, -1),
    };
    ComboMarketOrder(legs, 1);
    # Select the call and put contracts
    itm_call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == lower_strike, contracts))
    otm_call = next(filter(lambda x: x.right == OptionRight.CALL and x.strike == higher_strike, contracts))
    itm_put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == higher_strike, contracts))
    otm_put = next(filter(lambda x: x.right == OptionRight.PUT and x.strike == lower_strike, contracts))           
    
    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

$$ \begin{array}{rcll} C_T^{ITM} & = & (S_T - K_{-})^{+}\\ C_T^{OTM} & = & (S_T - K_{+})^{+}\\ P_T^{ITM} & = & (K_{+} - S_T)^{+}\\ P_T^{OTM} & = & (K_{-} - S_T)^{+}\\ Payoff_T & = & (C_T^{ITM} - C_{T_0}^{ITM} + P_T^{ITM} - P_{T_0}^{ITM} - C_T^{OTM} + C_{T_0}^{OTM} - P_T^{OTM} + P_{T_0}^{OTM})\times m - fee\\ & = & (K_{+} - K_{-} + C_{T_0}^{OTM} + P_{T_0}^{OTM} - C_{T_0}^{ITM} - P_{T_0}^{ITM})\times m - fee \end{array} $$ $$ \begin{array}{rcll} \textrm{where} & C_T^{ITM} & = & \textrm{ITM Call value at time T}\\ & C_T^{OTM} & = & \textrm{OTM Call value at time T}\\ & P_T^{ITM} & = & \textrm{ITM Put value at time T}\\ & P_T^{OTM} & = & \textrm{OTM Put value at time T}\\ & S_T & = & \textrm{Underlying asset price at time T}\\ & K_{+} & = & \textrm{Higher strike price}\\ & K_{-} & = & \textrm{Lower strike price}\\ & Payoff_{T_1} & = & \textrm{Payout total at time T1}\\ & C_{T_0}^{ITM} & = & \textrm{ITM Call price when the trade opened (debit paid)}\\ & C_{T_0}^{OTM} & = & \textrm{OTM Call price when the trade opened (credit received)}\\ & P_{T_0}^{ITM} & = & \textrm{ITM Put price when the trade opened (debit paid)}\\ & P_{T_0}^{OTM} & = & \textrm{OTM Put price when the trade opened (credit received)}\\ & m & = & \textrm{Contract multiplier}\\ & T & = & \textrm{Time of expiration} \end{array} $$

The following chart shows the payoff at expiration:

long 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 Call27.30810.00
ITM Put28.00857.50
OTM Call1.05857.50
OTM Put1.50810.00
Underlying Equity at expiration843.25-

Therefore, the payoff is

$$ \begin{array}{rcll} Payoff_T & = & (K_{+} - K_{-} + C_0^{OTM} + P_0^{OTM} - C_0^{ITM} - P_0^{ITM})\times m - fee\\ & = & (857.50 - 810.00 + 1.05 + 1.50 - 27.30 - 28.00)\times100 - 1.00\times4\\ & = & -529.00\\ \end{array} $$

So, the strategy loses $529.

The following algorithm implements a long box spread 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: