# Follow-up Question: KeyError in Manual Indicator Warm-up & Additional Questions
Hello again,
Thank you for the excellent guidance on batch rotation and indicator management. I've implemented your recommendations, but encountered a **KeyError** during manual warm-up. I also have additional questions about best practices.
---
## Problem Encountered: KeyError in Manual Warm-up
### Error Details
`
Runtime Error: Trying to retrieve an element from a collection using a key that does not exist in that collection throws a KeyError exception.
at create_phase1_indicators
self.warm_up_indicator(symbol, self.phase1_obv_indicators[symbol], Resolution.MINUTE)
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
in main.py: line 451
at initialize_batch
self.create_phase1_indicators(symbol)
in main.py: line 382
at rotate_batch
self.initialize_batch(self.current_batch_index)
in main.py: line 423
`
### Current Implementation (Following Your Advice)
I implemented manual warm-up as you suggested:
pythondefcreatephase1∈dica→rs(self,symbol): Create Phase 1 indicators with manual warm-up (Bot recommendation #5) ∈dica→rscreated=[] try: #Checkliqutyfirst(Botrecommendation#3) his→ry=self.his→ry(symbol,max(self.RDVPERIOD,self.CMFPERIOD,5),Resolution.MINUTE) ifhis→ry.emptyor≤n(his→ry)<2: self.debug(f[SKIP-ILLIQUID] {symbol.value} | No sufficient history data) returnFalse #CreateRDVwithseparateerrorhandl∈g try: rdv=self.rdv(symbol,self.RDVPERIOD,Resolution.MINUTE) #Maνalwarm−up(Botrecommendation#5) fortime,row∈his→ry.iterrows(): if'close'∈rowandrow['close']>0: rdv.update(time,row['close']) self.phase1rdv∈dica→rs[symbol]=rdv ∈dica→rscreated.append(fRDV(ready={rdv.is_ready}, samples={rdv.samples})) exceptExceptionase: self.error(f[ERROR] Failed to create RDV for {symbol.value}: {str(e)}) #CreateCMFwithseparateerrorhandl∈g try: cmf=self.cmf(symbol,self.CMFPERIOD,Resolution.MINUTE) #Maνalwarm−up fortime,row∈his→ry.iterrows(): ifall(k∈rowfork∈['close','high','low','volume']): cmf.update(TradeBar(time,symbol,row['open'],row['high'], row['low'],row['close'],row['volume'])) self.phase1cmf∈dica→rs[symbol]=cmf ∈dica→rscreated.append(fCMF(ready={cmf.is_ready}, samples={cmf.samples})) exceptExceptionase: self.error(f[ERROR] Failed to create CMF for {symbol.value}: {str(e)}) #CreateOBVwithseparateerrorhandl∈g try: obv=self.obv(symbol,Resolution.MINUTE) #Maνalwarm−up fortime,row∈his→ry.iterrows(): ifall(k∈rowfork∈['close','volume']): obv.update(TradeBar(time,symbol,row['open'],row['high'], row['low'],row['close'],row['volume'])) self.phase1obv∈dica→rs[symbol]=obv ∈dica→rscreated.append(fOBV(ready={obv.is_ready}, samples={obv.samples})) exceptExceptionase: self.error(f[ERROR] Failed to create OBV for {symbol.value}: {str(e)}) #Logrest–s if∈dica→rscreated: self.debug(f[IndicatorCreation-IMPROVED] {symbol.value} | {', '.join(indicators_created)}) returnTrue else: self.debug(f[SKIP-NO-INDICATORS] {symbol.value} | Failed to create any indicators) returnFalse exceptExceptionase: self.error(f[ERROR] General error in create_phase1_indicators for {symbol.value}: {str(e)}) returnFalse
### Questions About the KeyError
1. **Why does the KeyError occur?**
- The error happens at line 451 which seems to be the old warmup∈dica→r() call
- But I thought I replaced all warmup∈dica→r() calls with manual warm-up
- Could there be a caching issue or is the code not fully updated?
2. **Is my manual warm-up implementation correct?**
- Am I creating TradeBar objects correctly for CMF and OBV?
- Should I use TradeBar or just pass the row directly?
- Do I need to handle missing OHLCV data differently?
3. **Should I check if indicator creation succeeded before adding to dictionary?**
python #Currentapproach: obv=self.obv(symbol,Resolution.MINUTE) #...warmup... self.phase1obv∈dica→rs[symbol]=obv #Beerapproach? obv=self.obv(symbol,Resolution.MINUTE) ifobvis¬No≠: #Checkifcreation≻eeded? #...warmup... self.phase1obv∈dica→rs[symbol]=obv
4. **What if indicator creation fails silently?**
- Can self.rdv(), self.cmf(), or self.obv() return None?
- Or do they always return an object even if data is insufficient?
- How do I detect if indicator creation actually failed?
---
## Additional Questions
### 1. Indicator Update Methods
**Question:** What is the correct way to update different indicator types manually?
For RDV (price-based):
pythonrdv.update(time,row['close']) #✅Works?
For CMF and OBV (volume-based):
`python
# Option A: Create TradeBar
cmf.update(TradeBar(time, symbol, open, high, low, close, volume))
# Option B: Pass row directly?
cmf.update(time, row)
# Option C: Use different method?
cmf.update(TradeBar.from_dict(row))
`
Which approach is correct for each indicator type?
---
### 2. Handling Missing Data in History
**Question:** How should I handle incomplete or missing data in history?
Current approach:
pythonhis→ry=self.his→ry(symbol,10,Resolution.MINUTE)ifhis→ry.emptyor≤n(his→ry)<2: returnFalse #Skipthissymbol
But what if:
- History has 10 rows but some have zero volume?
- History has gaps (missing minutes)?
- OHLC values are present but invalid (negative, NaN)?
Should I:
`python
# Clean the data first?
history = history[history['volume'] > 0]
history = history[history['close'] > 0]
history = history.dropna()
# Then check if enough data remains?
if len(history) < indicator.warm_up_period:
return False
`
---
### 3. Indicator Readiness After Manual Warm-up
**Question:** After manual warm-up, should indicators be immediately ready?
Expected behavior:
pythonrdv=self.rdv(symbol,2,Resolution.MINUTE)#Maνallyfeed2s¯rdv.update(time1,close1)rdv.update(time2,close2)#Shod––rdv.isreadybeTruenow?
Or does isready only work with automatic data feed?
---
### 4. Best Practice for Indicator Creation Flow
**Question:** What is the recommended order of operations?
**Option A: Create → Store → Warm-up**
pythonrdv=self.rdv(symbol,2,Resolution.MINUTE)self.phase1rdv∈dica→rs[symbol]=rdv #S→refirst#Thenwarmupfortime,row∈his→ry.iterrows(): self.phase1rdv∈dica→rs[symbol].update(time,row['close'])
**Option B: Create → Warm-up → Store**
pythonrdv=self.rdv(symbol,2,Resolution.MINUTE)#Warmupfirstfortime,row∈his→ry.iterrows(): rdv.update(time,row['close'])#Thens→reself.phase1rdv∈dica→rs[symbol]=rdv
**Option C: Create → Warm-up → Verify → Store**
pythonrdv=self.rdv(symbol,2,Resolution.MINUTE)#Warmupfortime,row∈his→ry.iterrows(): rdv.update(time,row['close'])#Verifyitworkedifrdv.isreadyandrdv.samp≤s≥2: self.phase1rdv∈dica→rs[symbol]=rdvelse: self.debug(fRDV warm-up failed for {symbol.value})
Which option is best practice?
---
### 5. Error Recovery Strategy
**Question:** If indicator creation fails for one stock, what should I do?
**Current approach:**
- Try to create all 3 indicators
- If any fail, log error but continue
- Return True if at least one indicator was created
**Is this correct, or should I:**
- Return False if ANY indicator fails (all-or-nothing)?
- Keep partial indicators and mark the stock as "incomplete"?
- Retry indicator creation on next rotation?
---
### 6. Performance Optimization
**Question:** Is there a more efficient way to bulk warm-up indicators?
Current approach (per symbol):
pythonforsymbol∈batch: his→ry=self.his→ry(symbol,10,Resolution.MINUTE) #Createandwarmup∈dica→rs
Better approach (bulk request)?
python#Requesthis→ryforallsymbolsatonce?allhis→ry=self.his→ry(batchsymbols,10,Resolution.MINUTE)forsymbol∈batchsymbols: symbolhis→ry=allhis→ry[symbol] #Createandwarmup∈dica→rs
Does bulk history request improve performance?
---
### 7. Indicator Memory Management
**Question:** After removing a stock from the batch, how do I properly clean up indicators?
Current approach:
pythondefc≤aνpphase1∈dica→rs(self,symbol): self.phase1rdv∈dica→rs.pop(symbol,No≠) self.phase1cmf∈dica→rs.pop(symbol,No≠) self.phase1obv∈dica→rs.pop(symbol,No≠)
Should I also:
python#Explicitlydisposeofthe∈dica→r?ifsymbol∈self.phase1rdv∈dica→rs: ∈dica→r=self.phase1rdv∈dica→rs[symbol] #∈dica→r.dispose()? #∈dica→r.reset()? ∂self.phase1rdv∈dica→rs[symbol]
Or is pop() sufficient for garbage collection?
---
### 8. Monitoring Warm-up Success Rate
**Question:** How can I track and optimize warm-up success rate?
Should I maintain statistics like:
pythonself.warμpstats={ '→talaempts':0, '≻es′–:0, 'fai≤dnohis→ry':0, 'fai≤d∈dica→rcreation':0, '∂≻ess':0}
And log them periodically:
python≻essrate=self.warμpstats'≻es′–self.warμpstats['→talaempts']self.log(f[WARMUP-STATS] Success rate: {success_rate:.1%})
Is this recommended for production strategies?
---
## Summary of Questions
1. Why does KeyError occur if I replaced warmup∈dica→r()?
2. Is my manual warm-up implementation correct?
3. How to properly update different indicator types?
4. How to handle missing/incomplete data in history?
5. Should indicators be immediately ready after manual warm-up?
6. What is the best order: Create → Store → Warm-up?
7. What error recovery strategy should I use?
8. Is bulk history request more efficient?
9. How to properly clean up indicators?
10. Should I track warm-up success rate?
---
## Context
- **Strategy Type**: Intraday with batch rotation
- **Batch Size**: 100 stocks
- **Rotation Interval**: 15 minutes (increased from 5)
- **Indicators**: RDV (period=2), CMF (period=3), OBV
- **Implementation**: Following your previous recommendations
Thank you for your continued guidance!
Mia Alissi
Here's a reference implementation that demonstrates best practices for batch indicator creation, manual warm-up, input cleaning, readiness checking, memory management, and warm-up statistics in QuantConnect. This template addresses all of your core questions and is heavily commented for clarity.
Key points and best practices implemented:
rdv.update(IndicatorDataPoint),cmf/obv.update(TradeBar).Use/adapt this as your template for robust, scalable batch warm-up and management in QuantConnect.
Sources: Indicator Warmup Algorithm, Warm Up Periods - QuantConnect.com, Automatic Indicators - QuantConnect.com, Warmup Algorithm, Manual Indicators - QuantConnect.com
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.
مطلق الشمري
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!