
The strategy shorts S&P 500 out-of-the-money puts monthly, applies 2.0x leverage, invests excess margin in risk-free assets, and rebalances monthly to maintain consistent exposure and optimize returns.
ASSET CLASS: options | REGION: United States | FREQUENCY:
Monthly | MARKET: equities | KEYWORD: Cloning Hedge, Fund Indexes
I. STRATEGY IN A NUTSHELL
This strategy shorts out-of-the-money S&P 500 put options each month, using a strike based on 1× monthly index volatility. It applies 2× leverage and invests unused margin in the risk-free asset, rebalancing monthly to maintain consistent exposure and capture option premiums.
II. ECONOMIC RATIONALE
Option writing can earn compensation for jump and volatility risk premia. By systematically replicating these exposures, the strategy can mimic hedge fund returns and capture non-linear risk premia.
III. SOURCE PAPER
The Cost of Capital for Alternative Investments [Click to Open PDF]
Jakub W. Jurek and Erik Stafford.University of Pennsylvania – Finance Department; National Bureau of Economic Research (NBER).Harvard Business School – Finance Unit.
<Abstract>
Traditional risk factor models indicate that hedge funds capture pre-fee alphas of 6% to 10% per annum over the period from 1996 to 2012. At the same time, the hedge fund return series is not reliably distinguishable from the returns of mechanical S&P 500 put-writing strategies. We show that the high excess returns to hedge funds and put-writing are consistent with an equilibrium in which a small subset of investors specialize in bearing downside market risks. Required rates of return in such an equilibrium can dramatically exceed those suggested by traditional models, affecting inference about the attractiveness of these investments.


V. BACKTEST PERFORMANCE
| Annualised Return | 10.3% |
| Volatility | 7.7% |
| Beta | 1.196 |
| Sharpe Ratio | 1.34 |
| Sortino Ratio | 0.394 |
| Maximum Drawdown | -21.8% |
| Win Rate | 61% |
V. FULL PYTHON CODE
import numpy as np
from AlgorithmImports import *
from math import floor
from datetime import datetime
class CloningHedgeFundIndexes(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 1, 1)
self.SetCash(100000)
self.symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
self.leverage:float = 2.
# spy consolidator
self.consolidator:TradeBarConsolidator = TradeBarConsolidator(timedelta(days=1))
self.consolidator.DataConsolidated += self.CustomHandler
self.SubscriptionManager.AddConsolidator(self.symbol, self.consolidator)
self.period:int = 21
# Daily price data.
self.data:RollingWindow = RollingWindow[float](self.period)
option:Option = self.AddOption("SPY", Resolution.Minute)
def CustomHandler(self, sender: object, consolidated_bar: TradeBar) -> None:
self.data.Add(consolidated_bar.Close)
def OnData(self, slice:Slice) -> None:
for i in slice.OptionChains:
chains:OptionChain = i.Value
if self.Portfolio[self.symbol].Invested:
self.Liquidate(self.symbol)
if not self.Portfolio.Invested:
# Market data is ready.
if self.data.IsReady:
market_closes:np.ndarray = np.array(list(self.data))
market_returns:np.ndarray = market_closes[:-1] / market_closes[1:] - 1
market_std:float = np.std(market_returns)
# Divide option chains into put options
puts:List = list(filter(lambda x: x.Right == OptionRight.Put, chains))
if not puts: return
underlying_price:float = self.Securities[self.symbol].Price
expiries:List[datetime] = list(map(lambda x: x.Expiry, puts))
# Determine expiration date nearly one month.
expiry:datetime = min(expiries, key=lambda x: abs((x.date() - self.Time.date()).days - 30))
strikes:List[float] = list(map(lambda x: x.Strike, puts))
# Determine out-of-the-money strike.
otm_strike:float = min(strikes, key = lambda x:abs(x - float(1 - market_std) * underlying_price))
# Leverage calc.
otm_put:OptionContract = [i for i in puts if i.Expiry == expiry and i.Strike == otm_strike]
q:float = floor(float(self.Portfolio.MarginRemaining / (underlying_price * 100)) * self.leverage)
if otm_put:
# Sell with 2x leverage.
self.Sell(otm_put[0].Symbol, q)