Overall Statistics
Total Trades
390
Average Win
10.33%
Average Loss
-2.18%
Compounding Annual Return
57.357%
Drawdown
29.600%
Expectancy
1.188
Net Profit
7731.772%
Sharpe Ratio
1.605
Probabilistic Sharpe Ratio
82.644%
Loss Rate
62%
Win Rate
38%
Profit-Loss Ratio
4.73
Alpha
0.425
Beta
0.349
Annual Standard Deviation
0.334
Annual Variance
0.112
Information Ratio
0.473
Tracking Error
0.455
Treynor Ratio
1.538
Total Fees
$71872.94
Estimated Strategy Capacity
$480000.00
Lowest Capacity Asset
SVXY V0H08FY38ZFP
import numpy as np
from collections import deque
from datetime import datetime 
class Quad:

    def __init__(self, period):
        
        self.Name = "quad"
        self.Time = datetime.min
        self.a = 0
        self.b=0
        self.c=0
        self.IsReady = False
        self.time_scale=[-i-1 for i in range(period)]
        self.queue = deque(maxlen=period)
        self.period=period
        self.Value=0

    # Update method is mandatory
    def Update(self, input):

        self.queue.appendleft(input.Close)
        self.IsReady=(self.period==len(self.queue))
        self.Time = input.EndTime
        if self.IsReady:
            self.a,self.b,self.c=np.polyfit(self.time_scale,self.queue,2)
            self.Value=self.a
        return self.IsReady
        


class SleepyVioletCat(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2012, 1, 1)
        #self.SetEndDate(2020,5,1)
        self.SetCash(100000) 
        self.AddEquity('SVXY',Resolution.Minute)
        res=Resolution.Daily
        self.uvxy=self.AddEquity('UVXY',Resolution.Daily).Symbol
        self.bb=self.BB(self.uvxy,int(self.GetParameter('bb')),2,res)
        self.sma=self.SMA(self.uvxy,4,res)
        self.rc=self.RC(self.uvxy,int(self.GetParameter('rc')),float(self.GetParameter('std')),res)
        self.trigger=False
        self.buy=False
        self.hold=False
        self.sell=False
        self.days=0
        self.quad=Quad(8)
        self.RegisterIndicator("UVXY", self.quad, res)
        self.SetWarmUp(timedelta(15))
        self.SetBenchmark('SVXY')
        #self.AddFuture(Futures.Indices.VIX, Resolution.Minute).SetFilter(TimeSpan.Zero, TimeSpan.FromDays(120))
        #self.future=False
    def OnData(self, data):
        #self.Log(self.Portfolio['SVXY'].UnrealizedProfitPercent)
        '''
        for chain in data.FutureChains.Values:
            pool=sorted(chain.Contracts.Values,key=lambda x: x.Expiry)
            if len(pool)>2:
                vx0,vx1,vx2 = pool[:3]
                if vx0.LastPrice>vx1.LastPrice and vx2.LastPrice<vx1.LastPrice:
                    self.future=True
        '''
        if self.bb.IsReady and data.ContainsKey(self.uvxy) and self.sma.IsReady and self.quad.IsReady and data[self.uvxy]!=None:
            self.days=self.days+1
                
            vix=data[self.uvxy].Close
            k=self.rc.Slope.Current.Value/vix
            if self.rc.UpperChannel.Current.Value<vix:
                self.trigger=True
                #self.future=False

            if self.trigger and self.sma.Current.Value>vix and self.quad.a/vix<float(self.GetParameter('quad')) and float(self.GetParameter('pos'))<abs(self.quad.b/self.quad.a):
                self.buy=True

            if self.hold and (vix<(self.bb.MiddleBand.Current.Value-self.bb.StandardDeviation.Current.Value)):
                self.sell=True
                
            
        if self.buy and data.ContainsKey('SVXY'):
            if not self.hold:
                self.Log('uvxy:'+str(self.uvxy))
                self.Log('channel:'+str(0.5*(self.rc.UpperChannel.Current.Value-self.rc.LowerChannel.Current.Value)/vix))
                self.Log('normalized a:'+str(self.quad.a/vix))
                self.Log('normalized b:'+str(self.quad.b/vix))
                
            self.SetHoldings('SVXY',1)
            self.trigger=False
            self.buy=False
            self.hold=True
            


        if data.ContainsKey('SVXY') and (self.sell or self.Portfolio['SVXY'].UnrealizedProfitPercent<-float(self.GetParameter('loss'))) and self.days>385*1 and not self.buy:
            self.Log('profit' if self.Portfolio['SVXY'].UnrealizedProfitPercent>0 else 'loss')
            self.SetHoldings('SVXY',0)
            self.hold=False
            self.sell=False
            self.days=0