Hello my beloved community, 

I need serious help that may be easy for someone moderately well endowed in Python to help me out with. I am a beginner who is new to universe selection and doesn't understand classes very well. 

Questions - I have no idea to how to make OnData, Consolidated functions, Scheduled events, inclusive to my universe that is changing every day with a different amount of symbols potentially each day. I am very new 

Strategy - I want this algorithm to filter by volume, and then by which of those stocks have had earnings report recently, then some sort of buy logic. 

Buy Logic - The buy logic contains a consolidated data function where two variables are assigned every day.  The OnData method is going to check price every minute relative to the two variables declared shortly after market open

Here is the code just in case it does not show up without a backtest attached. 

  1. #region imports
  2. from AlgorithmImports import *
  3. #endregion
  4. class EarningsORB(QCAlgorithm):
  5. def Initialize(self):
  6. self.SetStartDate(2023, 2, 2)
  7. self.SetEndDate(2023, 2, 5)
  8. self.SetCash(100000)
  9. # Scheduled events
  10. self.Schedule.On(self.DateRules.EveryDay(),self.TimeRules.AfterMarketOpen(60), self.RangeToggle)
  11. self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(), self.UpdateUniverse)
  12. # Universe Selection
  13. self.AddUniverse(self.MyCoarseFilterFunction)
  14. self.volumeBySymbol = {}
  15. self.symbols = []
  16. # Toggles
  17. self.range_toggle = False
  18. # Consolidated data
  19. # Sixty Min Bars
  20. sixty_min_consolidator = TradeBarConsolidator(timedelta(minutes=60))
  21. self.SubscriptionManager.AddConsolidator(self.symbol.Symbol, sixty_min_consolidator)
  22. sixty_min_consolidator.DataConsolidated += self.OnSixtyMinBar
  23. self.sixtyMinBarWindow = RollingWindow[TradeBar](1)
  24. def MyCoarseFilterFunction(self, coarse):
  25. # Price above 10 and dollar volume above 10mil
  26. filtered = [ x for x in coarse if x.Price > 10 and x.DollarVolume > 10000000 ]
  27. # Adds to VolumeBySymbol Dictionary
  28. for x in filtered:
  29. if x.Symbol not in self.volumeBySymbol:
  30. self.volumeBySymbol[x.Symbol] = SymbolData(x.Symbol, self)
  31. self.volumeBySymbol[x.Symbol].Update(x.EndTime, x.Volume)
  32. # Filter based on recent earnings report - This is where the filter logic would go, this is example code, it is not correct
  33. # Maybe this is where the 'estimize' code is supposed to go?
  34. self.symbols = []
  35. for symbol in self.volumeBySymbol.keys():
  36. last_report_date = self.Fundamentals.GetLastReport(symbol).ReportDate
  37. if (self.Time - last_report_date).days <= 1: # Only include symbols with earnings report in the last day
  38. self.symbols.append(symbol)
  39. # Log
  40. symbol_strings = [str(symbol.Value) for symbol in self.symbols]
  41. self.Log(f"Symbols with recent earnings reports: {symbol_strings}")
  42. return self.symbols
  43. # Scheduled events
  44. def UpdateUniverse(self):
  45. # Refresh universe
  46. self.RemoveSecurity(self.symbols)
  47. self.AddUniverse(self.MyCoarseFilterFunction)
  48. def RangeToggle(self):
  49. self.range_toggle = True
  50. # Consolidated Data
  51. def OnSixtyMinBar(self, sender, bar):
  52. self.sixtyMinBarWindow.Add(bar)
  53. if not self.sixtyMinBarWindow.IsReady:
  54. return
  55. # VARIABLES - HIGHS - LOWS
  56. trigger_bar = self.sixtyMinBarWindow[0]
  57. if self.range:
  58. self.trigger_sixty_min_open = trigger_bar.Open
  59. self.trigger_sixty_min_close = trigger_bar.Close
  60. self.range = False
  61. # Buy Logic
  62. def OnData(self, data):
  63. # Check buy criteria every minute
  64. for symbol in self.symbols:
  65. # Enter long when it crosses sixty min high
  66. if self.Securities[symbol].Price > self.trigger_sixty_min_close[symbol]: # am i supposed to add [symbol] there? Do i add [symbol] anywhere else? Like in the consolidated data function?
  67. self.SetHoldings(symbol, 1 / len(self.symbols))
  68. # Symbol Data class
  69. class SymbolData:
  70. def __init__(self, symbol, algo):
  71. self.algo = algo
  72. self.symbol = symbol
  73. self.sma = SimpleMovingAverage(30)
  74. history = algo.History(symbol, 30, Resolution.Daily)
  75. if not history.empty:
  76. for time, row in history.loc[symbol].iterrows():
  77. self.sma.Update(time, row['volume'])
  78. def Update(self, time, vol):
  79. self.sma.Update(time, vol)
+ Expand

 

Thank you for taking the time to read this and maybe help me out as usual. 

Best, 

Jesse

Author

Jesse Fleming

March 2023