Hello,
1) Donchian Channel Indicator gets ready before the input period (I guess it is 3 period less than the input). It calculates the highest high according to this intrinsic period. Log file:
https://www.quantconnect.com/backtest/56893/1940861/4dfcad20762ba4e8c22f52f67b1120b8-log.txt
2) How do I initialize it with historical data? I work on AlgorithmFramework structure and warm-up period didn't work. I tried something like the following from the example, but the I couldn't figure out what the format of the historical input has to be.
history = algorithm.History(addedSymbols, self.period, self.resolution)
ticker = SymbolCache.GetTicker(symbol)
# ???
self.donchian.Update(history.loc[ticker].Index, history.loc[ticker])
# ???
Best,
Atacan
Jing Wu
If you use self.DCH(), the indicator will be updated automatically. You don't need self.RegisterIndicator(). You only need to initialize the indicator with Update().
For indicator constructor DonchianChannel("Donchian", period), you can use the Update() method to initialize the indicator and then use RegisterIndicator(symbol, indicator, consolidator) to update the indicator automatically.
This is an IBaseDataBar indicator because the calculation formula uses the open/high/low/close price. You should construct a QuoteBar with
public QuoteBar(
DateTime time,
Symbol symbol,
IBar bid,
decimal lastBidSize,
IBar ask,
decimal lastAskSize,
Nullable<TimeSpan> period
)
Please check the documentation.
Hello Jing Wu ,
thank you. I applied your suggestion into 'framework' structure.
The donchian.UpperBand gets a value in the second period but donchian.LowerBand waits for 7 periods and is zero until then.
Why is it so?
https://www.quantconnect.com/backtest/56893/1947678/8d66b6ccfbb0b1d14960c14c745c02ef-log.txt
Best,
AD
Jing Wu
Hi Atacan,
The issue lies in the lastBidSize and lastAskSize. To construct the quote bar, we can not set their values to be None. The correct syntax should be
history = self.History([eurusd.Symbol], 10, Resolution.Daily)
for tuple in history.itertuples():
bar = QuoteBar(tuple.Index-timedelta(days=1),
eurusd.Symbol,
Bar(tuple.bidclose, tuple.bidhigh, tuple.bidlow, tuple.bidopen),
0,
Bar(tuple.askclose, tuple.askhigh, tuple.asklow, tuple.askopen),
0,
timedelta(days=1))
self.donchian.Update(bar)
There's also a typo in your algorithm (the fourth argument of Bar() method is tuple.bidopen instead of symbolData.Symbol.
bar = QuoteBar(tuple.Index, symbolData.Symbol,
Bar(tuple.bidclose,tuple.bidhigh,tuple.bidlow, tuple.bidopen), 0,
Bar(tuple.askclose,tuple.askhigh,tuple.asklow, tuple.askopen), 0,
timedelta(days=1)
Jing Wu hi,
I get this error:
Runtime Error: This is a forward only indicator: EURUSD Input: 2017-01-17 00:00:00Z Previous: 2017-01-17 19:00:00Z System.ArgumentException: This is a forward only indicator: EURUSD Input: 2017-01-17 00:00:00Z Previous: 2017-01-17 19:00:00Z at QuantConnect.Indicators.IndicatorBase`1[T].Update (QuantConnect.Data.IBaseData input) [0x00063] in <40d1fbb2cc70483296faea5271a51178>:0 at QuantConnect.Algorithm.QCAlgorithm+<>c__DisplayClass477_0`1[T].b__1 (System.Object sender, QuantConnect.Data.IBaseData consolidated) [0x0000e] in :0 at QuantConnect.Data.Consolidators.DataConsolidator`1[TInput].OnDataConsolidated (QuantConnect.Data.IBaseData consolidated) [0x00010] in <3e4e2fe8d2794d82ba00323e20cf5973>:0 at QuantConnect.Data.Consolidators.PeriodCountConsolidatorBase`2[T, TConsolidated].OnDataConsolidated (TConsolidated e) [0x00001] in <3e4e2fe8d2794d82ba00323e20cf5973>:0 at QuantConnect.Data.Consolidators.PeriodCountConsolidatorBase`2[T, TConsolidated].Scan (System.DateTime currentLocalTime) [0x000a8] in <3e4e2fe8d2794d82ba00323e20cf5973>:0 at QuantConnect.Lean.Engine.AlgorithmManager.Run (QuantConnect.Packets.AlgorithmNodePacket job, QuantConnect.Interfaces.IAlgorithm algorithm, QuantConnect.Lean.Engine.DataFeeds.IDataManager dataManager, QuantConnect.Lean.Engine.DataFeeds.ISynchronizer synchronizer, QuantConnect.Lean.Engine.TransactionHandlers.ITransactionHandler transactions, QuantConnect.Lean.Engine.Results.IResultHandler results, QuantConnect.Lean.Engine.RealTime.IRealTimeHandler realtime, QuantConnect.Lean.Engine.Server.ILeanManager leanManager, QuantConnect.Lean.Engine.Alpha.IAlphaHandler alphas, System.Threading.CancellationToken token) [0x010f2] in Lean.Engine.Alpha.IAlphaHandler alphas, System.Threading.CancellationToken token) [0x010f2] in <20fbd5016b124364957b82e900d74eac>:0
I am confused also about the order of OHLC. Isn't it by standard in this order?
https://www.quantconnect.com/lean/documentation/topic24273.html Here it says OLHC.
Your correction is CHLO.
comment does not see the latest version. I paste the code
import numpy as np from datetime import timedelta from Alphas.EmaCrossAlphaModel import EmaCrossAlphaModel from Risk.NullRiskManagementModel import NullRiskManagementModel class BasicTemplateFrameworkAlgorithm(QCAlgorithmFramework): def Initialize(self): # self.SetWarmUp(10) self.SetStartDate(2018, 1, 18) #Set Start Date self.SetEndDate(2018, 10, 18) #Set End Date self.SetCash(1000) #Set Strategy Cash self.SetBrokerageModel(BrokerageName.OandaBrokerage,AccountType.Margin) self.UniverseSettings.Resolution = Resolution.Daily symbols = [Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda), Symbol.Create("GBPUSD", SecurityType.Forex, Market.Oanda)] self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) ) self.SetAlpha(customAlpha()) self.SetPortfolioConstruction(NullPortfolioConstructionModel()) self.SetExecution(NullExecutionModel()) self.SetRiskManagement(NullRiskManagementModel()) def OnOrderEvent(self, orderEvent): if orderEvent.Status == OrderStatus.Filled: # self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol)) pass class customAlpha(AlphaModel): def __init__(self): self.resolution = Resolution.Daily self.symbolDataBySymbol = {} def Update(self, algorithm, data): insights = [] for symbol, symbolData in self.symbolDataBySymbol.items(): algorithm.Log("Upper:"+ str(symbolData.donchian.UpperBand)+"Lower:"+ str(symbolData.donchian.LowerBand)) return insights def OnSecuritiesChanged(self, algorithm, changes): addedSymbols = [ x.Symbol for x in changes.AddedSecurities if x.Symbol not in self.symbolDataBySymbol] if len(addedSymbols) == 0: return history = algorithm.History(addedSymbols, 10, self.resolution) for symbol in addedSymbols: symbolData = SymbolData(algorithm, symbol, self.resolution) self.symbolDataBySymbol[symbol] = symbolData ticker = SymbolCache.GetTicker(symbol) for tuple in history.loc[ticker].itertuples(): bar = QuoteBar(tuple.Index, symbolData.Symbol , Bar(tuple.bidopen,tuple.bidhigh,tuple.bidlow, tuple.bidclose) , 0 , Bar(tuple.askopen,tuple.askhigh,tuple.asklow, tuple.askclose) , 0 ,timedelta(days=1) ) symbolData.donchian.Update( bar) class SymbolData: '''Contains data specific to a symbol required by this model''' def __init__(self, algorithm, symbol, resolution): self.Symbol = symbol self.resolution = resolution self.donch_period = 7 self.ticker = SymbolCache.GetTicker(symbol) self.donchian = DonchianChannel(self.ticker, self.donch_period, self.donch_period) algorithm.RegisterIndicator(self.Symbol, self.donchian, self.resolution)
Jing Wu
Sorry I made a mistake here. The time index in history request is the bar end time. When we create the QuoteBar with QuoteBar(time, symbol, bid, lastBidSize, ask, lastAskSize, period), the "time" argument should be the bar start time. Then the bar end time is time + period.
To fix this issue, you need to subtract the unit time interval from the end time index in history request. For example, you use the daily history price to update the indicator, the "time" argument should be "tuple.Index-timedelta(days=1)". Please see the attached algorithm
For the order of OHLC in bar construction, you need to refer to the LEAN class documentation (search "Bar Constructor ") and follow the syntax
public Bar( decimal open, decimal high, decimal low, decimal close )https://www.quantconnect.com/lean/documentation/topic23998.html
hello Jing Wu
Thank you very much.
FYI: Before this, the bands were being updated with every new bar. i.e. the UpperBand became equal to the current bar's high. I did not want that behaviour and defined a variable like "previous_band". After changing the first parameter, now it does not take the current bar into account and gives the highest high of only the previous n bars.
However, for another strategy I might need it to be updated with every bar. How would it be possible?
Jing Wu
Now you only use the Update() to warm-up the indicator. Instead of using RegisterIndicator(), you can also use Update() to update the indicator value with the current bar value manually.
# if manually update the indciator with the daily bar, remove the RegisterIndicator() def Update(self, algorithm, data): for symbol, symbolData in self.symbolDataBySymbol.items(): if data.ContainsKey(symbol): quoteBar = data[symbol] symbolData.donchian.Update(quoteBar)
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!