Hi there,
I've been trying to create a universe based on bollinger bands and keltner channels. I've followed the example here, with no success. My code is returning the error ‘object not set to an instance of a class.’ I have no idea why the algorithm is breaking at the history request. Can anyone help?
class TheSqueezeUniverseSelection(QCAlgorithm):
def __init__(self, algorithm, period = 20):
self.algorithm = algorithm
self.period = period
self.indicators = {}
def CoarseSelectionFunction(self, universe):
selected = []
universe = sorted(universe, key=lambda c: c.DollarVolume, reverse=True)
universe = [c for c in universe if c.Price > 10][:100]
for coarse in universe:
symbol = coarse.Symbol
if symbol not in self.indicators:
# 1. Call history to get an array of 200 days of history data
history = self.History(symbol, 200, Resolution.Daily)
#2. Adjust SelectionData to pass in the history result
self.indicators[symbol] = SelectionData(history, self.period)
self.indicators[symbol].update(self.Time, coarse.AdjustedPrice)
if self.indicators[symbol].is_ready() and \
indicators.BollingerUpper < indicators.KelterUpper and \
indicators.BollingerLower > indicators.KelterLower:
selected.append(symbol)
return selected[:10]
class SelectionData():
#3. Update the constructor to accept a history array
def __init__(self, history, period):
self.bollinger = BollingerBands(period, 2, MovingAverageType.Simple)
self.keltner = KeltnerChannels(period, 1.5, MovingAverageType.Simple)
#4. Loop over the history data and update the indicatorsc
for bar in history.itertuples():
tradeBar = TradeBar(bar.Index[1], bar.Index[0], bar.open, bar.high, bar.low, bar.close, bar.volume, timedelta(1))
self.bollinger.Update(bar.Index[1], bar.close)
self.keltner.Update(tradeBar)
@property
def BollingerUpper(self):
return float(self.bollinger.UpperBand.Current.Value)
@property
def BollingerLower(self):
return float(self.bollinger.LowerBand.Current.Value)
@property
def KeltnerUpper(self):
return float(self.keltner.UpperBand.Current.Value)
@property
def KeltnerLower(self):
return float(self.keltner.LowerBand.Current.Value)
def is_ready(self):
return self.bollinger.IsReady and self.keltner.IsReady
def update(self, time, value):
return self.bollinger.Update(time, value)
Nicholas Fitzgerald
Attached is the code running with a different universe selection module so that you can access the project easier. The current, problematic code which occurs when integrating the history request and keltner channels can be found in the Universe3 module.
Any help would be greatly appreciated, this has been a total wall for me!
Nick
Louis Szeto
Hi Nicholas
Sorry for the delay. Another call of the superclass QCAlgorithm in Universe3.py is not the same instance as the one in main.py. The bounded method History thus is not working properly on this repeat.
Instead of inheriting from QCAlgorithm, we suggest inheriting the class TheSqueezeUniverseSelection in universe3.py from the FundamentalUniverseSelectionModel superclass. The attached backtest is for reference.
Best
Louis Szeto
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.
Nicholas Fitzgerald
Hi Louis, thank you for this solution! I was able to get the universe selection working by incorporating it into my main file, but I will endeavor to move back to a fully modular approach for code re-use. My new issue is that the indicators in my alpha model don't seem to be applying themselves to the symbol data. Would you be able to have a look? The code runs but the rolling windows don't seem to function nor does calling the indicators current value work, which is what I have attempted in some of the test.py files. What am I doing wrong?
Please and thank you!
Louis Szeto
Hi Nicholas
In the class TheSqueeze in TheSqueeze.py, the method's name has to be "OnSecuritiesChanged" rather than "OnsecuritiesChanged" in order to override the virtual method successfully for adding the corresponding key-value pair into self.symbolData dictionary. The same case-sensitive issue needs to be addressed for self.resolution vs self.Resolution in the same alpha model class.
We also recommend warming up the indicators in the SymbolData class within the same file just like in CoarseSelectionFunction in main.py for accurate values.
Best
Louis Szeto
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.
Nicholas Fitzgerald
Hi Louis,
Thank you for looking over my code, so silly of me to of made such simple mistakes and not picked up on them. I have been trying to implement your suggestion of integrating the history request, but upon doing so I'm hit with the error:
Runtime Error: TypeError : __init__() missing 1 required positional argument: 'resolution' at OnSecuritiesChanged self.symbolData[added.Symbol] = SymbolData(algorithm in TheSqueeze2.py: line 45
The new alpha can be found in TheSqueeze2.py file. Attached is a backtest using the original module so you can see the code. I've found many examples on warming up indicators in the OnSecuritiesChanged function, but none for warming them up using the SymbolData class. Do you have an example on how to integrate the history request in this manner?
Regards,
Nick
Louis Szeto
Hi Nicholas
The constructor of the SymbolData class should be:
rather than:
as the History call of warm-up is within the constructor.
Best
Louis Szeto
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.
Nicholas Fitzgerald
Hi Louis,
Thank you for your continued assistance with this issue. I have implemented it as such within the new module TheSqueeze2.py, which runs. The alpha model still doesn't emit any insights which is confusing. I believe the indicators still aren't being updated correctly as even when trialling statements like if bollinger band upperband current value == bollinger band upperband current value, emit insight. Am I not applying the indicators correctly to the symboldata?
Regards,
Nick
Nicholas Fitzgerald
Hi Louis, I have been able to get the algorithm trading using a simplified version omitting the rolling windows. I assume my issue is therefore coming from the rolling window setup I have been using in TheSqueeze2.py. Do you have any suggestions as to how to implement these rolling windows effectively??
Regards,
Nick
Louis Szeto
Hi Nicholas
The rolling windows are well set up, but not the indicators. The indicators used were manual-updating type, so they must be explicitly updated or registered for auto-update. We recommend using RegisterIndicator with a single consolidator:
then remove the consolidator when removing the security subscription:
please check the SymbolData class in TheSqueeze2.py in the attached backtest.
Best
Louis Szeto
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.
Nicholas Fitzgerald
Hi Louis,
Thank you again for your continued assistance with this project. I'm looking to implement a risk management model using a fixed ATR stop loss. I would assume that implementing history requests as well as consolidators would follow the same format as seen in the Alpha Model?
Regards,
Nick
Varad Kabade
Hi Nicholas Fitzgerald,
We need to follow all the practices of using indicators and rolling windows as we did in the Alpha class above. We recommend going through the following doc for more information on implementing a RiskManagement model. We also recommend going through the following thread.
Best,
Varad Kabade
Nicholas Fitzgerald
Hi Varad,
I wasn't able to access the link you provided for that thread, do you have alternate source for me?
Thanks,
Nick
Alexandre Catarino
Hi Nicholas Fitzgerald ,
The links that Varad has provided are not broken. Could you please retry now?
Best regards,
Alex
Nicholas Fitzgerald
Hi Alex,
The links are now working, thank you. The information in that thread is quite valuable. My code seem to be running, however it is not returning any targets. I believe there must be some error in logic in the risk management model, or the average true range indicator is not updating and providing a value to compare to the average price of the given stock. I'm unsure why this is occuring as the structure follows that contained in the alpha model. Could you take a look and point out my errors?
Very much appreciated,
Nick
Louis Szeto
Hi Nicholas
This line in the OnSecuritiesChanged method of the RiskManagementModel.py shall be deleted, as it is called on the instance of the security added into the universe but not the portfolio. So the class SymbolData is not initiated for that symbol as at that instance, it has no open position. We recommend using minute resolution for accurate stop-loss behavior. Please also check on this thread. This method will avoid reinvesting right after stop-loss as the insight is still active.
Best
Louis
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.
Nicholas Fitzgerald
Hi Louis,
I removed the suggested line which uncovered a variety of new issues, allowing me to progress the code. The risk management module still seems to not return any targets. The backtest is attached below. I also wanted to clarify whether there should be a liquidate call in the risk management module, or do the targets pass to the execution module to be liquidated? I have read in other threads that calls to liquidate should not be contained in the risk management module, is this true?
I read through the thread you suggested which I will attempt to implement once my ATR stop loss is up and running, thank you for pointing me towards that information!
Regards,
Nick
Louis Szeto
Hi Nicholas
The code should be fine in RiskManagmentModel.py. However, since there is insight emitted every minute, the average price of each security could be adapted to a very recent price, so that it is unlikely to reach the stop level.
If you would like to adopt an ATR trailing stop loss. It would be better if the insight frequency is lowered, as well as revising the stop loss logic as the formula of that should be
Best
Louis
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.
Nicholas Fitzgerald
Hi Louis,
So just to confirm, the current stop loss is a static ATR close to the time of purchase, but the average price of each security is a dynamic value? Which results in the stop never being triggered?
In terms of the insight count, are you refering to insights being generated on a single security? Or for the entire universe?
Regards,
Nick
Louis Szeto
Hi Nicholas
The original stop loss level set in your algorithm is hardly reached if there isn't an extremely sharp drop. It is because
The correct way of setting up an ATR trailing stop loss would be
Insight frequency would not be a problem if you follow the above logic. But if you're using your original averaging with stop level moved down as well, too frequent averaging for single security could pose a problem for the stop loss.
Best
Louis
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.
Nicholas Fitzgerald
Hi Louis,
That all makes sense, I didn't realise the average price took the last price of the stock leading to a lower and lower stop loss.
The strategy I am coding typically does not use a trailing stop loss, what if I wanted to set a single, static stop loss using the average true range at the time of purchase? I have seen some suggestions of gathering this information by saving this information from the alpha or declaring global variables, however this violates the separation of concerns principle. Is there a way to access this information from the risk management model?
Regards,
Nick
Nicholas Fitzgerald
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!