Hello,
after hours of searching through google, the forums etc., i'm still unable to figure out how to get historical values for indicators. Could you help me out?
What I am trying to do is to access the ATR values of the past 20 days for each symbol in the universe and calculate the 95% percentile of it to compare it with the actual value.
I think i managed to save data in the rolling window object but when i try to access it, it throws an error for an unrecognized method.
Could you help me to figure out what I am doing wrong?
Thank you for your effort.
Sadly, I am unable to attach a backtest, as the backtest always fails in the first second with the error below.
class ATRMomentumUniverse(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 1, 7)
self.SetEndDate(2020, 4, 1)
self.SetCash(100000)
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction)
self.atrscan = { }
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.atrscan:
history = self.History(symbol, 20, Resolution.Daily)
self.atrscan[symbol] = SelectionData(symbol, history)
atr_quantile = self.atrscan[symbol].atr_container[0:15].quantile(0.25)
if self.atrscan[symbol].is_ready() and self.atrscan[symbol].atr_container[0] < atr_quantile:
selected.append(symbol)
return selected[:10]
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
self.SetHoldings(security.Symbol, 0.1)
def OnData(self, data):
for symbol, selectionData in self.atrscan.items():
if data.Bars.ContainsKey(symbol):
selectionData.update(data.Bars[symbol])
if self.Portfolio[symbol].Invested and selectionData.atr.Current.Value > 100:
self.Liquidate(symbol)
class SelectionData():
def __init__(self, symbol, history):
self.symbol = symbol
self.atr = AverageTrueRange(1)
self.atr.Updated += self.container_update
self.atr_container = RollingWindow[IndicatorDataPoint](20)
for bar in history.itertuples():
tbar = TradeBar(bar.Index[1], self.symbol, bar.open, bar.high, bar.low, bar.close, bar.volume)
self.atr.Update(tbar)
def is_ready(self):
return self.atr_container.IsReady
def update(self, bar):
self.atr.Update(bar)
def container_update(self, sender, updated):
self.atr_container.Add(updated)
Runtime Error: Trying to dynamically access a method that does not exist throws a TypeError exception. To prevent the exception, ensure each parameter type matches those required by the arguments method. Please checkout the API documentation.
at CoarseSelectionFunction in main.py:line 23
:: atr_quantile = self.atrscan[symbol].atr_container[0:15].quantile(0.25)
TypeError : No method matches given arguments (Open Stacktrace)
Rahul Chowdhury
Hey Korbinian,
The algorithm is throwing an TypeError : No method matches given arguments error because the RollingWindow.quantile(0.25) method does not exist. Instead, we can use the numpy.quantile(array, quantile) method. First, we'll need to convert our RollingWindow into a list.
list(self.atrscan[symbol].atr_container)
Then we can access the first 15 elements:
list(self.atrscan[symbol].atr_container)[0:15]
We'll also need to convert our list from a list of IndicatorDataPoints to a list of floats.
[x.Value for x in list(self.atrscan[symbol].atr_container)[0:15]]
Then we can apply the quantile method.
np.quantile([x.Value for x in list(self.atrscan[symbol].atr_container)[0:15]], 0.25)
Let's also make sure to check if our rolling window is ready before we calculate the quantile.
if self.atrscan[symbol].is_ready(): atr_quantile = np.quantile([x.Value for x in list(self.atrscan[symbol].atr_container)[0:15]], 0.25)
Korbinian Gabriel
Hi Rahul,
thank you for helping me! That is actually a more difficult method than I thought, but it works fine!
I've used your improvements and worked futher on the algorithm, adding an MACD indicator as a mean-reversion indicator. However, I seem to be unable to use your same approach to fill the MACD with data.
for bar in history.itertuples(): tbar = TradeBar(bar.Index[1], self.symbol, bar.open, bar.high, bar.low, bar.close, bar.volume) self.atr.Update(tbar) self.macd.Update(bar.close)
The bar.close throws an error and i cannot quite figure out why. When i comment it out, it probably leaves the MACD empty i suggest?
Additionally, as i tried to figure out what values MACD has, or if it has values at all, i tried to log it, however, nothing was logged. As it could be that i just logged wrongly, i tried print(), which printed nothing aswell. This leads me to the conclusion that the OnData() Function isn't called at all. How can I make sure it is called?
And one minor final question, as googling yielded no reliable result. There are no OCO orders, right? I have to use the order-id of the original order? How to I access if an order was triggered or not, so that i can append a new order on the symbol?
Rahul Chowdhury
Hey Korbinian,
When we update the non-bar indicators, we can use the Indicator.Update(time, value) method,
self.macd.Update(bar.Index[1], bar.close)
OnData is not being called because no securities have been added to your universe since no items are added to selected.Lean does not have built-in OCO orders; we have to implement that feature ourselves. We can do this by using the OnOrderEvent method, which fires each time there is an order event, including order submissions, fills, cancellations, etc. See this thread which covers implementing OCO orders.
Also note that, you will need to create a separate rolling window for each component of the MACD because each component is an IndicatorDataPoint(see MovingAverageConvergenceDivergence.cs). You can access each component of the MACD with
signal = self.macd.Signal.Current slow = self.macd.Slow.Current fast = self.macd.Fast.Current
Best
Rahul
Korbinian Gabriel
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!