Hello All! I am new to quantconnect and I am mind-blown by the possibilities that QC has to offer. Nonetheless I have a few questions ... :)
I am trying to develop a strategy where I want to:
* Subscribe to a custom universe with daily data resolution but with a condition requiring the 2 period weekly RSI. Update Universe every Friday.
*With the output symbols from the custom universe, consolidate data to weekly resolution for a Sell condition on the RSI indicator. And also have the possibility to access the daily data.
Currently I am using 2 custom classes:
SelectionData which is used to select the stocks for the custom universe, but I want to check if the 2 week period RSI is below 20
SymbolData which consolidates the data from the output stocks of the universe to weekly data, but the consolidations doesn't seem to work when I debug the 2 period weekly RSI.
Any Insights or links to similar projects?
Thanks!
Derek Melchin
Hi Victor,
To setup a custom universe, refer to this documentation. The EmaCrossUniverseSelectionAlgorithm is a great example of using technical indicators in the universe selection model.
Our docs on data consolidation may help with debugging the issue with the 2 period weekly RSI. For further assistance, attach a backtest to this thread.
Best,
Derek Melchin
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.
Victor Goujon
Hi Derek, thanks for your answer !
I have used the docs and think I have implemented the consolidation correctly but it is still not working.
What I am trying to achieve is a weekly consolidation with a historical warmup of the RSI Indicator. Right now, the output of the RSI value lags of 7 days. I have tried using the historical function to pump data into the RSI with not success. Any ideas?
PS: I have set the RSI to the SMA in the backtest to make debugging easier.
Derek Melchin
Hi Victor,
The RSI appears to be lagging because the algorithm updates the RSI using the start time of the consolidated bar.
self.RSI.Update(bar.Time, bar.Close)
To resolve this, we need to pass the EndTime of the consolidated bar when updating the RSI indicator.
self.RSI.Update(bar.EndTime, bar.Close)
See the attached backtest for reference.
Going forward, consider moving the history request and warm-up from OnSecuritiesChanged to inside the SymbolData_forAlpha constructor. Additionally, note that the securities in the universe can fail the RSI condition. To force all securities in the universe to meet the RSI condition, follow the example in the EmaCrossUniverseSelectionAlgorithm. Lastly, remember to remove the consolidator when securities are removed from the universe.
Best,
Derek Melchin
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.
Victor Goujon
Hi Derek, thanks for the info !
With your help I managed to advance but I am still stuck.
I want to create a universe selection based on daily data and consolidated weekly data. I have tried to implement it but I get the following error even though I subscribed to the consolidator.
ArgumentException : Please subscribe to this symbol before adding a consolidator for it. Symbol:
Any idea on how I could do this?
Many thanks,
Victor
Victor Goujon
class DynamicOptimizedContainmentField(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 11,20) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.MyCoarseFilterFunction) self.symbolsConsolidated = {} self.symbolUniv=[] self.UniverseData={} # def SelectCoarse(self, coarse): # d = self.Time.date() # if d.weekday() == 4 : # sortedCoarse = sorted(coarse, key=lambda c:c.DollarVolume, reverse=True) # self.symbolUniv = [c.Symbol for c in sortedCoarse][:2] # return self.symbolUniv # else : # return self.symbolUniv def MyCoarseFilterFunction(self,coarse): d = self.Time.date() if d.weekday() == 4 : # We are going to use a dictionary to refer the object that will keep the moving averages for c in coarse: if c.Symbol not in self.UniverseData: self.UniverseData[c.Symbol] = SymbolData_forUniverse(self,c.Symbol, 200,100,2) self.UniverseData[c.Symbol].update(c.EndTime, c.AdjustedPrice, c.DollarVolume) # Take top 500 highest 200 period volume EMA. sortedByDollarVolume = sorted(self.UniverseData.values(), key=lambda x: x.smaVolume.Current.Value, reverse=True)[:500] # Filter the values of the dict to those that have a weekly RSI<20 values = [x for x in sortedByDollarVolume if x.belowRSI ] # Filter the least volatiles stocks values.sort(key=lambda x: x.smavolatility.Current.Value, reverse=False) # Take 10 smallest volatility stocks self.symbols= [ x.symbol for x in values[:2] ] return self.symbols def OnSecuritiesChanged(self, changes): for security in changes.AddedSecurities : symbol = security.Symbol if symbol not in self.symbolsConsolidated: self.symbolsConsolidated[symbol] = SymbolData_forAlpha(self,symbol) for security in changes.RemovedSecurities : symbol = security.Symbol if symbol in self.symbolsConsolidated: symbolData = self.symbols.pop(symbol, None) self.SubscriptionManager.RemoveConsolidator(self.symbolsConsolidated.symbol, self.symbolsConsolidated.consolidator) def OnData(self,data): d = self.Time.date() symbol = list(self.symbolsConsolidated.keys())[0] self.Debug(symbol) symbolData=self.symbolsConsolidated[symbol] if symbolData.IsReady : self.Debug(f"Time: {symbolData.Time}; Close: {symbolData.Close}; RSI: {symbolData.RSI.Current.Value}") class SymbolData_forAlpha: def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.consolidator = TradeBarConsolidator(timedelta(days=7)) self.consolidator.DataConsolidated += self.OnDataConsolidated algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator) self.Time=None self.Close=None self.RSI=SimpleMovingAverage(2) self.IsReady=False history = algorithm.History(symbol,14, Resolution.Daily) for index, row in history.loc[str(self.symbol)].iterrows(): self.Close=row["close"] self.RSI.Update(index, row["close"]) self.Time=index def OnDataConsolidated(self, sender, bar): self.Close=bar.Close self.Time=bar.EndTime self.RSI.Update(self.Time,self.Close) self.IsReady = self.RSI.IsReady class SymbolData_forUniverse: def __init__(self, algorithm, symbol,periodSMA,periodVol,period_cons): self.algorithm = algorithm self.symbol = symbol self.Time=None self.IsReady=False self.Close=None #Consolidators self.consolidator = TradeBarConsolidator(timedelta(days=7)) self.consolidator.DataConsolidated += self.OnDataConsolidated algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator) #Volume self.smaVolume = SimpleMovingAverage(periodSMAVolume) self.volume=0 #volatility self.smavolatility=SimpleMovingAverage(periodVol) #RSI self.Close_consolidated=None self.RSI=SimpleMovingAverage(period_cons) self.Time_consolidated=None self.belowRSI=False #History history = algorithm.History(symbol,max[periodSMA,periodVol,period_cons], Resolution.Daily) for index, row in history.loc[str(self.symbol)].iterrows(): self.Close=row["close"] self.Close_consolidated=row["close"] self.RSI.Update(index, row["close"]) self.Time=index self.Volume=row["volume"] self.smaVolume.Update(index,row["close"]) self.smavolatility.Update(index,row["close"]) self.smaVolume.Update(index,row["close"]) self.belowRSI = self.RSI.Current.Value < 50 self.IsReady = self.smaVolume.IsReady def OnDataConsolidated(self, sender, bar): self.algorithm.Log(f"Data Consolidatoed for {self.symbol} at {bar.EndTime} with bar: {bar}") #self.algorithm.Log(str(bar.Time) + " " + str(bar)) self.Close_consolidated=bar.Close self.Time_consolidated=bar.EndTime self.RSI.Update(self.Time,self.Close_consolidated) self.IsReady = self.RSI.IsReady self.belowRSI = self.RSI.Current.Value < 50 def update(self, time,price,volume): self.Volume=volume self.Close=price self.Time=time self.smaVolume.Update(self.Time,self.volume) #update volume and belowRSI boolean self.smavolatility.Update(self.Time,np.std(self.Close))
Derek Melchin
Hi Victor,
We can't setup consolidators for securities the algorithm isn't subscribed to. Using the framework design, the algorithm subscribes to securities when they are returned from the universe selection model. A workaround is to just update the indicators in the SymbolData_forAlpha class with the price provided in the CoarseSelectionFunction. See this demo for reference.
Best,
Derek Melchin
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.
Victor Goujon
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!