Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -1.661 Tracking Error 0.128 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 |
from clr import AddReference AddReference("System.Core") AddReference("System.Collections") AddReference("QuantConnect.Common") AddReference("QuantConnect.Algorithm") from System import * from System.Collections.Generic import List from QuantConnect import * from QuantConnect.Algorithm import QCAlgorithm from QuantConnect.Data.UniverseSelection import * from datetime import datetime, timedelta import datetime class ConsolidatorHelp(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 12, 1) # Set Start Date self.SetEndDate(datetime.datetime.now()) self.SetCash(600000) # Set Strategy Cash self.SetWarmup(20) self.SetBenchmark("SPY") self.UniverseSettings.Resolution = Resolution.Minute self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.UniverseSettings.Leverage = 2 self._changes = None self.MinData = {} self.dayMinData = {} self.Data = {} # dictionary to hold rolling window for each symbol self.window_hr = {} self.windowmin = {} # Set params for tracking stop losses # ----------------------------------------------- self.activateStopCoef = 1 # activate trail when price rises 'x * ATR' self.initialStopCoef = 3.5 # exit when price dips 'x * ATR' self.trailStopCoef = 11 # exit when price dips 'x * ATR'(trailing) self.trailActivationPrice = 0 self.trailActivationPriceSells = 0 self.trailStopActivated = False self.trailStopActivatedSells = False self.trailingStopLoss = 0 self.initialStopLoss = 0 self.trailingStopLossSells = 0 self.initialStopLossSells = 0 self.ADXtresh = 20 ##___________FILTERS_________________## def CoarseSelectionFunction(self, coarse ): top = [x for x in coarse if x.HasFundamentalData and 500 > x.Price > 40 and x.Volume > 500000] self.Debug("len of coarse = " + str(len(top))) return [x.Symbol for x in top] def FineSelectionFunction(self, fine ): top = [x for x in fine if x.ValuationRatios.PERatio > 20 and x.ValuationRatios.TrailingDividendYield < .02 and not x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.BasicMaterials and not x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Energy] top = sorted(top, key=lambda x: x.ValuationRatios.PERatio, reverse=True) self.Debug("len of fine = " + str(len(top))) return [x.Symbol for x in top][:5] def OnData(self, data): # Make sure indicators and rolling windows are ready if not all([symbol.IsReady for symbol in self.dayMinData.values()]): return if not all([symbol.IsReady for symbol in self.MinData.values()]): return ''' for symbol, symbolData in self.dayMinData.items(): if not symbolData.IsReady: return for symbol, symbolData in self.MinData.items(): if not symbolData.IsReady: return for symbol in self.dayMinData.items(): if not (self.ema.IsReady and self.emaWindow.IsReady and \ self.rsi.IsReady and self.rsiWindow.IsReady and \ self.BB1UpperWindow.IsReady and self.BB1LowerWindow.IsReady and self.window_hr.IsReady): return self.Debug("Are WE GETTING DATA???")''' #---------------------------------------------------------------_--_# self.windowmin.Add(data[symbol]) self.window_hr.Add(data[symbol]) for symbol, value in self.dayMinData.items(): if data.ContainsKey(symbol) and \ data[symbol] != None: self.Debug("AM I GETTING DATA???") self.Debug(str(symbol)) for symbol, value in self.MinData.items(): if (value.windowmin[0].EndTime.hour < 15 or (value.windowmin[0].EndTime.hour == 15 and value.windowmin[0].EndTime.minute < 30)) and \ data.ContainsKey(symbol) and not self.Portfolio[symbol].Invested and \ value.windowmin[0].EndTime == self.Time and \ data[symbol] != None: self.windowmin.Add(data[symbol]) self.window_hr.Add(data[symbol]) self.Debug("I am GETTING DATA") self.Debug(str(symbol)) self.Debug("Windows ready one") currBar = self.window_hr[0].Close close_of_previous_bar = self.window_hr[1].Close self.Log(f"Latest `window` close for {symbol}: {close_of_previous_bar}") currMinCloseBar = self.windowmin[0].Close close_of_previous_Min_bar = self.windowmin[1].Close currema = self.emaWindow[0] # Current ema had index zero. pastema = self.emaWindow[self.emaWindow.Count-1] # Oldest ema has index of window count minus 1. self.Log("ema: {0} -> {1} ... {2} -> {3}".format(pastema.Time, pastema.Value, currema.Time, currema.Value)) currrsi = self.rsiWindow[0] # Current rsi had index zero. pastrsi = self.rsiWindow[self.rsiWindow.Count-1] # Oldest rsi has index of window count minus 1. currBBUpW = self.BB1UpperWindow[0] # Current bbup had index zero. pastBBUpW = self.BB1UpperWindow[self.BB1UpperWindow.Count-1] # Oldest bbup has index of window count minus 1. currBBlW = self.BB1LowerWindow[0] # Current bbdown had index zero. pastBBlW = self.BB1LowerWindow[self.BB1LowerWindow.Count-1] # Oldest bbdown has index of window count minus 1. self.diplus = self.ADX_hr.PositiveDirectionalIndex.Current.Value self.diminus = self.ADX_hr.NegativeDirectionalIndex.Current.Value if not (self.Portfolio.Invested and currema.Value > pastema.Value and self.diplus > self.ADXtresh): if currrsi.Value < 30 and \ currMinCloseBar > currBBUpW: self.SetHoldings(symbol, 0.5) self.SetInitialStopsBuys() if not (self.Portfolio.Invested and currema.Value < pastema.Value and self.diminus > self.ADXtresh): if currrsi.Value > 70 and \ currMinCloseBar < currBBlW: self.SetHoldings(symbol, -0.5) self.SetInitialStopsSells() # Add and remove stocks whenever we have changes to our universe def OnSecuritiesChanged(self, changes): self._changes = changes for security in changes.AddedSecurities: symbol = security.Symbol # For 5 minute quotes if symbol not in self.MinData: self.MinData[symbol] = SymbolData(self, symbol) # For daily quotes if symbol not in self.dayMinData: self.dayMinData[symbol] = DaySymbolData(self, symbol) '''for security in changes.RemovedSecurities: symbol = security.Symbol if symbol in self.MinData: #self.Data: symbolData = self.MinData.pop(symbol, None) self.SubscriptionManager.RemoveConsolidator(symbol, symbolData.fiveMinutesConsolidator) if symbol in self.DayMinData: #self.Data: symbolData = self.DayMinData.pop(symbol, None) self.SubscriptionManager.RemoveConsolidator(symbol, symbolData.HourConsolidator)''' ##__________5 min Quotes ______## class SymbolData: def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.windowmin = RollingWindow[QuoteBar](20) fiveMinutesConsolidator = QuoteBarConsolidator(timedelta(minutes=5)) fiveMinutesConsolidator.DataConsolidated += self.fiveMinutesBarHandler algorithm.SubscriptionManager.AddConsolidator(symbol, fiveMinutesConsolidator)# Register consolidator to get automatically updated with minute data ## Create nd Add Indicators to rolling window self.ema = ExponentialMovingAverage(symbol, 20) self.ema.Updated += self.emaUpdated algorithm.RegisterIndicator(symbol, self.ema, fiveMinutesConsolidator) self.emaWindow = RollingWindow[IndicatorDataPoint](21) self.rsi = RelativeStrengthIndex(symbol, 14) self.rsi.Updated += self.RsiUpdated algorithm.RegisterIndicator(symbol, self.rsi, fiveMinutesConsolidator) self.rsiWindow = RollingWindow[IndicatorDataPoint](21) self.macd3 = MovingAverageConvergenceDivergence(3, 6, MovingAverageType.Exponential) algorithm.RegisterIndicator(symbol, self.macd3, fiveMinutesConsolidator) algorithm.SubscriptionManager.AddConsolidator(symbol, fiveMinutesConsolidator) # -------------BB bands_________________# self.BB1 = BollingerBands(20, 2) self.BB1UpperWindow=RollingWindow[float](20) self.BB1LowerWindow=RollingWindow[float](20) self.BB1.Updated+=self.BB1Updated algorithm.RegisterIndicator(symbol, self.BB1, fiveMinutesConsolidator) # Update Indicator Windows def emaUpdated(self, sender, updated): '''Adds updated values to rolling window''' if self.ema.IsReady: self.emaWindow.Add(updated) def RsiUpdated(self, sender, updated): if self.rsi.IsReady: self.rsiWindow.Add(updated)# Add updated indicator data to rolling window def BB1Updated(self, sender, updated): self.BB1UpperWindow.Add(sender.UpperBand.Current.Value) self.BB1LowerWindow.Add(sender.LowerBand.Current.Value) # Lock and load @property def IsReady(self): if self.ema.IsReady and self.emaWindow.IsReady and \ self.rsi.IsReady and self.rsiWindow.IsReady and \ self.BB1UpperWindow.IsReady and self.BB1LowerWindow.IsReady: return # Make sure I can get stock values in Window. def fiveMinutesBarHandler(self, sender, bar): self.windowmin.Add(bar) ''' self.algorithm.Debug(f"Data Consolidatoed for {self.symbol} \ at {bar.EndTime} with bar: {bar} and sma {self.sma} and trix {self.trix} and \ kelt {self.kelt.LowerBand}") ''' ##__________60 Mins Quotes ______## class DaySymbolData: def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol ########## INDICATORS ################################# self.window_hr = RollingWindow[QuoteBar](20) ########### CONSOLIDATORS and WINDOWS ########################### HourConsolidator = QuoteBarConsolidator(timedelta(hours=1)) #BarPeriod = TimeSpan.FromMinutes(10) HourConsolidator.DataConsolidated += self.HourBarHandler algorithm.SubscriptionManager.AddConsolidator(symbol, HourConsolidator)# Register consolidator to get automatically updated with minute data ##-------- OTHER INDICATORS ----------## self.ATR_init = AverageTrueRange(symbol, 5) self.ATR_trail = AverageTrueRange(symbol, 10) self.ATR_activate = AverageTrueRange(symbol, 15) self.ADX_hr = AverageDirectionalIndex(symbol, 10) # Lock and load @property def IsReady(self): return self.window_hr.IsReady # Make sure I can get stock values in Window. def HourBarHandler(self, sender, bar): self.window_hr.Add(bar) #self.algorithm.Debug(f"Data Consolidated for {self.symbol} \ #at {bar.EndTime} with bar: {bar} ") # ======================================================================== # Set initial stop and activation level. Called after new position opened. # ======================================================================== def SetInitialStopsBuys(self): currBar = self.window_hr[0].Close self.atrValue_init = self.ATR_init.Current.Value self.atrValue_activate = self.ATR_activate.Current.Value self.trailStopActivated = False self.initialStopLoss = currBar - (self.atrValue_init * self.initialStopCoef) self.trailActivationPrice = currBar + (self.atrValue_activate * self.activateStopCoef) #self.PlotCharts() # Plot charts for debugging def SetInitialStopsSells(self): currBar = self.window_hr[0].Close self.atrValue_initsells = self.ATR_init.Current.Value self.atrValue_activatesells = self.ATR_activate.Current.Value self.trailStopActivatedSells = False self.initialStopLossSells = currBar + (self.atrValue_initsells * self.initialStopCoef) self.trailActivationPriceSells = currBar - (self.atrValue_activatesells * self.activateStopCoef)