Overall Statistics |
Total Trades 1166 Average Win 0.01% Average Loss -0.01% Compounding Annual Return -34.261% Drawdown 5.200% Expectancy -0.953 Net Profit -5.186% Sharpe Ratio -24.441 Loss Rate 97% Win Rate 3% Profit-Loss Ratio 0.52 Alpha -0.353 Beta -0.003 Annual Standard Deviation 0.014 Annual Variance 0 Information Ratio -1.968 Tracking Error 0.125 Treynor Ratio 112.243 Total Fees $1166.00 |
import numpy as np # Throws an error, what else? #from Risk.MaximumDrawdownPercentPerSecurity import MaximumDrawdownPercentPerSecurity class VWAPBreakout(QCAlgorithm): def Initialize(self): self.DBG = False # # Chart - Master Container for the Chart: stockPlot = Chart("Custom Plot") stockPlot.AddSeries(Series("Buy", SeriesType.Scatter, 0)) stockPlot.AddSeries(Series("Sell", SeriesType.Scatter, 0)) stockPlot.AddSeries(Series("VWAP", SeriesType.Line, 0)) stockPlot.AddSeries(Series("Price", SeriesType.Candle, 0)) self.AddChart(stockPlot) # #self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.07)) self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage) # # Daily EOD liquidation self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 59, 52), Action(self.End_of_day_liquidate)) # #Initial investment and backtest period self.SetStartDate(2019,7,1) self.SetEndDate(datetime.now().date() - timedelta(1)) #Set End Date self.SetCash(25000) # Adds SPY / QQQ to be used in our technical indicators self.sym = "QQQ" self.res = Resolution.Minute self.SetBenchmark(self.sym) equity = self.AddEquity(self.sym, self.res) # self.tolerance = 1.0025 # threshold to prevent bouncing self.lastPrice = 0 self.lastVwap = 0 # # Rolling Windows # https://www.quantconnect.com/docs/algorithm-reference/rolling-window # https://backtest-rookies.com/2018/09/21/quantconnect-accessing-previous-values/ # Creates a Rolling Window indicator to keep the 2 TradeBar # Calculating daily window size relative to sampling size # Trading occurs between 9:30 AM Eastern Time to 4:00 PM Eastern Time. # For 6 hours, 30 minutes or # 6*60 + 30 = 390 minutes # When time sampling is 15 minutes, that means 26 samples a day (390/15) # 390/10 = 39 # 390/15 = 26 # 390/30 = 13 # 390/60 = 6.5 ~6 # dropping last hour self.window_vwap_ten = RollingWindow[TradeBar](39) self.window_vwap_fifteen = RollingWindow[TradeBar](26) self.window_vwap_hour = RollingWindow[TradeBar](6) self.window_vwap_day = RollingWindow[TradeBar](2) # number of previous days self.tradeBar_Window = RollingWindow[TradeBar](2) # number of previous bars on sampling i.e. minute # self.lookback = 15 #1440 # minutes a day self.SetWarmup(self.lookback) #self.SetWarmup(TimeSpan.FromDays(3)) # # vwap indicators self.VWAPPeriod = 5 self.vwap_ten = VolumeWeightedAveragePriceIndicator(self.sym, self.VWAPPeriod) self.vwap_fifteen = VolumeWeightedAveragePriceIndicator(self.sym, self.VWAPPeriod) self.vwap_hour = VolumeWeightedAveragePriceIndicator(self.sym, self.VWAPPeriod) self.vwap_day = VolumeWeightedAveragePriceIndicator(self.sym, self.VWAPPeriod) # tenMinutesConsolidator = TradeBarConsolidator(timedelta(minutes =10)) tenMinutesConsolidator.DataConsolidated += self.TenMinutesBarHandler self.SubscriptionManager.AddConsolidator(self.sym, tenMinutesConsolidator) # fifteenMinutesConsolidator = TradeBarConsolidator(timedelta(minutes =10)) fifteenMinutesConsolidator.DataConsolidated += self.FifteenMinutesBarHandler self.SubscriptionManager.AddConsolidator(self.sym, fifteenMinutesConsolidator) # hourlyConsolidator = TradeBarConsolidator(timedelta(hours =1)) hourlyConsolidator.DataConsolidated += self.HourlyBarHandler self.SubscriptionManager.AddConsolidator(self.sym, hourlyConsolidator) # dailyConsolidator = TradeBarConsolidator(timedelta(hours =1)) dailyConsolidator.DataConsolidated += self.DailyBarHandler self.SubscriptionManager.AddConsolidator(self.sym, dailyConsolidator) # # https://www.quantconnect.com/tutorials/api-tutorials/consolidating-data-to-build-bars def TenMinutesBarHandler(self, sender, bar): # TradeBar( DateTime time, Symbol symbol, decimal open, decimal high, decimal low, decimal close, decimal volume) tradeBar = TradeBar(bar.EndTime, bar.Symbol, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume) self.vwap_ten.Update(tradeBar) #self.window_vwap_ten.Add(self.vwap_ten.Current.Value) def FifteenMinutesBarHandler(self, sender, bar): # TradeBar( DateTime time, Symbol symbol, decimal open, decimal high, decimal low, decimal close, decimal volume) tradeBar = TradeBar(bar.EndTime, bar.Symbol, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume) self.vwap_fifteen.Update(tradeBar) #self.window_vwap_fifteen.Add(self.vwap_fifteen.Current) def HourlyBarHandler(self, sender, bar): # TradeBar( DateTime time, Symbol symbol, decimal open, decimal high, decimal low, decimal close, decimal volume) tradeBar = TradeBar(bar.EndTime, bar.Symbol, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume) self.vwap_hour.Update(tradeBar) def DailyBarHandler(self, sender, bar): # TradeBar( DateTime time, Symbol symbol, decimal open, decimal high, decimal low, decimal close, decimal volume) tradeBar = TradeBar(bar.EndTime, bar.Symbol, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume) self.vwap_day.Update(tradeBar) def OnData(self, slice): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. Arguments: data: Slice object keyed by symbol containing the stock data ''' if slice[self.sym] is None: return if not self.vwap_fifteen.IsReady: return self.tradeBar_Window.Add(slice[self.sym]) self.lastPrice = slice[self.sym].Close self.lastVwap = self.vwap_fifteen.Current.Value #self.Debug(str(self.vwap.Current.Value)) self.Plot('Custom Plot', 'Price', self.lastPrice) self.Plot('Custom Plot', 'VWAP', self.lastVwap) curBar = self.tradeBar_Window[0] self.Debug("Current Price: " + str(curBar.Close)) # Cannot access previous price - WHY? #prvBar = self.tradeBar_Window[1] #self.Debug("Previous Price: " + str(prvBar.Close)) # # THIS IS THE BROKEN PART: How do I get the previous VWAP values from different time frames??? # #curVWAP = self.window_vwap_fifteen[0] #prvVWAP = self.window_vwap_fifteen[0] #self.Debug("Current VWAP: " + str(curVWAP)) #self.Debug("Previous VWAP: " + str(prvVWAP)) price = self.lastPrice * 1.0025 if not self.Portfolio.Invested and self.lastPrice < self.lastVwap: #set stop price and limit price at +-2% twoPercent = 0.98 takeProfit = 1.02 #SL and TP orders to protect investment stopPrice = self.Securities[self.sym].Price * twoPercent limitPrice = self.Securities[self.sym].Price * takeProfit qty = 5 self.MarketOrder(self.sym, 2) self.Plot("Custom Plot", "Buy", self.lastPrice) self.StopLimitOrder(self.sym, -qty, stopPrice, stopPrice) self.LimitOrder(self.sym, qty, limitPrice) if self.Portfolio.Invested and self.lastPrice > self.lastVwap: self.Plot("Custom Plot", "Sell", self.lastPrice) self.Liquidate() def End_of_day_liquidate(self): self.Liquidate() def OnOrderEvent(self, orderEvent): #self.Log(str(orderEvent)) self.Debug(str(orderEvent))