Introduction

The Wheel strategy is a popular trading strategy for Options that enables traders to build a steady flow of income from Equity assets they want to hold for the long term. In this research post, we’ll discuss the basic trading rules of the Wheel strategy, walk through how we can easily implement it on QuantConnect, and review the recent risk-adjusted returns of the strategy.

Background

The Wheel is a strategy that rotates between selling cash-secured puts and covered calls. In this strategy, the algorithm sells cash-secured out-of-the-money (OTM) puts until it’s assigned shares in the underlying Equity. While it holds the underlying shares, it sells OTM covered calls until the buyer exercises their Option contract and the algorithm loses its underlying shares. In both phases of the strategy, the algorithm generates income by collecting the premium from selling Option contracts.

The underlying Equity that is chosen should be a company that you don’t mind owning. When selling put contracts, the strike that’s selected should be the price below the current price that you’re comfortable buying the underlying stock. To make the position “cash-secured”, keep enough cash so that you can buy the underlying shares when you're assigned. After you write the put contracts, if the stock price stays above the strike price, the Option expires worthless and you keep the premium as profit. Otherwise, you’re obligated to buy the stock at the strike price and you rotate into selling covered calls.

When selling call contracts, the strike that’s selected should be the price above the current price that you’re comfortable selling the underlying stock. To make the position “covered”, the position size should be the same quantity you used when selling the put contracts. After you write the call contracts, if the stock price stays below the strike price, the Option expires worthless and you keep the premium as profit. Otherwise, you’re obligated to sell the stock at the strike price and you rotate into selling cash-secured puts again.

Implementation

To implement this strategy, we used SPY as the underlying Equity. It’s important to select an asset that’s relatively stable and that you’re willing to hold for the long term.

self._equity = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.Raw)

To calculate the price at which we would be comfortable selling contracts relative to the current underlying price, we chose an OTM threshold rate of 5%.

self._otm_threshold = 0.05

The _get_target_contract helper method is where we select the contracts we want to sell.

def _get_target_contract(self, right, target_price):
    contract_symbols = self.option_chain_provider.get_option_contract_list(self._equity.symbol, self.time)
    expiry = min([s.id.date for s in contract_symbols if s.id.date.date() > self.time.date() + timedelta(30)])
    filtered_symbols = [
        s for s in contract_symbols
        if (s.id.date == expiry and s.id.option_right == right and
            (s.id.strike_price <= target_price if right == OptionRight.PUT else s.id.strike_price >= target_price))
    ]
    symbol = sorted(filtered_symbols, key=lambda s: s.id.strike_price, reverse=right == OptionRight.PUT)[0]
    self.add_option_contract(symbol)
    return symbol

This method works through the following procedure: 

  1. Get all the Option contracts that are currently trading for the SPY.
  2. Select the closest expiration date that’s at least 30 days away.
  3. Select the call/put contract that has the expiry we want and is at least 5% OTM.
  4. Subscribe to the contract so we can trade it.

The on_data method contains the trading logic, condensed down to just 6 lines of code.

if not self.portfolio.invested and self.is_market_open(self._equity.symbol): 
    symbol = self._get_target_contract(OptionRight.PUT, self._equity.price * (1-self._otm_threshold)) 
    self.set_holdings(symbol, -0.2) 
elif [self._equity.symbol] == [symbol for symbol, holding in self.portfolio.items() if holding.invested]: 
    symbol = self._get_target_contract(OptionRight.CALL, self._equity.price * (1+self._otm_threshold)) 
    self.market_order(symbol, -self._equity.holdings.quantity / 100)

Conclusion

The Wheel strategy generates income through collecting the premiums of selling Option contracts. The backtest results show the Wheel strategy out-performs buy-and-hold in the underlying Equity, SPY. The algorithm achieved a Sharpe ratio of 1.083 while the SPY produced a Sharpe ratio of 0.7 over the same time period. 

To test if the strategy's performance was reliant on the specific parameters chosen, we ran an optimization job. We varied the _otm_threshold from 10% to 20% in steps of 2%. We also varied the minimum number of days before the selected contract expires from 15 days to 60 days in steps of 15. All parameter combinations outperformed the benchmark, suggesting the strategy is robust.