Overall Statistics
Total Trades
146
Average Win
2.42%
Average Loss
-1.92%
Compounding Annual Return
16.121%
Drawdown
13.800%
Expectancy
0.682
Net Profit
71.407%
Sharpe Ratio
1.382
Probabilistic Sharpe Ratio
67.628%
Loss Rate
26%
Win Rate
74%
Profit-Loss Ratio
1.26
Alpha
0.14
Beta
0.151
Annual Standard Deviation
0.123
Annual Variance
0.015
Information Ratio
-0.155
Tracking Error
0.217
Treynor Ratio
1.126
Total Fees
$1380.50
Estimated Strategy Capacity
$600000.00
Lowest Capacity Asset
SVXY V0H08FY38ZFP
# Go long SVXY (short volatility) for a short term hold expecting volatility to drop.
# Uses 3 entries, the first entry signal doesn't create a position, the second does.
# Use a SMA 4 and SMA13 on SVXY, and SPY adx. If the SMA4<SMA13, and the OHLC of SVXY is above SMA4 and SPY adx<30 then go long SVXY.
# When the SMA4>SMA13 and the SVXY OHLC goes above the SMA4 then exit.

class ShortVolwithSVXY(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2018, 2, 5)   # (2018,2,5) is the date of the deleveraging to 0.5x
        #self.SetEndDate(2018, 2, 1)
        self.SetCash(100000) 
        self.svxy = self.AddEquity("SVXY", Resolution.Minute)
        self.spy = self.AddEquity("SPY", Resolution.Minute)
        self.AddEquity("IEF", Resolution.Minute)
        self.AddEquity("UST", Resolution.Minute)
        self.svxy.SetDataNormalizationMode(DataNormalizationMode.Raw)
        self.smaFast = self.SMA("SVXY", 4, Resolution.Daily)
        self.smaSlow = self.SMA("SVXY", 13, Resolution.Daily)
        self.adx = self.ADX("SPY", 30, Resolution.Daily)
        self.SetWarmUp(30)      # warm up the indicator
        self.Schedule.On(self.DateRules.EveryDay("SVXY"), self.TimeRules.BeforeMarketClose("SVXY", 15), self.Rebalance)
        self.targets = {0:0, 1:0.15, 2:0.25, 3:1}      # dictionary to hold our target position sizes {position count: % allocation}
        self.counter = 0        # counts what target position we are at, start at zero for first position
        self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.12))
        
    def OnData(self, data):
        if not  data.ContainsKey("SVXY") or data["SVXY"] is None: return
        self.OHLC = (self.Securities["SVXY"].Open+self.Securities["SVXY"].High+self.Securities["SVXY"].Low+self.Securities["SVXY"].Price)/4
    
    def Rebalance(self):
        if self.adx.Current.Value<30 and self.OHLC > self.smaFast.Current.Value and self.smaFast.Current.Value<self.smaSlow.Current.Value:
            # if we add 1 to our current position count and it is greater than our 100% allocation, then we do nothing
            if self.counter + 1 not in self.targets:
                return            
            # since this is a new buy signal, we look at our current position counter and go up to the next allocation amount
            self.counter += 1
            #self.SetHoldings("IEF", 0, True) # just testing what would be a good sideline security while waiting for the next SVXY trade
            self.SetHoldings("SVXY", self.targets[self.counter])
            self.Debug("Buy SVXY")
                
        if self.OHLC>self.smaFast.Current.Value and self.smaFast.Current.Value>self.smaSlow.Current.Value:
            self.SetHoldings("SVXY", 0)
            #self.SetHoldings("IEF", 1)
            self.counter = 0
            self.Debug("Sell SVXY")
        else:
            pass