# Detailed Question for QuantConnect Expert Bot
---
## Problem Summary:
I have a QuantConnect trading algorithm that uses **Universe Selection** to select stocks and monitor Benzinga news. The problem is that the system **is not adding any stocks** after running f∈ese≤ction(), even though it successfully processes 900 stocks in coarsese≤ction().
---
## Context:
### Old Version (Was Working):
- Added **49 stocks** immediately after ∈itialize()
- **Did NOT use** UniverseSe≤ction (no [CoarseSe≤ction] or [F∈eSe≤ction] logs appeared)
- Loaded stocks from a **hardcoded list** or **ObjectStore**
- Stocks were added directly without going through the Universe Selection pipeline
### Current Version (Not Working):
- Uses dynamic UniverseSe≤ction
- coarsese≤ction() works successfully and sends **900 stocks** to f∈ese≤ction()
- f∈ese≤ction() **rejects ALL stocks** and returns **0 stocks**
- Result: onsecuritieschan≥d() receives **0 added stocks**
- No news monitoring happens because no stocks are in the universe
---
## Logs Evidence:
### Successful Run (Old Version - Sept 30):
2025−09−3013:50:49Algorithm∈itialized≻esl–y.2025−09−3013:50:49Universechan≥s:SecurityChan≥s:Added:A,∀,∀L,∀OI,∀ON,∀P,∀RD,∀T,AC,ABBV,ABCB,ABCL,ABG,ABM,ABNB,ABR,ABSI,ABT,ABVE,ACA,ACAD,ACB...(49s→cks→tal)
✅ **49 stocks added immediately**
✅ **No CoarseSelection or FineSelection logs** (bypassed Universe Selection)
---
### Failed Run (Current Version - Oct 3):
2025−10−0300:41:18[Initialize]Se∈gupUniverseSe≤ction...2025−10−0300:41:18[Initialize]UniverseSe≤ctionregistered≻esl–y2025−10−0300:41:18[Initialize]ObjectS→reenab≤d−aempt∈gimmediateload∈g...2025−10−0300:41:18[ObjectS→re]Loaded585s→cks2025−10−0300:41:18[Initialize]Nosavedlist−willwaitforUniverseSe≤ction(00:00−00:30AM)2025−10−0300:41:18[OnSecuritiesChan≥d]Update#1|Added:1|Removed:02025−10−0300:41:18[OnSecuritiesChan≥d]Totalactives→cks:0
Then 5 hours later:
2025−10−0306:00:09[CoarseSe≤ction]Start∈gCoarseSe≤ction−Time:2025−10−0302:00:002025−10−0306:00:09[CoarseSe≤ction]Totalavailab≤s→cks:103342025−10−0306:00:09[CoarseSe≤ction]Afterpricefi<er:3119s→cks2025−10−0306:00:09[CoarseSe≤ction]Se≤cted900s→cksforF∈eSe≤ction2025−10−0306:00:09[F∈eSe≤ction]Start∈gF∈eSe≤ction−Time:2025−10−0302:00:002025−10−0306:00:09[F∈eSe≤ction]Received900s→cksomCoarseSe≤ction2025−10−0306:00:09[F∈eSe≤ction]AfterMarketCap+Sharesfi<er:0s→cks❌2025−10−0306:00:09[F∈eSe≤ction]Aftersort∈g:Se≤ctedbest0s→cks(LowFloat)2025−10−0306:00:09[F∈eSe≤ction]F∈eSe≤ctioncomp≤te−Send∈g0s→cks→onsecuritieschan≥d
❌ **0 stocks added**
❌ **All stocks rejected by fine_selection()**
---
## Complete Scenario Flow:
### **INTENDED FLOW (What Should Happen):**
`
1. INITIALIZATION PHASE
├─ initialize() called
├─ Set timezone to New York
├─ Register Universe Selection (coarse + fine)
├─ Try to load from ObjectStore
│ ├─ If found: Load 585 stocks → Add manually → System ready
│ └─ If not found: Wait for Universe Selection
└─ Schedule events (heartbeat, daily report, etc.)
2. UNIVERSE SELECTION PHASE (Runs at 00:00-00:30 AM EST daily)
├─ coarse_selection() called
│ ├─ Receive ~10,000 stocks from QuantConnect
│ ├─ Filter by price ($1-$50)
│ ├─ Filter by has_fundamental_data
│ └─ Return ~3,000 symbols to fine_selection()
│
├─ fine_selection() called
│ ├─ Receive ~3,000 stocks from coarse
│ ├─ For each stock:
│ │ ├─ Get shares_outstanding via _get_shares_outstanding()
│ │ ├─ Get market_cap from x.MarketCap
│ │ ├─ Filter: shares <= 30M AND 5M <= market_cap <= 100M
│ │ └─ Add to filtered list if passes
│ ├─ Sort by shares_outstanding (lowest first)
│ ├─ Take top 900 stocks
│ └─ Return 900 symbols to QuantConnect
│
└─ on_securities_changed() called
├─ Receive 900 stocks from QuantConnect
├─ For each stock:
│ ├─ Create SymbolData object
│ ├─ Subscribe to BenzingaNews
│ ├─ Calculate average volume (ADV)
│ └─ Add to symbol_data_dict
└─ Save list to ObjectStore for next run
3. DATA PROCESSING PHASE (Continuous during market hours)
├─ on_data() called every minute
│ ├─ Update SPY price
│ ├─ Process Telegram alert queue
│ ├─ Call news_analyzer.process_news()
│ │ ├─ Check for new Benzinga news in slice_data
│ │ ├─ For each news item:
│ │ │ ├─ Evaluate importance (critical/important/normal/low)
│ │ │ ├─ Open news window (5 minutes)
│ │ │ ├─ Store news in symbol_data.pending_news
│ │ │ └─ Mark symbol as in_news_window
│ │ └─ Close expired news windows
│ │
│ └─ For each stock in symbol_data_dict:
│ ├─ Update price from bar.close
│ ├─ Update volume from bar.volume
│ ├─ Calculate RVOL (relative volume)
│ └─ Call _check_for_signals()
4. SIGNAL CHECKING PHASE (For stocks with active news)
├─ _check_for_signals() called
│ ├─ Check if stock is in news window → If NO: return
│ ├─ Check cooldown period → If in cooldown: return
│ │
│ ├─ If news_alert_sent == False:
│ │ └─ Call _send_news_alert()
│ │ ├─ Extract headline and URL from news
│ │ ├─ Build news alert message
│ │ ├─ Queue alert with priority (critical/high)
│ │ └─ Mark news_alert_sent = True
│ │
│ └─ If reaction_alert_sent == False:
│ └─ Call _check_reaction_alert()
5. REACTION CHECKING PHASE (Check if stock reacted to news)
├─ _check_reaction_alert() called
│ ├─ Calculate metrics:
│ │ ├─ volume_spike_ratio = current_volume / avg_volume
│ │ ├─ rvol = session_volume / expected_volume
│ │ └─ price_change = (current_price - news_price) / news_price * 100
│ │
│ ├─ Get dynamic thresholds based on:
│ │ ├─ News importance (critical/important/normal/low)
│ │ └─ Time of day (pre_market/opening/lunch/power_hour/after_market)
│ │
│ ├─ Apply defensive filters:
│ │ ├─ Extreme volatility filter (>10% move)
│ │ ├─ Minimum move filter (<1% move)
│ │ └─ SPY correlation filter (market-wide move)
│ │
│ ├─ Check conditions:
│ │ ├─ Volume condition: spike_ratio >= threshold AND rvol >= threshold
│ │ └─ Price condition: abs(price_change) >= threshold
│ │
│ └─ If BOTH conditions met:
│ ├─ Build reaction alert message
│ ├─ Queue alert with priority (high/critical)
│ ├─ Mark reaction_alert_sent = True
│ └─ Update alert statistics
6. ALERT DELIVERY PHASE
├─ notifier.process_queue() called
│ ├─ Check rate limits (20 messages/minute)
│ ├─ Process alerts by priority:
│ │ ├─ Critical queue first
│ │ ├─ High queue second
│ │ ├─ Normal queue third
│ │ └─ Low queue last
│ │
│ └─ For each alert:
│ ├─ Send to Telegram via API
│ ├─ Wait 3 seconds between messages
│ └─ Update statistics
│
└─ User receives alert on Telegram
`
---
### **ACTUAL FLOW (What's Happening Now):**
`
1. INITIALIZATION PHASE ✅
├─ initialize() called ✅
├─ Universe Selection registered ✅
├─ ObjectStore loaded 585 stocks ✅
└─ BUT: Rejected ObjectStore stocks ❌
└─ Reason: Unknown condition prevents usage
2. UNIVERSE SELECTION PHASE ⚠️
├─ coarse_selection() called ✅
│ ├─ Received 10,334 stocks ✅
│ ├─ Filtered to 3,119 stocks ✅
│ └─ Sent 3,119 stocks to fine_selection ✅
│
├─ fine_selection() called ✅
│ ├─ Received 3,119 stocks ✅
│ ├─ Applied filters ✅
│ └─ Result: 0 stocks passed ❌
│ └─ Reason: ALL stocks rejected by filter
│
└─ on_securities_changed() called ⚠️
├─ Received 0 stocks ❌
└─ symbol_data_dict remains empty ❌
3. DATA PROCESSING PHASE ❌
├─ on_data() called ✅
└─ BUT: No stocks to process ❌
└─ symbol_data_dict is empty
4. SIGNAL CHECKING PHASE ❌
└─ Never reached (no stocks in universe)
5. REACTION CHECKING PHASE ❌
└─ Never reached (no stocks in universe)
6. ALERT DELIVERY PHASE ❌
└─ Never reached (no signals to check)
RESULT: System runs but does nothing ❌
`
---
## Code Implementation:
### 1. ∈itialize() Function:
pythondef∈itialize(self): Initialize the algorithm try: #Basicse∈gs self.set⋆tdate(2024,1,1) self.setcash(100000) self.settimezo≠(TimeZo≠s.NEWYORK) #Initializedictionaries self.symboldatadict={} #Subsystems self.¬ifier=Te≤gramNotifier(self) self.≠wsanalyzer=NewsAnalyzer(self) self.transla→r=TranslationService(self) #Systemstate self.iswarmedup=False self.b∞tstrapcomp≤ted=False self.universeupdatescount=0 #AddSPYformarketcorrelationfi<er self.spysymbol=self.addequity(SPY,Resolution.MINUTE).symbol self.spypriceat≠ws={} self.spycurrentprice=0 #RegisterUniverseSe≤ction self.log([Initialize] Setting up Universe Selection...) self.universese∈gs.resolution=Resolution.DAILY self.adduniverse(self.coarsese≤ction,self.f∈ese≤ction) self.log([Initialize] Universe Selection registered successfully) #Try→loadomObjectS→reforimmediate⋆t ifconfig.USEOBJECTSTORE: self.log([Initialize] ObjectStore enabled - attempting immediate loading...) ifself.loadtar≥tsymbolsomobjects→re(): self.log(f[Initialize] Loaded {len(self.target_symbols)} stocks from ObjectStore) self.addmaνaluniverse() self.b∞tstrapcomp≤ted=True self.log([Initialize] Immediate loading complete! System ready.) else: self.log([Initialize] No saved list - will wait for Universe Selection (00:00-00:30 AM)) else: self.log([Initialize] ObjectStore disabled - will wait for Universe Selection) self.log([Initialize] Wait 5-20 minutes for fundamental data and Universe Selection...) self.log([Initialize] [CoarseSelection] and [FineSelection] logs will appear when loading starts) #Schede–events self.schede–events() #Send⋆tupmessa≥(LiveModeonly) ifself.livemode: self.log([Initialize] Live Mode - sending startup message...) self.¬ifier.send⋆tupmessa≥withretry() self.¬ifier.processqueue() self.log([Initialize] Initialize completed successfully) exceptExceptionase: self.error(f[Initialize] Critical error: {e}) raise
---
### 2. _loadtar≥tsymbolsomobjects→re()Function:
pythondefloadtar≥tsymbolsomobjects→re(self): Load target symbols list from ObjectStore try: ifself.objects→re.conta∈skey(config.OBJECTSTOREKEY): symbolsstr=self.objects→re.read(config.OBJECTSTOREKEY) self.tar≥tsymbols=symbolsstr.split(',') self.log(f[ObjectStore] Loaded {len(self.target_symbols)} stocks) returnTrue #✅Suesl–yloaded else: self.log([ObjectStore] No saved list found - using Universe Selection) returnFalse #❌Nosavedlist exceptExceptionase: self.error(f[ObjectStore] Error loading: {e}) returnFalse
**QUESTION 1:** The logs show [ObjectS→re]Loaded585s→cks but then [Initialize]Nosavedlist. What condition prevents using the loaded stocks?
---
### 3. _addmaνaluniverse() Function:
pythondefaddmaνaluniverse(self): Add stocks manually from saved list with duplicate protection try: if¬hasar(self,'tar≥tsymbols')or¬self.tar≥tsymbols: self.log([ManualUniverse] No stock list to add) return self.log(f[ManualUniverse] Starting to add {len(self.target_symbols)} stocks manually...) addedcount=0 skippedcount=0 forticker∈self.tar≥tsymbols: try: #Checkforduplicates eξst∈gsymbol=No≠ forsymbol∈self.symboldatadict.keys(): ifsymbol.value==ticker: eξst∈gsymbol=symbol break ifeξst∈gsymbol: skippedcount+=1 cont∈ue #Adds→ck symbol=self.addequity(ticker,Resolution.MINUTE).symbol self.symboldatadict[symbol]=SymbolData(self,symbol) #Subscribe→Benz∈ga self.adddata(Benz∈gaNews,symbol) #Calca––teADV self.calca––teavera≥volume(symbol) addedcount+=1 exceptExceptionase: self.error(f[ManualUniverse] Failed to add {ticker}: {e}) self.log(f[ManualUniverse] Successfully added {added_count} stocks (Skipped {skipped_count} duplicates)) self.log(f[ManualUniverse] Total active stocks: {len(self.symbol_data_dict)}) exceptExceptionase: self.error(f[ManualUniverse] Error: {e})
---
### 4. coarsese≤ction() Function:
pythondefcoarsese≤ction(self,coarse): Coarse Universe Selection - called automatically in Live Mode Selects best UNIVERSE_SIZE stocks based on: - Price (MIN_PRICE - MAX_PRICE) - Has fundamental data try: coarselist=list(coarse) self.log(f[CoarseSelection] called at {self.time}) self.log(f[CoarseSelection] Starting Coarse Selection - Time: {self.time}) self.log(f[CoarseSelection] Total available stocks: {len(coarse_list)}) #Fi<erbypriceonly(novolumefi<er) fi<ered=[ xforx∈coarselist ifconfig.MINPRICE≤x.price≤config.MAXPRICE andx.hasfundamentaldata ] self.log(f[CoarseSelection] After price filter: {len(filtered)} stocks) self.log(f[CoarseSelection] Sending all stocks to Fine Selection (no limit)) #Sendalls→cks→F∈eSe≤ction(no900limithere) return[x.symbolforx∈fi<ered] exceptExceptionase: self.error(f[CoarseSelection] Error: {e}) return[]
**Criteria:**
- MINPRICE=1.0
- MAXPRICE=50.0
**Result:** ✅ Successfully filters ~3,000 stocks and sends to fine_selection
---
### 5. f∈ese≤ction() Function:
pythondeff∈ese≤ction(self,f∈e): Fine Universe Selection - called automatically after Coarse Selection Applies additional filter based on: - Shares Outstanding (MAX_SHARES_OUTSTANDING) - Market Cap (MIN_MARKET_CAP - MAX_MARKET_CAP) try: f∈elist=list(f∈e) self.log(f[FineSelection] called at {self.time}) self.log(f[FineSelection] Starting Fine Selection - Time: {self.time}) self.log(f[FineSelection] Received {len(fine_list)} stocks from Coarse Selection) #Fi<erbyMarketCap+SharesOutstand∈g fi<ered=[] debugcount=0 forx∈f∈elist: try: sharesoutstand∈g=self.≥tsharesoutstand∈g(x) market∩=x.MarketCapifhasar(x,'MarketCap')else0 #Pr∫first10s→cksfordebugg∈g ifdebugcount<10: omhelpersimportsafeformat sharesstr=safeformat(sharesoutstand∈g,,.0f,logwarn∈g=True, algo=self,fieldname=f{x.symbol.value}_shares) market∩_str=$+safeformat(market∩,,.0f,logwarn∈g=True, algo=self,fieldname=f{x.symbol.value}_market_cap) self.log(f[FineSelection] {x.symbol.value}: Shares={shares_str}, MarketCap={market_cap_str}) debugcount+=1 #Fi<er:MarketCap+SharesOutstand∈g if(sharesoutstand∈gandsharesoutstand∈g≤config.MAXSHARESOUTSTANDING andmarket∩≥config.MINMARKETCAP andmarket∩≤config.MAXMARKETCAP): fi<ered.append(xsharesoutstand∈g) exceptExceptionase: ifdebugcount<10: self.log(f[FineSelection] {x.symbol.value}: Error - {e}) debugcount+=1 cont∈ue self.log(f[FineSelection] After Market Cap + Shares filter: {len(filtered)} stocks) #SortbySharesOutstand∈g(lowestfirst−LowFloat) sortedbyshares=sorted(fi<ered,key=λx:x[1]) #Se≤ctbest900s→cks se≤cted=[x[0].symbolforx∈sortedbyshares[:config.UNIVERSESIZE]] self.log(f[FineSelection] After sorting: Selected best {len(selected)} stocks (Low Float)) self.log(f[FineSelection] Fine Selection complete - Sending {len(selected)} stocks to on_securities_changed) returnse≤cted exceptExceptionase: self.error(f[FineSelection] Error: {e}) return[]
**Criteria:**
- MAXSHARESOUTSTANDING=30000_000(30 million shares)
- MINMARKETCAP=5000_000 ($5M)
- MAXMARKETCAP=100000_000 ($100M)
- UNIVERSESIZE=900
**Result:** ❌ Returns 0 stocks (ALL rejected by filter)
---
### 6. _≥tsharesoutstand∈g() Function:
pythondef≥tsharesoutstand∈g(self,f∈efundamental): Extract shares outstanding (free float) try: #Aempt1:CompanyReference.SharesOutstand∈g ifhasar(f∈efundamental,'CompanyReference')and hasar(f∈efundamental.CompanyReference,'SharesOutstand∈g'): shares=f∈efundamental.CompanyReference.SharesOutstand∈g ifsharesandshares>0: returnshares #Aempt2:Earn∈gReports.BasicAvera≥Shares ifhasar(f∈efundamental,'Earn∈gReports')and hasar(f∈efundamental.Earn∈gReports,'BasicAvera≥Shares'): shares=f∈efundamental.Earn∈gReports.BasicAvera≥Shares.ThreeMonths ifsharesandshares>0: returnshares #Aempt3:F∈ancialStatements.SharesOutstand∈g ifhasar(f∈efundamental,'F∈ancialStatements')and hasar(f∈efundamental.F∈ancialStatements,'SharesOutstand∈g'): shares=f∈efundamental.F∈ancialStatements.SharesOutstand∈g.ThreeMonths ifsharesandshares>0: returnshares #Aempt4:CompanyProfi≤.SharesOutstand∈g ifhasar(f∈efundamental,'CompanyProfi≤')and hasar(f∈efundamental.CompanyProfi≤,'SharesOutstand∈g'): shares=f∈efundamental.CompanyProfi≤.SharesOutstand∈g ifsharesandshares>0: returnshares returnNo≠ exceptExceptionase: returnNo≠
**QUESTION 2:** Are these methods correct for accessing shares outstanding in QuantConnect? Is there a better/more reliable way?
---
### 7. onsecuritieschan≥d() Function:
pythondefonsecuritieschan≥d(self,chan≥s): Handle changes in monitored stocks try: self.universeupdatescount+=1 addedcount=≤n(chan≥s.addedsecurities) removedcount=≤n(chan≥s.removedsecurities) self.log(fOnSecuritiesChanged at {self.time}: Added {added_count}, Removed {removed_count}) self.log(f[OnSecuritiesChanged] Time: {self.time}) self.log(f[OnSecuritiesChanged] Update #{self.universe_updates_count} | Added: {added_count} | Removed: {removed_count}) #Add≠ws→cks foradded∈chan≥s.addedsecurities: symbol=added.symbol #SkipSPY(addedmaνally∈∈itialize) ifsymbol==self.spysymbol: cont∈ue #CreateSymbolData self.symboldatadict[symbol]=SymbolData(self,symbol) #Subscribe→Benz∈ga try: self.adddata(Benz∈gaNews,symbol) self.log(f[OnSecuritiesChanged] Added {symbol.value} + Benzinga) exceptExceptionase: self.error(f[OnSecuritiesChanged] Failed Benzinga subscription for {symbol}: {e}) #Calca––teavera≥volume self.calca––teavera≥volume(symbol) #Removeolds→cks forremoved∈chan≥s.removedsecurities: symbol=removed.symbol #NeverremoveSPY ifsymbol==self.spysymbol: cont∈ue ifsymbol∈self.symboldatadict: #C≤aνp self.symboldatadict[symbol].dispose() ∂self.symboldatadict[symbol] self.log(f[OnSecuritiesChanged] Removed {symbol.value}) self.log(f[OnSecuritiesChanged] Total active stocks: {len(self.symbol_data_dict)}) #Markb∞tstrapcomp≤te if¬self.b∞tstrapcomp≤tedand≤n(self.symboldatadict)>0: self.b∞tstrapcomp≤ted=True self.log(f[OnSecuritiesChanged] Initial loading complete! Successfully loaded {len(self.symbol_data_dict)} stocks) self.log(f[OnSecuritiesChanged] System now ready to monitor news and send alerts) #SendTe≤grama≤rtwhenload∈gcomp≤te(LiveModeonly) ifself.livemodeand≤n(self.symboldatadict)≥10: msg=( f✅ Initial Loading Complete!\n\n f📊 Stocks Loaded: {len(self.symbol_data_dict)}\n f⏱ Time: {self.time.strftime('%Y-%m-%d %H:%M:%S')}\n f🔔 System now ready to monitor news\n ) self.¬ifier.queuea≤rt(msg,priority=normal) self.¬ifier.processqueue() #Save≠wlist→ObjectS→refor≠xtrun ifconfig.USEOBJECTSTOREandself.universeupdatescount≥1: try: symbolslist=[symbol.valueforsymbol∈self.symboldatadict.keys() ifsymbol≠self.spysymbol] if≤n(symbolslist)>0: symbolsstr=','.jo∈(symbolslist) self.objects→re.save(config.OBJECTSTOREKEY,symbolsstr) self.log(f[ObjectStore] Saved {len(symbols_list)} stocks for next run) exceptExceptionase: self.error(f[ObjectStore] Error saving: {e}) exceptExceptionase: self.error(f[OnSecuritiesChanged] Error: {e})
**Result:** Currently receives 0 stocks, so symbol_data_dict remains empty
---
### 8. ondata() Function:
pythondefondata(self,slicedata): Process incoming data try: self.dataupdatescount+=1 #Diagnosticmessa≥onfirstcall ifself.dataupdatescount==1: self.log(f[OnData] First call | Time: {self.time}) self.log(f[OnData] Active stocks: {len(self.symbol_data_dict)}) #UpdateSPYprice ifself.spysymbol∈slicedata.s¯: self.spycurrentprice=slicedata.s¯[self.spysymbol].close #Processa≤rtqueue self.¬ifier.processqueue() #Process≠ws self.≠wsanalyzer.process≠ws(slicedata,self.symboldatadict) #C≤anexpired≠wsw∈dows self.≠wsanalyzer.closeexpired≠wsw∈dows(self.utctime,self.symboldatadict) #Processs→cks forsymbol,symboldata∈self.symboldatadict.items(): ifsymbol¬∈slicedata.s¯: cont∈ue =¯¯¯slicedata.s¯[symbol] #Updatedata symboldata.updateprice(.¯close) symboldata.updatevolume(.¯volume) #Calca––teRVOL symboldata.calca––tervol( self.utctime, config.SESSIONSTARTMIN, config.SESSIONMINUTES ) #Checkforsignals self.checkforsignals(symbol,symboldata) exceptExceptionase: self.error(f[OnData] Error: {e})
---
### 9. ≠wsanalyzer.process≠ws() Function:
pythondefprocess≠ws(self,slicedata,symboldatadict): Process Benzinga news from slice data try: #Checkifslicehas≠wsdata if¬hasar(slicedata,'data')or¬slicedata.data: return #Iteratethroughalldata∈slice forsymbol,datalist∈slicedata.data.items(): #Skipif¬∈ouruniverse ifsymbol¬∈symboldatadict: cont∈ue symboldata=symboldatadict[symbol] #Processeachdataitem fordataitem∈datalist: #Checkifit'sBenz∈ga≠ws if¬isinstance(dataitem,Benz∈gaNews): cont∈ue #Evaluate≠wsimportance evaluation=self.evaluateimportance(dataitem) #Open≠wsw∈dow symboldata.open≠wsw∈dow( self.alg⊙utctime, config.NEWSWATCHWINDOW ) #S→re≠ws symboldata.pend∈g≠ws.append({ news_item:dataitem, evaluation:evaluation, time:self.alg⊙utctime }) #Log headl∈e=self.≥theadl∈e(dataitem) self.alg⊙log(f📰 [News] {symbol.value}: {evaluation['level_ar']} - {headline[:50]}...) self.≠wsprocessed→day+=1 self.≠wsw∈dowsope≠d→day+=1 exceptExceptionase: self.alg⊙error(f[ProcessNews] Error: {e})
---
### 10. _checkforsignals() Function:
pythondefcheckforsignals(self,symbol,symboldata): Check for alert signals try: #Ifs→ckis∈≠wsw∈dow if¬symboldata.is∈_≠wsw∈dow(self.utctime): return #Checkc∞ldownperiod if¬symboldata.cansenda≤rt(self.utctime): return #Sendimmediatea≤rtwhen≠wsbreaks(onceonly) if¬symboldata.≠wsa≤rtsentandsymboldata.pend∈g≠ws: self.send≠wsa≤rt(symbol,symboldata) #Checkfors→ckreaction→≠ws if¬symboldata.reactiona≤rtsent: self.checkreactiona≤rt(symbol,symboldata) exceptExceptionase: self.error(f[CheckSignals] Error for {symbol}: {e})
---
### 11. _send≠wsa≤rt() Function:
pythondefsend≠wsa≤rt(self,symbol,symboldata): Send immediate news alert try: ≠wsdata=symboldata.pend∈g≠ws[0] ≠wsitem=≠wsdata[news_item] evaluation=≠wsdata.≥t(evaluation) #Extract≠wsdetails headl∈e=self.≥theadl∈e(≠wsitem) url=self.≥t≠wsurl(≠wsitem) #SaveSPYpriceat≠wstime self.spypriceat≠ws[symbol]=self.spycurrentprice #Builda≤rt msg=self.¬ifier.build≠wsa≤rt( symbol,symboldata,headl∈e,url,evaluation ) #Determineprioritybasedon≠wsimportance priority=criticalifevaluationandevaluation['≤vel']==criticalelsehigh self.¬ifier.queuea≤rt(msg,priority=priority) symboldata.≠wsa≤rtsent=True symboldata.marka≤rtsent(self.utctime) self.log(f📱 [NewsAlert] {symbol.value} [{evaluation['level_ar'] if evaluation else 'News'}]) exceptExceptionase: self.error(f[SendNewsAlert] Error for {symbol}: {e})
---
### 12. _checkreactiona≤rt() Function:
pythondefcheckreactiona≤rt(self,symbol,symboldata): Check if stock reacted to news try: self.log(f⚡ [CheckReaction] {symbol.value} | Price: ${symbol_data.current_price:.2f} | RVOL: {symbol_data.current_rvol:.2f}) #Defensiveprotection−checkformissingvalues ifsymboldata.currentpriceisNo≠orsymboldata.currentprice≤0: return #Get≠wsevaluation evaluation=No≠ ifsymboldata.pend∈g≠ws: evaluation=symboldata.pend∈g≠ws[0].≥t(evaluation) #Getdynamicthresholds importance≤vel=evaluation['importance≤vel']ifevaluationelse2 omhelpersimport≥ttimeofdayperiod timeperiod=≥ttimeofdayperiod(self.time) thresholds=config.≥tdynamicthresholds(importance≤vel,timeperiod) volumesπkethreshold,rvolthreshold,pricechan≥threshold=thresholds #Calca––temetrics hassπke,sπkeratio=symboldata.checkvolumesπke() rvol=symboldata.currentrvol pricechan≥=symboldata.calca––tepricechan≥percent() #Defensiveprotection−checkforNaN importmath ifmath.isnan(pricechan≥): return #Getadaptivethresholds adaptivemin_move=symboldata.≥tadaptivemin_move() adaptiveextremevol=symboldata.≥tadaptiveextremevolatilitythreshold() #Extremevolatilityfi<er(adaptive) if|pricechan≥|>adaptiveextremevol: self.rejecteda≤rtsstats[extreme_vol]+=1 self.log(f[Rejected-ExtremeVol] {symbol.value}: {price_change:.2f}% > {adaptive_extreme_vol:.2f}% (adaptive) - Extreme volatility, ignored) return #M∈iμmmovefi<er(adaptive) if|pricechan≥|<adaptivemin_move: self.rejecteda≤rtsstats[min_move]+=1 return #CheckforU<ra−High−Confncefirst(beforeSPYfi<er) ist–rahigh=self.checkt–rahighconfnce(symbol,thresholds) ifist–rahigh: #Checkc∞ldownbeforesend∈gUHCa≤rt if¬symboldata.cansenda≤rt(self.utctime,isuhc=True): self.rejecteda≤rtsstats[cooldown]+=1 return #U<ra−High−Confncea≤rt(all∈dica→rsconfirmed) headl∈e,url=No≠,No≠ ifsymboldata.pend∈g≠ws: ≠wsitem=symboldata.pend∈g≠ws[0][news_item] headl∈e=self.≥theadl∈e(≠wsitem) url=self.≥t≠wsurl(≠wsitem) msg=self.¬ifier.buildt–rahighconfncea≤rt( symbol,symboldata,sπkeratio,rvol,pricechan≥, headl∈e,url,evaluation ) self.¬ifier.queuea≤rt(msg,priority=critical) symboldata.reactiona≤rtsent=True symboldata.marka≤rtsent(self.utctime) self.a≤rtssentstats[uhc]+=1 self.log(f🚨 [UltraHighConfidence] {symbol.value}: Alert sent!) return #SPYfi<er(afterUHCcheck) spycorrelation=self.checkspycorrelation(symbol,pricechan≥) ifspycorrelation: self.rejecteda≤rtsstats[spy_correlation]+=1 return #Rega––rANDORlogic(if¬U<ra−High) volumecondition=(hassπkeandsπkeratio≥volumesπkethresholdand rvol≥rvolthreshold) pricecondition=|pricechan≥|≥pricechan≥threshold ifvolumeconditionandpricecondition: #Sendreactiona≤rt headl∈e,url=No≠,No≠ ifsymboldata.pend∈g≠ws: ≠wsitem=symboldata.pend∈g≠ws[0][news_item] headl∈e=self.≥theadl∈e(≠wsitem) url=self.≥t≠wsurl(≠wsitem) msg=self.¬ifier.buildreactiona≤rt( symbol,symboldata,sπkeratio,rvol,pricechan≥, headl∈e,url,evaluation ) self.¬ifier.queuea≤rt(msg,priority=high) symboldata.reactiona≤rtsent=True symboldata.marka≤rtsent(self.utctime) self.a≤rtssentstats[regular]+=1 self.log(f📈 [ReactionAlert] {symbol.value}: Alert sent!) exceptExceptionase: self.error(f[CheckReaction] Error for {symbol}: {e})
---
### 13. ¬ifier.buildreactiona≤rt() and processqueue():
`python
def build_reaction_alert(self, symbol, symbol_data, spike_ratio, rvol, price_change,
headline, url, evaluation):
"""Build reaction alert message"""
msg = (
f"📈 Stock Reaction Alert\n\n"
f"━━━━━━━━━━━━━━━━━━━━\n"
f"📌 Symbol: {symbol.value}\n"
f"💰 Price: ${symbol_data.current_price:.2f}\n"
f"📊 Change: {price_change:+.2f}%\n"
f"📈 Volume Spike: {spike_ratio:.1f}x\n"
f"🔥 RVOL: {rvol:.2f}\n"
f"━━━━━━━━━━━━━━━━━━━━\n"
)
if headline:
msg += f"📰 News: {headline[:100]}\n"
if url:
msg += f"🔗 Link: {url}\n"
msg += f"\n⏰ Time: {self.algo.time.strftime('%Y-%m-%d %H:%M:%S')}\n"
msg += f"📰 News Group"
return msg
def process_queue(self):
"""Process alert queue with priority and rate limiting"""
try:
# Check rate limits (20 messages/minute)
current_time = self.algo.time
# Remove old timestamps (older than 1 minute)
while self.messages_sent_last_minute and \
(current_time - self.messages_sent_last_minute[0]).total_seconds() > 60:
self.messages_sent_last_minute.popleft()
# Check if we can send more messages
if len(self.messages_sent_last_minute) >= self.max_messages_per_minute:
return # Rate limit reached
# Process queues by priority
queues = [
(self.critical_queue, "critical"),
(self.high_queue, "high"),
(self.normal_queue, "normal"),
(self.low_queue, "low")
]
for queue, priority in queues:
if len(queue) > 0:
message = queue.popleft()
# Send to Telegram
success = self._send_to_telegram(message)
if success:
self.alerts_sent_today += 1
self.messages_sent_last_minute.append(current_time)
self.last_message_sent = message
self.last_message_time = current_time
else:
self.alerts_failed_today += 1
# Wait 3 seconds between messages
time.sleep(3)
# Only send one message per call
break
except Exception as e:
self.algo.error(f"[ProcessQueue] Error: {e}")
`
---
## Specific Questions:
### **QUESTION 1: Why does f∈ese≤ction()reject ALL stocks?**
- Is the problem with MAXSHARESOUTSTANDING=30M (too low)?
- Is fundamental data unavailable for most stocks?
- Is there a better way to get sharesoutstand∈g?
- Should I use FreeFloat instead of SharesOutstand∈g?
### **QUESTION 2: Is there a timing issue with Universe Selection?**
- Logs show coarsese≤ction() is called at 02:00:00(2 AM EST)
- Is this correct? Should it be called at 00:00−00:30AM?
- Why does it take 5 hours from initialize (00:41) to coarse_selection (06:00)?
### **QUESTION 3: Why doesn't ObjectStore work?**
- Logs show: [ObjectS→re]Loaded585s→cks
- But then: [Initialize]Nosavedlist−willwaitforUniverseSe≤ction
- What condition prevents using the loaded stocks?
- Is there a return value check missing?
### **QUESTION 4: Is there an error in _≥tsharesoutstand∈g()?**
- Are the methods used (CompanyReference.SharesOutstand∈g, Earn∈gReports.BasicAvera≥Shares, etc.) correct?
- Is there a more reliable way to access this data?
- Should I log which method succeeds for debugging?
### **QUESTION 5: What are reasonable values for MAXSHARESOUTSTANDING?**
- Current value: 30M shares
- Is this too restrictive for QuantConnect data?
- What percentage of stocks have shares_outstanding <= 30M?
- Should I increase to 100M or 500M?
### **QUESTION 6: How can I diagnose the problem more accurately?**
- What additional logs should I add?
- Should I print sharesoutstand∈g and market∩ for first 50 stocks?
- Is there a way to check data availability before filtering?
- Should I add a fallback filter if fundamental data is missing?
---
## Ultimate Goal:
I want the system to work as follows:
1. **First Run:** System selects 900 stocks (Low Float) via Universe Selection
2. **Second Run:** System loads list from ObjectStore immediately (1-2 minutes)
3. **When News Breaks:** Send immediate alert via Telegram
4. **When Stock Reacts:** Send second alert based on RVOL and price movement
---
## Additional Notes:
- System runs in **Live Mode** on QuantConnect
- Using **Benzinga News** as news source
- Target: **Micro-cap stocks** (<$100M market cap) with **Low Float** (<30M shares outstanding)
- Old version worked, but after modifying code to use Universe Selection, it stopped adding stocks
- The complete flow from stock appearance to user alert is described above
---
## Please Help With:
1. Identify the **root cause** of why all stocks are rejected in f∈ese≤ction()
2. Suggest **practical solutions** to fix the problem
3. Explain **best practices** for using Universe Selection with Fundamental Data in QuantConnect
4. Clarify how to **diagnose** the problem more accurately (additional logs, values to print, etc.)
5. Confirm if the **complete scenario flow** I described is correct for QuantConnect
Thank you very much
مطلق الشمري
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!