Overall Statistics |
Total Trades 2 Average Win 17.20% Average Loss 0% Compounding Annual Return 2.024% Drawdown 4.600% Expectancy 0 Net Profit 17.190% Sharpe Ratio 0.451 Probabilistic Sharpe Ratio 1.329% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0.032 Annual Variance 0.001 Information Ratio 0.451 Tracking Error 0.032 Treynor Ratio 0 Total Fees $10.00 Estimated Strategy Capacity $5000.00 Lowest Capacity Asset UVXY 2ZWLGYQK5YDEU|UVXY V0H08FY38ZFP |
# region imports from AlgorithmImports import * from scipy import stats # endregion class WellDressedTanLemur(QCAlgorithm): def Initialize(self): self.SetStartDate(2015, 1, 1) # Set Start Date self.SetEndDate(datetime.now()) self.SetCash(100000) # Set Strategy Cash self.SetWarmup(timedelta(50)) self.equity = self.AddEquity("UVXY", Resolution.Hour) self.VIX = self.AddIndex("VIX", Resolution.Hour).Symbol self.symbol = self.equity.Symbol self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw) self.contractsAdded = set() self.percentileThreshold = 50 self.lookback = 50 self.DTEput = 20 self.DaysBeforeExp = 3 self.putcontract = str() self.current_VIX_percentile = 0 self.VIXwindow = RollingWindow[Tick](self.lookback) def OnData(self, data): if(self.IsWarmingUp): return self.VIXwindow.Add(data["VIX"]) current_VIX = self.Securities[self.VIX].Price self.current_VIX_percentile = stats.percentileofscore(self.VIXwindow, current_VIX) self.Log(self.current_VIX_percentile) option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option] for option in option_invested: if option.IsShort: if (self.putcontract.ID.Date - self.Time) <= timedelta(self.DaysBeforeExp): self.Liquidate(self.putcontract) self.Log("Closed: too close to expiration") self.putcontract = str() if self.Portfolio.UnrealizedProfitPercent < -1: self.Liquidate(self.putcontract) self.putcontract = str() if self.Portfolio.UnrealizedProfitPercent >= 0.75: self.Liquidate(self.putcontract) self.putcontract = str() if self.current_VIX_percentile < self.percentileThreshold: self.SellPut(data) def SellPut(self, data): if self.putcontract == str(): self.putcontract = self.OptionsFilter(data) return elif not self.Portfolio[self.putcontract].Invested and data.ContainsKey(self.putcontract): self.underlyingPrice = self.Securities[self.symbol].Price positionSize = self.Portfolio.Cash / (self.putcontract.ID.StrikePrice * 100) self.Sell(self.putcontract, positionSize) # Allocation sizing goes here def OptionsFilter(self, data): contracts = self.OptionChainProvider.GetOptionContractList(self.symbol, data.Time) self.underlyingPrice = self.Securities[self.symbol].Price # self.underlyingPrice can later be replaced with projected UVXY price otm_puts = [i for i in contracts if i.ID.OptionRight == OptionRight.Put and i.ID.StrikePrice < self.underlyingPrice] if len(otm_puts) > 0: putcontract = sorted(sorted(otm_puts, key = lambda x: abs((x.ID.Date - self.Time).days - self.DTEput)), key = lambda x: self.underlyingPrice - x.ID.StrikePrice)[0] if putcontract not in self.contractsAdded: self.contractsAdded.add(putcontract) self.AddOptionContract(putcontract, Resolution.Hour) return putcontract else: return str() def OnOrderEvent(self, orderEvent): # log order events self.Log(str(orderEvent)) # QC appears to support daily resolution for options now