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")