Good day,
I am trying to create a rolling window of consolidated indicator information. I have looked the rolling window and consolidating data docs (documents and demonstration algorithms) and I have tried to stitch something together.
When I try backtest the algorithm, I get an error on line 61 stating that an update method must be defined.
When I remove the self.registerindicator lines, I get another error on line 106 regarding (.Current) or (.Signal). Its as if the only information that I can extract from the rolling window is (.Value) which is a problem cause I need to extract upper and lower band from the bollinger band indicator and signal from the macd indicator.
Please could you assist with this. Your assistance will be truly appreciated.
Mfundo Zubane
# Imports
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Jupyter")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Algorithm")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data import *
from QuantConnect.Data.Custom import *
from QuantConnect.Data.Market import TradeBar, QuoteBar
from QuantConnect.Data.Consolidators import *
from QuantConnect.Jupyter import *
from QuantConnect.Indicators import *
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
class BasicTemplateAlgorithm(QCAlgorithm):
def Initialize(self):
self.symbol = "USDZAR"
self.highprice = None
self.lowprice = None
self.tidetrend = None
self.wavetrend = None
self.closeWindow = RollingWindow[float](4)
self.SetStartDate(2018,9,1) #Set Start Date
self.SetEndDate(datetime.now()) #Set End Date to Now
self.SetCash(1122) #Set Strategy Cash
self.AddForex(self.symbol, Resolution.Minute).SetLeverage(50.0)
# Create the rolling windows
# Creates MACDOH indicator and add to a rolling window when it is updated
self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential).Updated += self.MACDOHUpdated
self.macdoh = RollingWindow[float](5)
# Creates MACDTM indicator and add to a rolling window when it is updated
self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential).Updated += self.MACDTMUpdated
self.macdtm = RollingWindow[float](5)
# Creates BB indicator and add to a rolling window when it is updated
self.BB(self.symbol, 20, 1, MovingAverageType.Exponential, Resolution.Minute).Updated += self.BBUpdated
self.bb = RollingWindow[float](5)
# Creates RSI indicator and add to a rolling window when it is updated
self.RSI(self.symbol, 14, MovingAverageType.Simple, Resolution.Minute).Updated += self.RSIUpdated
self.rsi = RollingWindow[float](5)
oneHourConsolidator = QuoteBarConsolidator(timedelta(minutes=60))
oneHourConsolidator.DataConsolidated += self.OneHourBarHandler
self.RegisterIndicator(self.symbol, self.macdoh, oneHourConsolidator)
self.SubscriptionManager.AddConsolidator(self.symbol, oneHourConsolidator)
tenMinuteConsolidator = QuoteBarConsolidator(timedelta(minutes=10))
tenMinuteConsolidator.DataConsolidated += self.TenMinuteBarHandler
self.RegisterIndicator(self.symbol, self.macdtm, tenMinuteConsolidator)
self.RegisterIndicator(self.symbol, self.bb, tenMinuteConsolidator)
self.RegisterIndicator(self.symbol, self.rsi, tenMinuteConsolidator)
self.SubscriptionManager.AddConsolidator(self.symbol, tenMinuteConsolidator)
twoMinuteConsolidator = QuoteBarConsolidator(timedelta(minutes=2))
twoMinuteConsolidator.DataConsolidated += self.TwoMinuteBarHandler
self.SubscriptionManager.AddConsolidator(self.symbol, twoMinuteConsolidator)
self.SetWarmUp(120, Resolution.Minute)
#Pass (cause this is only for minute data)
def OnData(self, data):
pass
# Adds updated values to MACDOH rolling window
def MACDOHUpdated(self, sender, updated):
self.macdoh.Add(updated)
# Adds updated values to MACDTM rolling window
def MACDTMUpdated(self, sender, updated):
self.macdtm.Add(updated)
# Adds updated values to BB rolling window
def BBUpdated(self, sender, updated):
self.bb.Add(updated)
# Adds updated values to RSI rolling window
def RSIUpdated(self, sender, updated):
self.rsi.Add(updated)
def OneHourBarHandler(self, sender, consolidated):
if not (self.macdoh.IsReady): return
macd_hist_0 = self.macdoh[0].Current.Value - self.macdoh[0].Signal.Current.Value
macd_hist_1 = self.macdoh[1].Current.Value - self.macdoh[1].Signal.Current.Value
macd_hist_2 = self.macdoh[2].Current.Value - self.macdoh[2].Signal.Current.Value
macd_hist_3 = self.macdoh[3].Current.Value - self.macdoh[3].Signal.Current.Value
def TenMinuteBarHandler(self, sender, consolidated):
self.closeWindow.Add(data[self.symbol].Close)
if not (self.closeWindow.IsReady and self.macdoh.IsReady and self.macdtm.IsReady and self.bb.IsReady and self.rsi.IsReady): return
price_0 = self.closeWindow[0]
price_1 = self.closeWindow[1]
price_2 = self.closeWindow[2]
self.highprice = max(price_0, price_1, price_2)
self.lowprice = min(price_0, price_1, price_2)
currrsi = self.rsi[0].Current.Value
currbbub = self.bb[0].UpperBand.Current.Value
currbblb = self.bb[0].LowerBand.Current.Value
macd_hist_0 = self.macdtm[0].Current.Value - self.macdtm[0].Signal.Current.Value
macd_hist_1 = self.macdtm[1].Current.Value - self.macdtm[1].Signal.Current.Value
macd_hist_2 = self.macdtm[2].Current.Value - self.macdtm[2].Signal.Current.Value
macd_hist_3 = self.macdtm[3].Current.Value - self.macdtm[3].Signal.Current.Value
Gurumeher Sawhney
Thank you for attaching the source code! The reason for the error is because self.RegisterIndicator requires the parameters self.RegisterIndicator(symbol, indicator, consolidator). However, the code above gave a RollingWindow instead of an indicator. After changing the types, the error did not come up again. However, there were a few other errors. Here is a reference to the documentation.
One of the errors was in the method TenMinuteBarHandle. data is not defined in the line:
self.closeWindow.Add(data[self.symbol].Close)
I went ahead and changed that to Self.Securities[self.symbol].Close. Another error was the types contained in the RollingWindow. I changed that to IndicatorDataPoint so that IndicatorDataPoint.Value could be called on the data. Below is the algorithm in progress:
# Imports from clr import AddReference AddReference("System") AddReference("QuantConnect.Common") AddReference("QuantConnect.Jupyter") AddReference("QuantConnect.Indicators") AddReference("QuantConnect.Algorithm") from System import * from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Data import * from QuantConnect.Data.Custom import * from QuantConnect.Data.Market import TradeBar, QuoteBar from QuantConnect.Data.Consolidators import * from QuantConnect.Jupyter import * from QuantConnect.Indicators import * from datetime import datetime, timedelta import matplotlib.pyplot as plt import pandas as pd import numpy as np class BasicTemplateAlgorithm(QCAlgorithm): def Initialize(self): self.symbol = "USDZAR" self.highprice = None self.lowprice = None self.tidetrend = None self.wavetrend = None self.closeWindow = RollingWindow[float](4) self.SetStartDate(2018,9,1) #Set Start Date self.SetEndDate(datetime.now()) #Set End Date to Now self.SetCash(1122) #Set Strategy Cash self.AddForex(self.symbol, Resolution.Minute).SetLeverage(50.0) # Create the rolling windows # Creates MACDOH indicator and add to a rolling window when it is updated self.macd1 = self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential) self.macd1.Updated += self.MACDOHUpdated self.macdoh = RollingWindow[IndicatorDataPoint](5) # Creates MACDTM indicator and add to a rolling window when it is updated self.macd2 = self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential) self.macd2.Updated += self.MACDTMUpdated self.macdtm = RollingWindow[IndicatorDataPoint](5) # Creates BB indicator and add to a rolling window when it is updated self.boll = self.BB(self.symbol, 20, 1, MovingAverageType.Exponential, Resolution.Minute) self.boll.Updated += self.BBUpdated self.bb = RollingWindow[IndicatorDataPoint](5) # Creates RSI indicator and add to a rolling window when it is updated self.strength = self.RSI(self.symbol, 14, MovingAverageType.Simple, Resolution.Minute) self.strength.Updated += self.RSIUpdated self.rsi = RollingWindow[IndicatorDataPoint](5) oneHourConsolidator = QuoteBarConsolidator(timedelta(minutes=60)) oneHourConsolidator.DataConsolidated += self.OneHourBarHandler self.RegisterIndicator(self.symbol, self.macd1, oneHourConsolidator) self.SubscriptionManager.AddConsolidator(self.symbol, oneHourConsolidator) tenMinuteConsolidator = QuoteBarConsolidator(timedelta(minutes=10)) tenMinuteConsolidator.DataConsolidated += self.TenMinuteBarHandler self.RegisterIndicator(self.symbol, self.macd2, tenMinuteConsolidator) self.RegisterIndicator(self.symbol, self.boll, tenMinuteConsolidator) self.RegisterIndicator(self.symbol, self.strength, tenMinuteConsolidator) self.SubscriptionManager.AddConsolidator(self.symbol, tenMinuteConsolidator) # twoMinuteConsolidator = QuoteBarConsolidator(timedelta(minutes=2)) # twoMinuteConsolidator.DataConsolidated += self.TwoMinuteBarHandler # self.SubscriptionManager.AddConsolidator(self.symbol, twoMinuteConsolidator) self.SetWarmUp(120, Resolution.Minute) #Pass (cause this is only for minute data) def OnData(self, data): pass # Adds updated values to MACDOH rolling window def MACDOHUpdated(self, sender, updated): self.macdoh.Add(updated) # Adds updated values to MACDTM rolling window def MACDTMUpdated(self, sender, updated): self.macdtm.Add(updated) # Adds updated values to BB rolling window def BBUpdated(self, sender, updated): self.bb.Add(updated) # Adds updated values to RSI rolling window def RSIUpdated(self, sender, updated): self.rsi.Add(updated) def OneHourBarHandler(self, sender, consolidated): if not (self.macdoh.IsReady): return macd_hist_0 = self.macdoh[0].Current.Value - self.macdoh[0].Signal.Current.Value macd_hist_1 = self.macdoh[1].Current.Value - self.macdoh[1].Signal.Current.Value macd_hist_2 = self.macdoh[2].Current.Value - self.macdoh[2].Signal.Current.Value macd_hist_3 = self.macdoh[3].Current.Value - self.macdoh[3].Signal.Current.Value def TenMinuteBarHandler(self, sender, consolidated): self.closeWindow.Add(self.Securities[self.symbol].Close) if not (self.closeWindow.IsReady and self.macdoh.IsReady and self.macdtm.IsReady and self.bb.IsReady and self.rsi.IsReady): return price_0 = self.closeWindow[0] price_1 = self.closeWindow[1] price_2 = self.closeWindow[2] self.highprice = max(price_0, price_1, price_2) self.lowprice = min(price_0, price_1, price_2) currrsi = self.rsi[0].Current.Value currbbub = self.bb[0].UpperBand.Current.Value currbblb = self.bb[0].LowerBand.Current.Value macd_hist_0 = self.macdtm[0].Current.Value - self.macdtm[0].Signal.Current.Value macd_hist_1 = self.macdtm[1].Current.Value - self.macdtm[1].Signal.Current.Value macd_hist_2 = self.macdtm[2].Current.Value - self.macdtm[2].Signal.Current.Value macd_hist_3 = self.macdtm[3].Current.Value - self.macdtm[3].Signal.Current.Value
Mfundo Zubane
@Gurumeher THANK YOU SO MUCH!!!! I truly appreciate your help with this. Everything is now working except for lines 119 to 126. Eveytime Itry backtest, I get the following error: "'IndicatorDataPoint' object has no attribute 'Current'" Its seems like I can only access the (.Value) data from the rolling windows. Hence, I cant access the Current, UpperBand, LowerBand or Signal data from the bollinger band or MACD. Is there a way access this information?
Gurumeher Sawhney
A potential solution to this can be to change the type of the RollingWindows in Initialize() from IndicatorDataPoint to the object of the indicator itself, i.e. MovingAverageConvergenceDivergence, BollingerBands and RelativeStrengthIndex.
This way, when accessing the objects from the RollingWindow, you have the ability to call any one of the objects' properties.
Faultsaycool
I tried this code but it throws a type error. When using IndicatorDataPoints, it throws an attribute error, saying it has no attribute “current”, and when using the object of the indicator itself, it throws a type error.
Varad Kabade
Hi Xavier Lopez,
In the above algorithm when initializing the RollingWindows' we need to assign the type as IndicatorDataPoint instead of the indicator name. Also, we do not need to use the Current attribute when accessing an IndicatorDatapoint just use the Value attribute. IndicatorDataPoints only store one piece of information. To get the upper/lower band information, we need to create separate RollingWindows that are updated using the upper and lower band's information. Refer to the following thread for more information and an example.
Best,
Varad Kabade
Jackson Dude
Thank you this has been help full for me to.
Mfundo Zubane
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!