Overall Statistics
Total Trades
1484
Average Win
1.69%
Average Loss
-2.45%
Compounding Annual Return
-12.464%
Drawdown
84.100%
Expectancy
0.001
Net Profit
-41.307%
Sharpe Ratio
0.166
Probabilistic Sharpe Ratio
3.312%
Loss Rate
41%
Win Rate
59%
Profit-Loss Ratio
0.69
Alpha
0.122
Beta
-0.184
Annual Standard Deviation
0.598
Annual Variance
0.358
Information Ratio
-0.04
Tracking Error
0.614
Treynor Ratio
-0.542
Total Fees
$2150.84
from System import *
from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Data import *
from QuantConnect.Data.Market import *
from QuantConnect.Data.Custom import *
from QuantConnect.Algorithm import *
from QuantConnect.Python import PythonQuandl
from QuantConnect.Data.Custom.CBOE import *

class VentralTachyonAtmosphericScrubbers(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2016, 1, 1)
        self.SetEndDate(2020, 1, 1)
        self.SetCash(10000)  # Set Strategy Cash
        
        self.perc_qnty = 0.95
        self.selectedResolution = Resolution.Daily
            
        # Tradable Symbols    
        self.svxy = self.AddEquity("SVXY", self.selectedResolution).Symbol
        self.uvxy = self.AddEquity("UVXY", self.selectedResolution).Symbol
        self.tqqq = self.AddEquity("TQQQ", self.selectedResolution).Symbol
        self.AddEquity("SPY", self.selectedResolution)
        
        # Vix Data
        self.vix = "VIX"
        self.vxv = "CBOE/VXV"
        self.vixsm = "VIX9D"
        
        self.cboeVix = self.AddData(CBOE, self.vix, Resolution.Daily).Symbol
        self.quandlvxv = self.AddData(Quandl, self.vxv, Resolution.Daily).Symbol
        self.cboeVixsm = self.AddData(CBOE, self.vixsm, Resolution.Daily).Symbol
        
        # SPY SMA Indicator
        self.spySma = self.SMA("SPY", 25, self.selectedResolution, Field.Open)
        # SPY MACD Indicator
        self.macd = self.MACD("SPY", 12, 26, 6, MovingAverageType.Exponential, self.selectedResolution, Field.Open)
        
        self.Schedule.On(self.DateRules.EveryDay(), \
                         self.TimeRules.At(0, 0), \
                         self.ResetVix)
                         
        # self.AddRiskManagement(TrailingStopRiskManagementModel(0.05))
        # self.AddRiskManagement(MaximumUnrealizedProfitPercentPerSecurity(0.30))
        
        self.yspy = 0
        self.yspySma = 0

    def OnData(self, data):
        if data.ContainsKey(self.cboeVix):
            self.vixData = data.Get(CBOE, self.cboeVix)
            
        if data.ContainsKey(self.vxv):
            self.vxvData = data.Get(Quandl, self.quandlvxv)
            
        if data.ContainsKey(self.cboeVixsm):
            self.vixsmData = data.Get(CBOE, self.cboeVixsm)
            
        if not (self.spySma.IsReady and self.macd.IsReady): return
        if not (self.vixData and self.vxvData and self.vixsmData): return
        
        vixPrice = self.vixData.Close
        vxvPrice = self.vxvData.Value
        vixsmPrice = self.vixsmData.Close
        
        vixRatio = vixPrice/vxvPrice
        
        vixCrossUp = False
        if vixsmPrice:
            vixCrossUp = vixsmPrice > vixPrice
            
        inShort = self.Portfolio["SVXY"].Invested
        inLong = self.Portfolio["SVXY"].Invested
        inRest = self.Portfolio["TQQQ"].Invested
            
        macdLong = self.macd.Current.Value < self.macd.Signal.Current.Value
        
        shortEntry = (vixRatio < 0.95) and not vixCrossUp and not (self.Securities["SPY"].Open <= self.spySma.Current.Value and self.yspy > self.yspySma)
        shortExit = inShort and (not shortEntry)
        
        longEntry = vixRatio > 1.05 and vixCrossUp and macdLong
        longExit = inLong and (not longEntry)
        
        if shortExit or longExit:
            self.Liquidate()
            if not inRest and longExit:
                self.SetHoldings(self.tqqq, self.perc_qnty)
            return
        
        if (shortEntry):
            if inLong:
                self.Liquidate(self.uvxy)
            if inRest:
                self.Liquidate(self.tqqq)
            if not inShort:
                self.SetHoldings(self.svxy, self.perc_qnty)
        
        if (longEntry):
            if inShort:
                self.Liquidate(self.svxy)
            if inRest:
                self.Liquidate(self.tqqq)
            if not inLong:
                self.SetHoldings(self.uvxy, self.perc_qnty)
        
        self.yspy = self.Securities["SPY"].Open
        self.yspySma = self.spySma.Current.Value
        
    def ResetVix(self):
        self.vixData = None
        self.vxvData = None
        self.vixsmData = None
        

# In CBOE/VIX data, there is a "vix close" column instead of "close" which is the 
# default column namein LEAN Quandl custom data implementation.
# This class assigns new column name to match the the external datasource setting.
class QuandlVix(PythonQuandl):
    
    def __init__(self):
        self.ValueColumnName = "VIX Close"
from QuantConnect.Python import PythonQuandl # quandl data not CLOSE
from QuantConnect.Python import PythonData # custom data
from QuantConnect.Data import SubscriptionDataSource

from datetime import datetime, timedelta
import decimal

class CboeVix(PythonData):
    '''CBOE Vix Download Custom Data Class'''
    def GetSource(self, config, date, isLiveMode):
        url_vix = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vixcurrent.csv"
        return SubscriptionDataSource(url_vix, 
                                      SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLiveMode):
        if not (line.strip() and line[0].isdigit()): return None
        # New CboeVix object
        index = CboeVix();
        index.Symbol = config.Symbol
        try:
            # Example File Format:
            # Date          VIX Open    VIX High VIX Low    VIX Close
            # 01/02/2004    17.96    18.68     17.54        18.22
            #print line
            data = line.split(',')
            date = data[0].split('/')
            index.Time = datetime(int(date[2]), int(date[0]), int(date[1]))
            index.Value = decimal.Decimal(data[4])
            index["Open"] = float(data[1])
            index["High"] = float(data[2])
            index["Low"] = float(data[3])
            index["Close"] = float(data[4])
        except ValueError:
            # Do nothing
            return None
#       except KeyError, e:
#          print 'I got a KeyError - reason "%s"' % str(e)
        return index

class CboeVixsm(PythonData):
    '''CBOE Vix Download Custom Data Class'''
    def GetSource(self, config, date, isLiveMode):
        url_vix = "https://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vix9ddailyprices.csv"
        return SubscriptionDataSource(url_vix, 
                                      SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLiveMode):
        if not (line.strip() and line[0].isdigit()): return None
        # New CboeVix object
        index = CboeVixsm();
        index.Symbol = config.Symbol
        try:
            # Example File Format:
            # Date          VIX Open    VIX High VIX Low    VIX Close
            # 01/02/2004    17.96    18.68     17.54        18.22
            #print line
            data = line.split(',')
            date = data[0].split('/')
            index.Time = datetime(int(date[2]), int(date[0]), int(date[1]))
            index.Value = decimal.Decimal(data[4])
            index["Open"] = float(data[1])
            index["High"] = float(data[2])
            index["Low"] = float(data[3])
            index["Close"] = float(data[4])
        except ValueError:
            # Do nothing
            return None
#       except KeyError, e:
#          print 'I got a KeyError - reason "%s"' % str(e)
        return index
        
# NB: CboeVxV class ==  CboeVix class, except for the URL
class CboeVxv(PythonData):
    '''CBOE VXV Download Custom Data Class'''
    
    def GetSource(self, config, date, isLiveMode):
        url_vxv = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vix3mdailyprices.csv"
        return SubscriptionDataSource(url_vxv, 
                                      SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLiveMode):
        if not (line.strip() and line[0].isdigit()): return None
        index = CboeVxv();
        index.Symbol = config.Symbol
        try:
        # Example File Format:
        #                 OPEN    HIGH    LOW        CLOSE
        # 12/04/2007    24.8    25.01    24.15    24.65
            data = line.split(',')
            date = data[0].split('/')
            index.Time = datetime(int(date[2]), int(date[0]), int(date[1]))
            index.Value = decimal.Decimal(data[4])
            index["Open"] = float(data[1])
            index["High"] = float(data[2])
            index["Low"] = float(data[3])
            index["Close"] = float(data[4])
        except ValueError:
                # Do nothing
                return None
        return index