Overall Statistics |
Total Trades 217 Average Win 0.18% Average Loss -0.18% Compounding Annual Return 59.253% Drawdown 3.500% Expectancy 0.165 Net Profit 4.158% Sharpe Ratio 2.516 Loss Rate 41% Win Rate 59% Profit-Loss Ratio 0.99 Alpha -1.467 Beta 116.998 Annual Standard Deviation 0.15 Annual Variance 0.023 Information Ratio 2.413 Tracking Error 0.15 Treynor Ratio 0.003 Total Fees $298.31 |
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 * import numpy as np class VerticalCalibratedRegulators(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 3, 1) # Set Start Date self.SetEndDate(2019, 4, 1) self.SetCash(100000) # Set Strategy Cash # self.AddEquity("SPY", Resolution.Minute) self.__numberOfSymbols = 100 self.__numberOfSymbolsFine = 5 self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.smav = {} self.rsi = {} self.adx = {} self.atr = {} self.sma = {} self.selectedSymbols = [] self._changes = None def OnData(self, data): pass # sort the data by daily dollar volume and take the top 'NumberOfSymbols' def CoarseSelectionFunction(self, coarse): filtered = [ x for x in coarse if x.HasFundamentalData and x.Price > 1 and x.DollarVolume > 2500000 ] sortedByDollarVolume = sorted(filtered, key=lambda x: x.DollarVolume, reverse=True) # return the symbol objects of the top entries from our sorted collection return [ x.Symbol for x in sortedByDollarVolume[:self.__numberOfSymbols] ] # sort the data by P/E ratio and take the top 'NumberOfSymbolsFine' def FineSelectionFunction(self, fine): # sort descending by P/E ratio sortedByPeRatio = sorted(fine, key=lambda x: x.ValuationRatios.PERatio, reverse=True) ## Retrieve 20 days of historical data for each symbol symbols = [x.Symbol for x in sortedByPeRatio] history = self.History(symbols, 150, Resolution.Daily) ## Iterate through symbols for symbol in symbols: ## Find hsitory for specific symbol if str(symbol) in history.index.get_level_values(0): symbolVolumeHistory = history.loc[str(symbol)] if symbolVolumeHistory.empty: self.Log("EMPTY dataframe!") ## Create SMA for symbol and register it with algorithm else: symbolSMAv = SimpleMovingAverage(50) symbolRSI = RelativeStrengthIndex(3) symbolADX = AverageDirectionalIndex(7) symbolATR = AverageTrueRange(10) symbolSMA = SimpleMovingAverage(150) ## Iterate through historical data for tuple in symbolVolumeHistory.itertuples(): bar = TradeBar(tuple.Index, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume) ## Update SMA with data time and volume symbolSMAv.Update(tuple.Index, tuple.volume) #self.Debug(f'Updating {symbol.Value} SMA...') symbolRSI.Update(tuple.Index, tuple.close) symbolADX.Update(bar) symbolATR.Update(bar) symbolSMA.Update(tuple.Index, tuple.close) self.Log(f'{symbol.Value} ADX: {symbolADX.Current.Value}') self.Log(f'{symbol.Value} ATR: {symbolATR.Current.Value}') ## Add SMA to dictionary so you can access it later self.smav[symbol] = symbolSMAv self.rsi[symbol] = symbolRSI self.adx[symbol] = symbolADX self.atr[symbol] = symbolATR self.sma[symbol] = symbolSMA #self.Debug(f' {symbol.Value} Price ' + str(symbolVolumeHistory['close'][-1]) + 'SMA' + str(self.sma[symbol])) else: symbols.pop(symbols.index(symbol)) ## Perform SMA filtering conditions and select/return the symbols you want to add to your universe ## Fine Selection will use only these ones self.selectedSymbols = [ x for x in symbols if self.smav[x].Current.Value > 500000 and self.rsi[x].Current.Value < 30 and history.loc[str(x)]['close'][-1] > self.sma[x].Current.Value ] return self.selectedSymbols def OnData(self, data): # if we have no changes, do nothing if self._changes is None: return # liquidate removed securities for security in self._changes.RemovedSecurities: if security.Invested: self.Liquidate(security.Symbol) # we want 20% allocation in each security in our universe for security in self._changes.AddedSecurities: self.SetHoldings(security.Symbol, 0.1) self._changes = None # this event fires whenever we have changes to our universe def OnSecuritiesChanged(self, changes): self._changes = changes