| Overall Statistics |
|
Total Trades 60 Average Win 0.35% Average Loss -0.65% Compounding Annual Return 0.774% Drawdown 1.400% Expectancy 0.019 Net Profit 0.325% Sharpe Ratio -2.927 Sortino Ratio -1.852 Probabilistic Sharpe Ratio 29.947% Loss Rate 33% Win Rate 67% Profit-Loss Ratio 0.53 Alpha -0.05 Beta 0.038 Annual Standard Deviation 0.017 Annual Variance 0 Information Ratio -0.675 Tracking Error 0.097 Treynor Ratio -1.303 Total Fees $142.60 Estimated Strategy Capacity $1300000.00 Lowest Capacity Asset SPY 32CO0FSIZGKCM|SPY R735QTJ8XC9X Portfolio Turnover 0.20% |
# region imports
from AlgorithmImports import *
# endregion
class VariancePremium(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2023, 7, 1)
self.SetEndDate(2023, 12, 1)
self.SetCash(100000)
self.spy = self.AddEquity("SPY", Resolution.Minute)
self.option = self.AddOption("SPY", Resolution.Minute)
self.option_symbol = self.option.Symbol
self.option.SetFilter(-2, 2, 0, 1)
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.At(10, 0), self.SellStraddle)
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.Every(TimeSpan.FromMinutes(30)), self.DeltaHedge)
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.At(15, 55), self.LiquidatePositions)
# Determine straddle order quantity
def OrderSizing(self):
spy_price = self.Securities["SPY"].Price
size = int(self.Portfolio.Cash / (spy_price * 50))
return size
# Place short straddle order
def SellStraddle(self):
if not self.Portfolio.Invested:
if self.CurrentSlice.OptionChains.ContainsKey(self.option_symbol):
chain = self.CurrentSlice.OptionChains[self.option_symbol]
contracts_expiring_today = [i for i in chain if i.Expiry.date() == self.Time.date()]
if len(contracts_expiring_today) == 0:
contracts_expiring_today = [i for i in chain if i.Expiry.date() == self.Time.date() + timedelta(days=1)]
if len(contracts_expiring_today) == 0:
return
spy_price = self.Securities["SPY"].Price
contract = min(contracts_expiring_today, key=lambda x: abs(x.Strike - spy_price))
straddle = OptionStrategies.Straddle(self.option_symbol, contract.Strike, contract.Expiry)
order_size = self.OrderSizing()
self.Sell(straddle, order_size)
self.Debug(f"Sold straddle: strike = {contract.Strike}, expiry = {contract.Expiry}, quantity = {order_size}")
# Dynamically hedge straddle by adjusting position in the underlying
def DeltaHedge(self):
if not self.Portfolio.Invested:
return
total_delta = 0
for holding in self.Portfolio.Values:
if holding.Symbol.SecurityType == SecurityType.Option:
if self.CurrentSlice.OptionChains.ContainsKey(holding.Symbol.Underlying):
option_contract = self.CurrentSlice.OptionChains[holding.Symbol.Underlying].Contracts[holding.Symbol]
total_delta += holding.Quantity * option_contract.Greeks.Delta
spy_holding = self.Portfolio["SPY"]
spy_quantity = spy_holding.Quantity
target_spy_quantity = -total_delta
if spy_quantity != target_spy_quantity:
self.MarketOrder("SPY", target_spy_quantity - spy_quantity)
self.Debug("Adjusted Underlying Hedge Position")
# Liquidate all positions
def LiquidatePositions(self):
self.Liquidate()
self.Debug("Portfolio Liquidated")