I am trying to figure out why I am getting the following error: 

Runtime Error: AttributeError : 'UniverseRollingAlgorithm' object has no attribute 'universe'at OnDatafor symbol at self.universe:===at Python.Runtime.PyObject.Invoke(PyTuple args in main.py:line 97 AttributeError : 'UniverseRollingAlgorithm' object has no attribute 'universe' (Open Stacktrace) 

Ideally, this should be looking through the top 2 sectors and sort the data by P/E ratio and take the top 5 stocks within those sectors.   I then want to run TA conditions to time when to buy the stock list that is populated from the corse/fine selectors.  Can anyone please point me in the right direction here?

 

  1. from itertools import groupby
  2. class UniverseRollingAlgorithm(QCAlgorithm):
  3. def Initialize(self): #Initialize Dates, Cash, Equities, Fees, Allocation, Parameters, Indicators, Charts
  4. # Set Start Date, End Date, and Cash
  5. #-------------------------------------------------------
  6. self.SetTimeZone(TimeZones.NewYork) #EDIT: Added Timezon
  7. self.SetStartDate(2021, 1, 1) # Set Start Date
  8. # self.SetEndDate(2020, 4, 15) # Set End Date
  9. self.SetCash(100000) # Set Strategy Cash
  10. #-------------------------------------------------------
  11. # Set Custom Universe
  12. #-------------------------------------------------------
  13. self.AddUniverse(self.CoarseSelectionFilter, self.FineSelectionFilter)
  14. self.UniverseSettings.Resolution = Resolution.Minute #Needs to change to Resolution.Minute once code works, leaving Daily for now to minimize data
  15. self.UniverseSettings.SetDataNormalizationMode = DataNormalizationMode.SplitAdjusted
  16. self.UniverseSettings.FeeModel = ConstantFeeModel(0.0)
  17. self.UniverseSettings.Leverage = 1
  18. #-------------------------------------------------------
  19. # self.SetBrokerageModel(BrokerageName.Alpaca, AccountType.Cash) #EDIT: Added Brokerage, appears to have set fees to zero
  20. self.EMA_Period_Fast = 20
  21. self.EMA_Period_Slow = 50
  22. self.__numberOfSymbols = 100
  23. self.__numberOfSymbolsFine = 10
  24. self.indicators = {}
  25. # Define Percentage Allocation
  26. #-------------------------------------------------------
  27. self.percentagebuy = 0.1
  28. #-------------------------------------------------------
  29. # Sector Selectior
  30. self.numberOfSymbolsCoarse = 500
  31. self.exposureToSector = 2
  32. self.lastMonth = -1
  33. self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
  34. def CoarseSelectionFilter(self, coarse):
  35. if self.Time.month == self.lastMonth:
  36. return Universe.Unchanged
  37. self.lastMonth = self.Time.month
  38. allCoarse = [x for x in coarse if x.HasFundamentalData and x.Price > 1 and x.Volume > 1]
  39. finalCoarse = sorted(allCoarse, key = lambda x: x.DollarVolume, reverse = True)
  40. return [x.Symbol for x in finalCoarse][:self.numberOfSymbolsCoarse]
  41. #Old
  42. #sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) # sort descending by daily dollar volume
  43. #return [ x.Symbol for x in sortedByDollarVolume[:self.__numberOfSymbols] ] # return the symbol objects of the top entries from our sorted collection
  44. def FineSelectionFilter(self, fine): # sort the data by P/E ratio and take the top 'NumberOfSymbolsFine'
  45. filteredSymbols = []
  46. sortedBySector = [x for x in fine]
  47. # self.Log("ORDER NOTIFICATION >> {}".format(str(AssetClassification.MorningstarSectorCode)))
  48. for code, g in groupby(sortedBySector, lambda x: x.AssetClassification.MorningstarSectorCode):
  49. for x in sorted(g, key = lambda x: x.ValuationRatios.PERatio, reverse = True)[:self.exposureToSector]:
  50. filteredSymbols.append(x.Symbol)
  51. return filteredSymbols[:5]
  52. #Old
  53. #sortedByPeRatio = sorted(fine, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=False) # sort descending by P/E ratio
  54. #self.universe = [ x.Symbol for x in sortedByPeRatio[:self.__numberOfSymbolsFine] ] # take the top entries from our sorted collection
  55. #return self.universe
  56. def OnSecuritiesChanged(self, changes):
  57. # Create indicator for each new security
  58. for security in changes.AddedSecurities:
  59. self.indicators[security.Symbol] = SymbolData(security.Symbol, self, self.EMA_Period_Fast, self.EMA_Period_Slow)
  60. for security in changes.RemovedSecurities:
  61. if security.Invested:
  62. self.Liquidate(security.Symbol, "Universe Removed Security")
  63. if security in self.indicators:
  64. self.indicators.pop(security.Symbol, None)
  65. def OnData(self, data): #Entry Point for Data and algorithm - Check Data, Define Buy Quantity, Process Volume, Check Portfolio, Check RSI, Execute Buy/Sell orders, Chart Plots
  66. for symbol in self.universe:
  67. if not data.ContainsKey(symbol): #Tested and Valid/Necessary
  68. continue
  69. if data[symbol] is None: #Tested and Valid/Necessary
  70. continue
  71. if not symbol in self.indicators: #Tested and Valid/Necessary
  72. continue
  73. # Ensure indicators are ready to update rolling windows
  74. if not self.indicators[symbol].slow_ema.IsReady:
  75. continue
  76. # Update EMA rolling windows
  77. self.indicators[symbol].fast_ema_window.Add(self.indicators[symbol].get_fast_EMA())
  78. self.indicators[symbol].slow_ema_window.Add(self.indicators[symbol].get_slow_EMA())
  79. # Check for Indicator Readiness within Rolling Window
  80. #-------------------------------------------------------
  81. if not (self.indicators[symbol].fast_ema_window.IsReady and self.indicators[symbol].slow_ema_window.IsReady):
  82. continue #return #EDIT
  83. #EXECUTE TRADING LOGIC HERE -
  84. if self.Portfolio[symbol].Invested:
  85. # Sell condition
  86. if (self.indicators[symbol].fast_ema_window[1] >= self.indicators[symbol].slow_ema_window[1]) and (self.indicators[symbol].fast_ema_window[4] < self.indicators[symbol].slow_ema_window[4]):
  87. self.Liquidate(symbol)
  88. # Buy conditions
  89. elif self.Portfolio.MarginRemaining > 0.9 * self.percentagebuy * self.Portfolio.TotalPortfolioValue:
  90. if self.indicators[symbol].fast_ema_window[1] <= self.indicators[symbol].slow_ema_window[1] and \
  91. (self.indicators[symbol].fast_ema_window[4] > self.indicators[symbol].slow_ema_window[4]):
  92. self.buyquantity = round((self.percentagebuy*self.Portfolio.TotalPortfolioValue)/data[symbol].Close)
  93. self.MarketOrder(symbol, self.buyquantity)
  94. class SymbolData(object):
  95. rolling_window_length = 5
  96. def __init__(self, symbol, context, fast_ema_period, slow_ema_period):
  97. self.symbol = symbol
  98. self.fast_ema_period = fast_ema_period
  99. self.slow_ema_period = slow_ema_period
  100. self.fast_ema = context.EMA(symbol, self.fast_ema_period, Resolution.Minute) #, fillDataForward = True, leverage = 1, extendedMarketHours = False)
  101. self.slow_ema = context.EMA(symbol, self.slow_ema_period, Resolution.Minute) #, fillDataForward = True, leverage = 1, extendedMarketHours = False)
  102. self.fast_ema_window = RollingWindow[float](self.rolling_window_length)
  103. self.slow_ema_window = RollingWindow[float](self.rolling_window_length)
  104. # Warm up EMA indicators
  105. history = context.History([symbol], slow_ema_period + self.rolling_window_length, Resolution.Minute)
  106. for time, row in history.loc[symbol].iterrows():
  107. self.fast_ema.Update(time, row["close"])
  108. self.slow_ema.Update(time, row["close"])
  109. # Warm up rolling windows
  110. if self.fast_ema.IsReady:
  111. self.fast_ema_window.Add(self.fast_ema.Current.Value)
  112. if self.slow_ema.IsReady:
  113. self.slow_ema_window.Add(self.slow_ema.Current.Value)
  114. def get_fast_EMA(self):
  115. return self.fast_ema.Current.Value
  116. def get_slow_EMA(self):
  117. return self.slow_ema.Current.Value
+ Expand

Author

Axist

July 2021