Option Strategies

Long Strangle

Introduction

Long Strangle is an options trading strategy involving simultaneous buying of an OTM put and an OTM call, where both options have the same underlying asset and expiration date. This strategy aims to profit from volatile movements in the underlying stock, either positive or negative.

Compare to a long straddle, the net debit is lower since OTM options are cheaper, but this also widen the losing range and the strike spread is widen.

The payoff is as follows:

$Payoff_{call}=(Price_{underlying}-Strike)^{+}$

$Payoff_{put}=(Strike-Price_{underlying})^{+}$

$Profit/Loss=(Payoff_{call}+Payoff_{put}-debit\ paid_{call}-debit\ paid_{put})\times multiplier-commissions$

long strangle strategy payoff

The maximum profit is unlimited, if the underlying price is risen to infinity at expiration.

Maximum loss is the net debit paid when opening the trade, where is underlying price is unchanged and both options become worthless.

Implementation

Follow these steps to implement the long strangle 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, 4, 1);
        SetEndDate(2017, 4, 30);
        SetCash(100000);
    
        var option = AddOption("GOOG", Resolution.Minute);
        _symbol = option.Symbol;
        option.SetFilter(universe => universe.Strikes(-5, 5)
                                                .Expiration(TimeSpan.FromDays(0), TimeSpan.FromDays(30)));
    }
    def Initialize(self) -> None:
        self.SetStartDate(2017, 4, 1)
        self.SetEndDate(2017, 4, 30)
        self.SetCash(100000)
        
        option = self.AddOption("GOOG", Resolution.Minute)
        self.symbol = option.Symbol
    
        # set our strike/expiry filter for this option chain
        option.SetFilter(-5, 5, timedelta(0), timedelta(30))
  3. In the OnData method, select the Option contracts.
  4. public override void OnData(Slice slice)
    {
        if (Portfolio.Invested) return;
    
        // Get the OptionChain of the symbol
        var chain = slice.OptionChains.get(_symbol, null);
        if (chain == null || chain.Count() == 0) return;
    
        // sort the optionchain by expiration date and choose the furthest date
        var expiry = chain.OrderBy(x => x.Expiry).Last().Expiry;
    
        // filter the call and put options from the contracts expires on that date
        var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call);
        var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put);
        if (calls.Count() == 0 || puts.Count() == 0) return;
    
        // sort the contracts according to their strike prices
        var callContracts = calls.OrderBy(x => x.Strike);
        var putContracts = puts.OrderBy(x => x.Strike);
    
        // select the furthest OTM contracts
        var call = callContracts.Last();
        var put = putContracts.First();
    def OnData(self, slice: Slice) -> None:
        # avoid extra orders
        if self.Portfolio.Invested: return
    
        # Get the OptionChain of the self.symbol
        chain = slice.OptionChains.get(self.symbol, None)
        if not chain: return
    
        # sort 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 and put options from the contracts expires on that date
        call = [i for i in chain if i.Expiry == expiry and i.Right == 0]
        put = [i for i in chain if i.Expiry == expiry and i.Right == 1]
    
        # sort the contracts according to their strike prices
        call_contracts = sorted(call, key = lambda x: x.Strike)
        put_contracts = sorted(put, key = lambda x: x.Strike)
    
        if len(call_contracts) == 0 or len(put_contracts) == 0: return
        self.call = call_contracts[-1]
        self.put = put_contracts[0]
  5. Buy the call option and the put option at the same time and wait until expiration.
  6.     Buy(call.Symbol, 1);
        Buy(put.Symbol, 1);
    }
    self.Buy(self.call.Symbol, 1)
    self.Buy(self.put.Symbol, 1)

Summary

In this algorithm, we've realised the below payout at expiration (2017-4-22).

ItemsPrice
Price of call$ 4.60
Price of put$ 6.00
Strike price of call$ 845.00
Strike price of put$ 822.50
Price of underlying at expiration$ 843.19
Commission per trade$ 1.00
$Payoff_{call}=(843.19-845.00)^{+}=0$

$Payoff_{put}=(822.50-843.19)^{+}=0$

$Payoff_{total}=(0+0-4.60-6.00)\times100-1.00\times2=-1062$

So, the strategy losses $1062.

Algorithm

Backtest using SetFilter

Backtest using OptionChainProvider

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: