I can't figure this out for the life of me as in other parts of the project there are similarly referenced modules/classes that don't raise this error. Note that I've set up RsiAlphaModel the same way I have with MainAlgorithm - yet the MainAlgorithm class declaration doesn't throw an error and RsiAlphaModel does. My project directory has folders "Alphas", "Indicators" and "Algorithms" aside from main.py. Hoping someone can shed some light on this.
from Algorithms import StandardAlgorithm
from Alphas import RsiAlphaModel
class MainAlgorithm(StandardAlgorithm):
def Initialize(self):
# Securities traded
symbols = [ Symbol.Create("CRNS", SecurityType.Equity, Market.USA) ]
self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
super().Initialize()
self.SetAlpha(CompositeAlphaModel(RsiAlphaModel()))
class StandardAlphaModel(AlphaModel):
def Initialize(self):
self.Indicator = None
def OnSecuritiesChanged(self, algorithm, changes):
for security in changes.AddedSecurities:
for minutes, timeframe in algorithm.timeframes.items():
algorithm.RegisterIndicator(security.Symbol.Value, self.Indicator, timeframe)
class StandardAlgorithm(QCAlgorithmFramework):
def Initialize(self):
self.SetTimeframes()
self.SetSecurityInitializer(self.SetSecurities)
def SetSecurities(self, security):
security.SetDataNormalizationMode(DataNormalizationMode.Raw)
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
for minutes, timeframe in self.timeframes.items():
self.SubscriptionManager.AddConsolidator(security.Symbol.Value, timeframe)
for security in changes.RemovedSecurities:
for minutes, timeframe in self.timeframes.items():
self.SubscriptionManager.RemoveConsolidator(security.Symbol.Value, timeframe)
def SetTimeframes(self):
self.SetTimeZone(TimeZones.Toronto)
self.UniverseSettings.Resolution = Resolution.Minute
self.timeframes = {
1: None,
5: None,
15: None,
30: None,
60: None,
240: None,
390: None,
1950: None
}
for minutes in self.timeframes:
self.timeframes[minutes] = TradeBarConsolidator(TimeSpan.FromMinutes(minutes))
self.timeframes[minutes].DataConsolidated += self.OnDataConsolidated
def OnDataConsolidated(self, sender, bar):
pass
from Alphas import StandardAlphaModel
from Indicators import EhlerRsiDiscriminator
# This is where the error occurs!
class RsiAlphaModel(StandardAlphaModel):
def Initialize(self):
self.Name = "RSI Alpha"
self.Indicator = EhlerRsiDiscriminator(true, 48, 10)
Jake Mitchell
Barring a solution to this, is there a way I can iterate over my algo's alphas so I don't have to rely on the alpha itself to register?
Jack Simonson
Hi Jake,
Can you attach a full backtest of the algorithm? This would help us better understand the structure of the algorithm and better help us to debug it. Right now I can't see an immediate solution and having full access to your code would be immensely helpful.
Jake Mitchell
Hi Jack,
Thanks for responding; I'm new to Python and as it turns out all I needed to do was specify the class name in the import along with the module name. i.e:
from Algorithms import StandardAlgorithm to from Algorithms.StandardAlgorithm import StandardAlgorithm
However I'd still like to know how to iterate over CompositeAlphaModel. Right now I'm storing my Alphas in an array and then passing it to CompositeAlphaModel and using the array elsewhere in my algorithm. It just feels like an unnecessary step.
I store my indicator instances within the alpha model that utilizes it, so that's why I need to iterate them (for the sake of plotting, registering consolidators, passing data, etc.)
Alexandre Catarino
Hi Jake Mitchell ,
I am not sure what you want to accomplish with the CompositeAlphaModel.
We should just add the alpha models to it:
self.SetAlpha(CompositeAlphaModel(RsiAlphaModel(), EmaCrossAlphaModel()))
The engine tags each insight with the alpha model name. In the portfolio construction model, we can take different actions with insights from different alpha models.
If I have missed your point, could you please give us a practical example?
Jake Mitchell
Each of my Alpha models contain a corresponding indicator. For example, my RsiAlphaModel has a class attribute which holds a custom RsiIndicator. In my Algorithm I iterate over multiple consolidated timeframes and each of these Alphas to populate the corresponding symbol+timeframe indicators. That way the only thing I need to do when creating a new Algorithm is include the relevant Alpha and all of the corresponding timeframe-based indicators and insights will be included and I can work up from there. I'm in essence attempting to replicate what I see in TradingView when I have an indicator template and multiple timeframes open (1 minute, 5 minute, 15 minute). I then want to aggregate my multiple time frame indicator values in the RsiAlphaModel to get a more comprehensive confidence level in my trades.
I'm still having issues getting the right values to calculate properly (much less the bar chart; all indicator values are 0 atm) so if you could help with that as well it would be greatly appreciated. This is an attempt to translate this indicator from TV.
Alexandre Catarino
I would say that you have two options: create a list of alphas with different timeframes or create different timeframe in one alpha:
timeframes = [1, 5, 15, 30, 60, 240, 390, 1950] alphas = [MyAlphaA(x) for x in timeframes] self.SetAlpha(CompositeAlphaModel(alphas))
where
class MyAlphaA(AlphaModel): def __init__(self, timeframe): self.timeframe = timeframe self.Name = f'MyAlphaA({timeframe})'
or
timeframes = [1, 5, 15, 30, 60, 240, 390, 1950] self.SetAlpha(MyAlphaB(timeframes))
where
class MyAlphaB(AlphaModel): def __init__(self, timeframes): self.timeframes = timeframes
Then you will have to create the consolidator (consolidators in AlphaB) to aggregate the data in the alpha models.
The advantage of the first method is the ability to have different AlphaModel.Name corresponding to a different timeframe. If we want to use different timeframes to confirm an insight, probably the second method is better, because we will have to implement a portfolio construction model that will create a target based on insights of different instances of MyAlphaA.
About the indicator, I couldn't find the statement that calls EhlerRsiDiscriminator.Update.
I would suggest you that use the basic template framework algorithm and adapt Lean MacdAlphaModel because, in this example, we create the indicator with a constructor:
class SymbolData: def __init__(self, algorithm, security, fastPeriod, slowPeriod, signalPeriod, movingAverageType, resolution): self.Security = security self.MACD = MovingAverageConvergenceDivergence(fastPeriod, slowPeriod, signalPeriod, movingAverageType) self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution) algorithm.RegisterIndicator(security.Symbol, self.MACD, self.Consolidator)
so we just need to change the 4th line for EhlerRsiDiscriminator.
Jake Mitchell
I've followed your advice and reworked my project. I still don't have an explicit call to Update as the examples shown don't call it either (and the indicator uses the ComputeNextValue, not the Update method). But I'm stuck on an error that I feel is more Python-related yet I can't troubleshoot.
SymbolData is complaining that algorithm doesn't have Consolidators even though it should.
Jake Mitchell
Sorry the wrong backtest is attached. Most most recent ones aren't showing up in the dropdown list.
Here's the link
Jake Mitchell
Most up to date script; same error but code should be much more easily understood. I figure this may be a class inheritance/instantiation issue as the 'algorithm' that gets passed to OnSecuritiesChanged should most definitely have the 'Consolidators' attribute.
Jake Mitchell
Further inquiries over email have revealed that this is an issue brought about by Python being embedded in C#. The object being passed to the alpha methods `Update` and `OnSecuritiesChanged` is actually a QCFrameworkAlgorithm object and not my algorithm (MainAlgorithm). The solution was to pass the algorithm through the __init__ of the alpha model and to ignore the algorithm argument in those functions.
Also FWIW, my indicator doesn't use the `ComputeNextValue` method but instead uses `Update` (even though the docs on how to create an indicator says to use `ComputeNextValue`).
Jake Mitchell
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!