Hello,
I am trying to create an extended version of the Bollinger Bands indicator that would include the Band Width and %B as described by John Bollinger in its book ‘Bollinger on Bollinger Bands’ (I have also created a GitHub ticket).
I started by copying the code from the Bollinger Bands indicator on GitHub and tried to extend it from there. I ran into the following issues and would appreciate some guidance:
- In the custom indicator file (BBextended.cs), I have tried several things but I could not manage to get the current close price that I need to calculate the %B. I found a way around it which is to use a SMA indicator with a period of 1 (line 10), but I would like to understand how to do that the proper way. Also, to cross check the result, I have plotted the %B calculated from in the indicator vs. a %B calculated in the OnData method and if you look at the %B graph, you will notice that there are some slight differences between the two calculation.
- I wanted to apply a Bollinger Band indicator to the %B value of my custom indicator but I am getting an error. If you uncomment line 48 of ‘SymbolData.cs’ you will see “Cannot implicitly convert type 'QuantConnect.BollingerBandsExtended' to 'QuantConnect.Indicators.BollingerBands'”.
- The BandWidth indicator (line 85 in BBextended.cs) should be multiply by 100 for a cleaner reading. I tried several variations of the code below but I am getting an error. That’s just a minor cosmetic change but it would be good for my understanding to know how to do that.
BandWidth = (UpperBand.Minus(LowerBand).Over(MiddleBand).Times(100m, name + "_BandWidth");
Many thanks!
Rahul Chowdhury
Hey Pi..R,
1. The best way to define PctB is as the combination of other indicators, like LowerBand and UpperBand, which is how you defined it. This way your PctB indicator is automatically updated as the other indicators are updated. By defining the last close price with an SMA of period 1, you can define the PctB entirely as a combination of indicators.
As alternative approach, you could have defined PctB as a decimal; in this situation, you would have to update its value with the current values of the Lower and Upper Bands, and also the last close.
2. You declared BBofBB as BollingerBands
public BollingerBands BBofBB;
But when you define it on line 48 of SymbolData.cs, you defined it as BollingerBandsExtended. Instead you should define it as BollingerBands.
BBofBB = new BollingerBandsExtended(_BBofBBPeriod, _BBofBBxStdv).Of(BBext.PctB); //should be BBofBB = new BollingerBands(_BBofBBPeriod, _BBofBBxStdv).Of(BBext.PctB);
3. You can use indicator extensions here to multiply by 100.
BandWidth = IndicatorExtensions.Times(UpperBand.Minus(LowerBand).Over(MiddleBand, name + "_BandWidth"), 100);
Pi..R
Thank you very much Rahul!
Regarding 2. I corrected the code as you suggested and do no longer get the error, but if you look at the plot “BB ext BandWidth ETHUSD” the values of the Bollinger Bands of the BandWidth are completely off. Can you see what I am still getting wrong?
Pi..R
I solved the issue regarding 2, I just needed to delete line 59
BBofBB.Update(_bar.Time, _bar.Close);
which was overiding the value BandWidth.
The only question I got left is why do I sometime get different values in the %B calculated in the OnData method vs. the one calculated inside the indicator. If you look at the plot called "%B ETHUSD" you will see for example that on October 24, 2019 the value is 0.3906 vs. 0.0822 (quite a difference), while it is otherwise almost exactly the same (rounding error only) most of the time. The value inside the indicator seems to be the wrong one. Are you able to identify what is causing the differences?
Rahul Chowdhury
Hey Pi..R,
The difference between %B Indic and %B Calc is being caused be the difference in price data you're using to calculate. In %B Indic, the price data is coming from the smaPrice indicator, while the price in %B Calc is coming from the bar data for that symbol.
If you check by debugging in OnData
Debug($"%B Indic: {symbolData.BBext.PctB} with smaPrice {symbolData.BBext.smaPrice}"); Debug($"%B Calc: {(symbolData.Price - symbolData.BBext.LowerBand) / (symbolData.BBext.UpperBand - symbolData.BBext.LowerBand)} with price {symbolData.Price}");
You'll see that the prices are mostly near each other, but sometimes they diverge. You can also use the debugger to better understand which prices are being delivered to the indicator. This may help you better understand what is causing the differences.
If the divergences affect your algorithm, I suggest calculating the %B rather than storing it in your BBExtended indicator.
Pi..R
Thanks Rahul, I can see that the price are sometime different between the smaPrice and the bar data, my question is why is it the case. I would expect the 1-period SMA to be always equal to the price in the bar data. I am affraid there is a bug somewhere. Happy to report that as a bug if more appropriate, Please let me know. Thanks
Rahul Chowdhury
Hey Pi..R,
There is a subtle reason why there is a discrepancy. Cryptocurrencies on QC have both quote bar and trade bar data available. When we use
data[symbolData.Symbol].Close, we are accessing the close of the QuoteBar.
However, the data which is fed into the SMA is trade bar data. You can confirm this by checking the difference between % BB Calc and % BB Indic, but using data.Bars[symbolData.Symbol].Close to calculate % BB Calc. You will find that they are now equal.
Pi..R
Awsome! Thank you very much for your help in getting to the bottom of this!
Pi..R
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!