Back

Rolling window of consolidated indicator data

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. 

Update Backtest







# 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

0

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
0

@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? 

0

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.

0

Update Backtest





0

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.


Loading...

This discussion is closed