pythonpandascsvta-lib

TA-Lib BBANDS returning NaN values


While using the BBANDS function present in TA-Lib to generate upper, middle and lower band values for the close price column in my dataframe, it is returning me only a few rows that contain the respective values, whereas the majority of the rows have NaN values.

df = pd.read_csv("3131.csv", parse_dates=True, index_col="datetime")
df["upper_band"], df["middle_band"], df["lower_band"] = talib.BBANDS(df["close"], timeperiod=10)

Above is the function used to find the values for the respective bands and below are a few sample rows of my csv file.

datetime,open,high,low,close,volume
1996-01-01,15.859429,15.944529,15.754989,15.917452,48051995.0
1996-01-02,15.87877,15.956133,15.677626,15.793671,77875009.0
1996-01-03,16.052837,16.783918,15.87877,15.913584,96602936.0
1996-01-04,15.762726,15.813012,15.553845,15.766594,100099436.0
1996-01-05,15.704703,15.704703,15.5229,15.658285,76935930.0
1996-01-08,15.62734,15.638945,14.876918,15.031645,86288584.0

The first 9 rows are expected to have NaN values, but also after row 1900, all the rows have NaN values. Is there any way that I can compute the BBAND values for all the rows together at once?


Solution

  • I think that the problem is in your CSV file (there may be missing values). Bollinger bands are calculated with SMA (simple moving average), so it is calculated in a sliding period. According to your timeperiod (e.g. 20 days, 10 days) configuration, it calculates. If your time period is 10 days, it cannot calculate the first 9 days as expected. You can also check it (by using data.iloc[9] => 10th day, BBAND calculated; but data.iloc[8] => 9th day, BBAND is NaN),

    Bolling Band (BBAND) Formula (time-period: 20 days):

      * Middle Band = 20-day simple moving average (SMA)
      * Upper Band = 20-day SMA + (20-day standard deviation of price x 2) 
      * Lower Band = 20-day SMA - (20-day standard deviation of price x 2)
    

    Ref: https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands

    The following code works after getting data using yfinance:

    Code:

    import yfinance as yf
    import pandas as pd
    import talib
    
    data = yf.download("AAPL", start="1996-01-01", end="2023-01-01")
    data["upper_band"], data["middle_band"], data["lower_band"] = talib.BBANDS(data["Close"], timeperiod=10)
    print(data)
    

    Output:

    [*********************100%%**********************]  1 of 1 completed
                      Open        High         Low       Close   Adj Close     Volume  upper_band  middle_band  lower_band
    Date
    1996-01-02    0.287946    0.287946    0.283482    0.286830    0.243140  139294400         NaN          NaN         NaN
    1996-01-03    0.285714    0.293527    0.284598    0.286830    0.243140  429833600         NaN          NaN         NaN
    1996-01-04    0.289063    0.289063    0.280134    0.281808    0.238883  300182400         NaN          NaN         NaN
    1996-01-05    0.282366    0.305804    0.280134    0.305804    0.259224  445928000         NaN          NaN         NaN
    1996-01-08    0.308036    0.316964    0.303571    0.309152    0.262062  121340800         NaN          NaN         NaN
    ...                ...         ...         ...         ...         ...        ...         ...          ...         ...
    2022-12-23  130.919998  132.419998  129.639999  131.860001  131.127060   63814900  147.186911   136.839000  126.491089
    2022-12-27  131.380005  131.410004  128.720001  130.029999  129.307236   69007800  145.080385   135.392999  125.705614
    2022-12-28  129.669998  131.029999  125.870003  126.040001  125.339409   85438400  142.000876   133.449999  124.899123
    2022-12-29  127.989998  130.479996  127.730003  129.610001  128.889572   75703700  137.879145   132.089999  126.300852
    2022-12-30  128.410004  129.949997  127.430000  129.929993  129.207779   77034200  136.519708   131.432998  126.346288
    
    [6798 rows x 9 columns]