| Overall Statistics |
|
Total Trades 384 Average Win 6.45% Average Loss -5.59% Compounding Annual Return -38.130% Drawdown 82.200% Expectancy 0.016 Net Profit -36.289% Sharpe Ratio 0.652 Probabilistic Sharpe Ratio 26.744% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 1.16 Alpha 1.189 Beta 2.773 Annual Standard Deviation 1.381 Annual Variance 1.907 Information Ratio 0.767 Tracking Error 1.311 Treynor Ratio 0.325 Total Fees $2830.64 Estimated Strategy Capacity $8300000.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(2022, 1, 1)
self.SetEndDate(2022, 12, 31)
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
inverse_sum = sum([1/std.Current.Value for std in top5.values()])
if inverse_sum == 0:
return
# Create Portfoliotarget for the inverse weighted STD
targets = [PortfolioTarget(future.Mapped, 1/std.Current.Value/inverse_sum)
for future,std in top5.items() if future.Mapped]
# 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)