Back to Community
bollinger bands with talib: garbage in , garbage out?

Hi guys,

Take a look at the recordings of the bollinger band function I've pieced together from different examples on this site. For the love of me, I cannot get the data to correspond to the values I get when using Interactive Brokers, Tradingview or Stockcharts.

I imagine talib has been tested and vetted to the max. So the error is obviously in my code. But what's wrong?

Here's a link to the same chart in stockcharts, in which I indicate on which days closing price ends above or below a bollinger band set at 2 standard deviations with a 14 day setting.

stockcharts NFLX chart for same periods

As you see, the price closed above bollingers 4 times and below 4 times over the period in question. The results in my Q program are quite different The price seems to only close above the bollinger once on March 29. I understand there will be slight deviations on how different programs report pricing on given days, but this should also cause the bollinger calculations to move proportionately, and therefore not affect the overall trigger decisions.

Also check out the upper bollinger on Jan 27. It reads around 112.68 at at time Stockcharts shows it to be 120! In percentage terms, these are enormous differences.

The resulting errors are so wide that a strategy that otherwise can make money becomes a losing one. Hopefully someone can solve this for me, and if not, at least others can be alerted to this problem and save themselves a lot of grief.

Thanks for any input or critiques.

Clone Algorithm
6
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5870198ffa9f0f63c657c8ec
There was a runtime error.
5 responses

Your code here:

    if unit == "d":  
        unit = "1d"  
        if interval < 15:  
            period = 10 # there are 10 days in a two week period makes more sense to me than 9-12 that John Bollinger advocated  
        else:  
            period = 12 # there are 12 months in the year.  
    elif unit == "m":  
        unit = "1m"  
        period = 8 # there are 8 hours in a normal working day  
    else:  
        unit = "1d" # kludge that needs to be fixed  
        if interval < 15:  
            period = 10 # there are 10 days in a two week period makes more sense to me than 9-12 that John Bollinger advocated  
        else:  
            period = 12 # there are 12 months in the year.  

changes your interval of 14 you put in to 10 so you are actually getting the BB of the wrong interval when comparing it to your netflix sample chart which is at BB of 14. When I changed that it showed more accurately. Also quantopian isnt known for it's accurate charts because after a certain time it condenses the data into bigger chunks. If you were to run this algo in paper trading mode you could look at and compare to the current BB from a website like tradingview and it should be pretty close. You can also add logging functions that will print out the date and time it crossed the BB exactly. I added an example of this to your handle data but forgot that it spits out every minute so it needs to be tweaked a bit to be more readable

Clone Algorithm
5
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5870276ec6340b6230f9c3d5
There was a runtime error.

Luke,

Thanks for that catch. Can't believe I let that error creep in. Yes the figures now come much closer to stockcharts. But they are still off in proportion to underlying data. If you check the sample you ran, you'll see there are only times prices exceeded the upper and lower bands, as opposed to 4 with IB, stockcharts or tradingview. That could mean missing important trades.

Found the solution I think. It has to do with the way quantopian data every minute vs the way other chart websites display graphs with a simple open/high/low/close. As I said before the best way is to use log messages. When quantopian records the graph every minute through the day it compresses it before showing it to you in the backtest graph. I'm not sure if this causes rounding errors or what but when I print a log and record the graphs and calculate the BB only AT the closing minute of every day instead of every minute of the day it shows all 4 upper and lower crosses in the log. The other website also calculates it's BB only from the closing price of each day, not the full intra-day price that will change the results depending on how you calculate it. assuming you are trading based on the closing price you won't actually be able to trade on that data until the NEXT day at which point quantopian history function gives you the true closing price. So don't worry that the value it shows you as the "price" isn't the true closing price aka 105.74 vs 105.7 on 4/1. You need to calculate the BB for the previous day in before_trading_start() using the history returned closing price of the previous day. That would give you exact results.

2016-01-04 14:59 market_close:89 DEBUG 109.85 below lower 111.457974588  
2016-01-05 14:59 market_close:89 DEBUG 107.65 below lower 108.933944942  
2016-01-13 14:59 market_close:89 DEBUG 106.73 below lower 106.762367571  
2016-01-27 14:59 market_close:89 DEBUG 91.05 below lower 91.8525083541  
2016-03-01 14:59 market_close:87 DEBUG 98.17 above upper 97.9048424833  
2016-03-04 14:59 market_close:87 DEBUG 101.77 above upper 101.499611392  
2016-03-29 14:59 market_close:87 DEBUG 104.25 above upper 103.1972272  
2016-04-01 14:59 market_close:87 DEBUG 105.74 above upper 105.140814321  
End of logs.  
Clone Algorithm
3
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5870427420e68661eead3149
There was a runtime error.

Serge,

I have calculated BB Bands myself

upper1 = prices.mean() + nbdevup*np.std(prices)  
lower1 = prices.mean() - nbdevdn*np.std(prices)  

and got perfect match with the results talib.BBANDS

upper, middle, lower = talib.BBANDS(prices, period, nbdevup, nbdevdn)  

The difference with other software may be resulting from different ways of calculating std or difference in data or different way to calculate middle.

Clone Algorithm
9
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 58707eb313cf9262a2fc16ac
There was a runtime error.

Thanks to both of you guys, Luke and Vladimir.
So conclusion is talib bollinger calc is ok and can be used. Don't be discouraged by apparent inaccuracies in graphical display.

Sh#$($($([email protected]#@$$%t, here I was hoping I could blame a poor instrument on my lousy trading results... Back to the drawing board!