-
Notifications
You must be signed in to change notification settings - Fork 125
Bug Report: key error in bbands calculatiuon using Candles feature #67
Description
Describe the bug
hi all,
i'm currently trying to calculate volatility using the Candles features,
my code looks like that:
INTERVALS = ["30m"]
VOLATILITY_WINDOW = 100
Volatility(VolatilityConfig(window=VOLATILITY_WINDOW)).calculate(all_candles[INTERVALS[0]][0].data)
and get this:
Cell In[14], line 1
----> 1 all_candles[INTERVALS[0]][0].add_features([Volatility(VolatilityConfig(window=VOLATILITY_WINDOW)), Volume(VolumeConfig(short_term_window=VOLUME_SHORT_WINDOW, long_term_window=VOLUME_LONG_WINDOW))])
File ~/quants-lab/core/data_structures/data_structure_base.py:16, in DataStructureBase.add_features(self, features)
14 def add_features(self, features: List[FeatureBase]):
15 for feature in features:
---> 16 self.data = feature.calculate(self.data)
17 return self
File ~/quants-lab/core/features/candles/volatility.py:41, in Volatility.calculate(self, data)
39 # Bollinger Bands width
40 bbands = ta.bbands(df["close"], length=window)
---> 41 df["bb_width"] = bbands[f"BBB_{window}_2.0"]
43 return df
File ~/miniconda3/envs/quants-lab/lib/python3.12/site-packages/pandas/core/frame.py:4113, in DataFrame.__getitem__(self, key)
4111 if self.columns.nlevels > 1:
4112 return self._getitem_multilevel(key)
-> 4113 indexer = self.columns.get_loc(key)
4114 if is_integer(indexer):
4115 indexer = [indexer]
File ~/miniconda3/envs/quants-lab/lib/python3.12/site-packages/pandas/core/indexes/base.py:3819, in Index.get_loc(self, key)
3814 if isinstance(casted_key, slice) or (
3815 isinstance(casted_key, abc.Iterable)
3816 and any(isinstance(x, slice) for x in casted_key)
3817 ):
3818 raise InvalidIndexError(key)
-> 3819 raise KeyError(key) from err
3820 except TypeError:
3821 # If we have a listlike key, _check_indexing_error will raise
3822 # InvalidIndexError. Otherwise we fall through and re-raise
3823 # the TypeError.
3824 self._check_indexing_error(key)
KeyError: 'BBB_100_2.0'
after a simple investigation on what pandas ta give us back i found this:
the code for calculating the volatility is in the quants-labs/core/features/candles/volatility.py
the culprit is Volatility.calculate() method:
def calculate(self, data):
"""Calculate volatility indicators on data."""
window = self.config.window
df = data.copy()
# Standard deviation of returns
df["volatility"] = df["close"].pct_change().rolling(window=window).std()
# Normalized ATR
df["natr"] = ta.natr(df["high"], df["low"], df["close"], length=window) / 100
# Bollinger Bands width
bbands = ta.bbands(df["close"], length=window)
df["bb_width"] = bbands[f"BBB_{window}_2.0"] #<--- here the culprit line
return df
we can see from the screen that our df have double "_2.0" in the name.
the real problem is that pandas ta build the df name for bb calculation method, adding the "_x.x" to df name based on 2 parameter of the method "lower_std" and "upper_std"(Ref. /pandas_ta/volatility/bbands.py)
looking at the fact that in the volatility.py we can omit these param, in this way we use the defaults that are always 2.0. standardizing the name and adding just a "_2.0" to the culprit line inside of volatility.py should be enogh.
Steps to reproduce bug
- try calculate the volatility using the Candles feature