| 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