Overall Statistics |
Total Trades 4746 Average Win 0.51% Average Loss -0.54% Compounding Annual Return 3.932% Drawdown 37.800% Expectancy 0.042 Net Profit 58.559% Sharpe Ratio 0.276 Probabilistic Sharpe Ratio 0.128% Loss Rate 46% Win Rate 54% Profit-Loss Ratio 0.93 Alpha 0.002 Beta 0.358 Annual Standard Deviation 0.129 Annual Variance 0.017 Information Ratio -0.384 Tracking Error 0.151 Treynor Ratio 0.1 Total Fees $54404.70 Estimated Strategy Capacity $45000000.00 Lowest Capacity Asset ZO Y6RTF5MGZVOL |
# region imports from AlgorithmImports import * from datetime import datetime import math # endregionfs class InverseVolatility(QCAlgorithm): def Initialize(self): self.SetStartDate(2011, 1, 1) # Jens #self.SetEndDate(2021, 12, 31) self.SetCash(1000000) # Set Strategy Cash self.SetSecurityInitializer(BrokerageModelSecurityInitializer(self.BrokerageModel, FuncSecuritySeeder(self.GetLastKnownPrices))) self.volatility = {} tickers = [ Futures.Indices.VIX, Futures.Indices.SP500EMini, Futures.Indices.NASDAQ100EMini, Futures.Indices.Dow30EMini, Futures.Energies.BrentCrude, Futures.Energies.Gasoline, Futures.Energies.HeatingOil, Futures.Energies.NaturalGas, Futures.Grains.Corn, Futures.Grains.Oats, Futures.Grains.Soybeans, Futures.Grains.Wheat ] for ticker in tickers: future = self.AddFuture(ticker, extendedMarketHours=True) # 30-day standard deviation of 1-day returns roc = self.ROC(future.Symbol, 1, Resolution.Daily) self.volatility[future] = IndicatorExtensions.Of(StandardDeviation(30), roc) self.SetWarmup(31, Resolution.Daily) self.Schedule.On( self.DateRules.WeekStart(), self.TimeRules.At(10,0,0), self.Rebalance) def Rebalance(self): if self.IsWarmingUp: return sorted_by_value = sorted([kvp for kvp in self.volatility.items() if kvp[1].IsReady], key=lambda item: item[1].Current.Value) top5 = {k: v for k, v in sorted_by_value[:5]} # Sum the inverse STD of ROC # Jens: Added exception here as well. Not sure if that still works as it should. I ignore values that have no std yet inverse_sum = sum([1/std.Current.Value if std.Current.Value else 0 for std in top5.values()]) if inverse_sum == 0: return # Create Portfoliotarget for the inverse weighted STD targets = [PortfolioTarget(future.Mapped, 0.1/std.Current.Value/inverse_sum) # Jens: added exception for std being zero then no target will be given. This accounts for the fact that these # contracts are also not included in the inverse_sum for future,std in top5.items() if future.Mapped and std.Current.Value] # Liquidate if invested and no new negative news for symbol, holdings in self.Portfolio.items(): if holdings.Invested and symbol not in top5: targets.append(PortfolioTarget(symbol, 0)) #for target in targets: # self.Plot("Targets", target.Symbol.Value, target.Quantity) self.SetHoldings(targets)