atr (and others) indicators not working with resample
- Dominant language
- Python
- Stars
- 9k
- Forks
- 1.5k
- PR merge metrics
- No merged PRs in 30d
Description
Hi, I'm using minute level data:
Dataframe sample
```
Open High Low Close
Date
2020-01-01 22:02:00+00:00 1.32463 1.32464 1.32462 1.32463
2020-01-01 22:03:00+00:00 1.32463 1.32466 1.32462 1.32466
2020-01-01 22:04:00+00:00 1.32466 1.32466 1.32463 1.32463
2020-01-01 22:05:00+00:00 1.32465 1.32466 1.32462 1.32462
2020-01-01 22:06:00+00:00 1.32462 1.32470 1.32462 1.32463
... ... ... ... ...
2020-01-29 23:55:00+00:00 1.30208 1.30208 1.30208 1.30208
2020-01-29 23:56:00+00:00 1.30207 1.30208 1.30207 1.30208
2020-01-29 23:57:00+00:00 1.30208 1.30208 1.30208 1.30208
2020-01-29 23:58:00+00:00 1.30208 1.30208 1.30203 1.30203
2020-01-29 23:59:00+00:00 1.30202 1.30207 1.30202 1.30207
```
I need the average daily range, so I thought I could just resample the atr to daily frequency. So I followed the documentation:
```python
def init(self):
# Average daily range
self.adr = resample_apply('D', ta.atr, self.data.High, self.data.Low, self.data.Close)
```
Error output:
```
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File ~/my_strat/.venv/lib/python3.12/site-packages/backtesting/backtesting.py:150, in Strategy.I(self, func, name, plot, overlay, color, scatter, *args, **kwargs)
149 try:
--> 150 value = func(*args, **kwargs)
151 except Exception as e:
File ~/my_strat/.venv/lib/python3.12/site-packages/backtesting/lib.py:322, in resample_apply..wrap_func(resampled, *args, **kwargs)
321 # Resample back to data index
--> 322 if not isinstance(result.index, pd.DatetimeIndex):
323 result.index = resampled.index
AttributeError: 'numpy.ndarray' object has no attribute 'index'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
Cell In[205], line 73
70 bt = Backtest(data, smr_01, margin = 1/100)
71 # import time
72 # start_time = time.time()
---> 73 stats = bt.run()
74 # end_time = time.time()
75
76 # time_taken = end_time - start_time
(...) 82 # print(f"Number of candlesticks: {num_candlesticks}")
83 # print(f"Candlesticks per second: {candlesticks_per_second}")
84 bt.plot()
File ~/my_strat/.venv/lib/python3.12/site-packages/backtesting/backtesting.py:1296, in Backtest.run(self, **kwargs)
1293 broker: _Broker = self._broker(data=data)
1294 strategy: Strategy = self._strategy(broker, data, kwargs)
-> 1296 strategy.init()
1297 data._update() # Strategy.init might have changed/added to data.df
1299 # Indicators used in Strategy.next()
Cell In[205], line 39, in smr_01.init(self)
37 self.range_25, self.range_50, self.range_75 = self.I(range_levels, self.daily_high, self.daily_low, overlay=True)
38 # Average daily range
---> 39 self.adr = resample_apply('D', ta.atr, self.data.High, self.data.Low, self.data.Close)
40 # self.adr = resample_apply('D', ta.sma, self.data.Close, 14)#, self.data.Low, self.data.Close)
42 self.adr2 = self.I(average_daily_range, self.data.df)
File ~/my_strat/.venv/lib/python3.12/site-packages/backtesting/lib.py:330, in resample_apply(rule, func, series, agg, *args, **kwargs)
326 return result
328 wrap_func.__name__ = func.__name__
--> 330 array = strategy_I(wrap_func, resampled, *args, **kwargs)
331 return array
File ~/my_strat/.venv/lib/python3.12/site-packages/backtesting/backtesting.py:152, in Strategy.I(self, func, name, plot, overlay, color, scatter, *args, **kwargs)
150 value = func(*args, **kwargs)
151 except Exception as e:
--> 152 raise RuntimeError(f'Indicator "{name}" error. See traceback above.') from e
154 if isinstance(value, pd.DataFrame):
155 value = value.values.T
RuntimeError: Indicator "atr(H[D],L,C)" error. See traceback above.
```
However I don't get any error with:
```python
self.sma = resample_apply('D', ta.sma, self.data.Close, 14)
```
So, again following the docs, I tried doing it myself:
```python
def average_daily_range(df, period):
df_resampled = df.resample('D', label='right').agg({'High': 'max', 'Low': 'min', 'Close': 'last'})
print(df_resampled)
df_resampled.dropna()
atr = ta.atr(df_resampled['High'], df_resampled['Low'], df_resampled['Close'], period)
atr = atr.reindex(df.index).ffill()
return atr
class smr_01(Strategy):
def init(self):
# Average daily range
# self.adr = resample_apply('D', ta.atr, self.data.High, self.data.Low, self.data.Close)
self.sma = resample_apply('D', ta.sma, self.data.Close, 14)
self.adr = self.I(average_daily_range, self.data.df, 14)
```
Resampled df:
```
High Low Close
Date
2020-01-02 00:00:00+00:00 1.32608 1.32457 1.32497
2020-01-03 00:00:00+00:00 1.32661 1.31152 1.31467
2020-01-04 00:00:00+00:00 1.31600 1.30531 1.30787
2020-01-05 00:00:00+00:00 NaN NaN NaN
2020-01-06 00:00:00+00:00 1.30855 1.30633 1.30768
2020-01-07 00:00:00+00:00 1.31785 1.30638 1.31711
2020-01-08 00:00:00+00:00 1.32120 1.30948 1.31134
2020-01-09 00:00:00+00:00 1.31694 1.30799 1.31051
2020-01-10 00:00:00+00:00 1.31233 1.30126 1.30691
2020-01-11 00:00:00+00:00 1.30968 1.30422 1.30569
2020-01-12 00:00:00+00:00 NaN NaN NaN
2020-01-13 00:00:00+00:00 1.30441 1.30287 1.30432
2020-01-14 00:00:00+00:00 1.30450 1.29608 1.29859
2020-01-15 00:00:00+00:00 1.30329 1.29542 1.30211
2020-01-16 00:00:00+00:00 1.30582 1.29850 1.30392
2020-01-17 00:00:00+00:00 1.30828 1.30252 1.30760
2020-01-18 00:00:00+00:00 1.31184 1.30050 1.30058
2020-01-19 00:00:00+00:00 NaN NaN NaN
2020-01-20 00:00:00+00:00 1.30071 1.29915 1.30051
2020-01-21 00:00:00+00:00 1.30132 1.29617 1.30035
2020-01-22 00:00:00+00:00 1.30831 1.29952 1.30451
2020-01-23 00:00:00+00:00 1.31525 1.30343 1.31435
2020-01-24 00:00:00+00:00 1.31508 1.30966 1.31186
2020-01-25 00:00:00+00:00 1.31739 1.30565 1.30701
2020-01-26 00:00:00+00:00 NaN NaN NaN
2020-01-27 00:00:00+00:00 1.30799 1.30606 1.30606
2020-01-28 00:00:00+00:00 1.31050 1.30395 1.30588
2020-01-29 00:00:00+00:00 1.30649 1.29752 1.30231
2020-01-30 00:00:00+00:00 1.30273 1.29892 1.30207
```
Now I have a working ATR resampled to daily... But there is a problem, as you may have noticed both sma and atr are resampled daily with a period of 14:

As you see the ATR start on 20 jan 2020 at 12:00, while the SMA start on 17 jan 2020 at 12:00. So am I doing something wrong or is the library that should be updated?
Packages version:
```
Package Version
----------------------- -----------
asttokens 3.0.0
backtesting 0.6.3
bokeh 3.6.3
comm 0.2.2
contourpy 1.3.1
cycler 0.12.1
debugpy 1.8.13
decorator 5.2.1
executing 2.2.0
fonttools 4.56.0
ipykernel 6.29.5
ipython 9.0.0
ipython-pygments-lexers 1.1.1
jedi 0.19.2
jinja2 3.1.6
jupyter-client 8.6.3
jupyter-core 5.7.2
kiwisolver 1.4.8
markupsafe 3.0.2
matplotlib 3.10.1
matplotlib-inline 0.1.7
mplfinance 0.12.10b0
nest-asyncio 1.6.0
numpy 2.2.3
packaging 24.2
pandas 2.2.3
pandas-ta 0.3.14b0
parso 0.8.4
pexpect 4.9.0
pillow 11.1.0
platformdirs 4.3.6
prompt-toolkit 3.0.50
psutil 7.0.0
ptyprocess 0.7.0
pure-eval 0.2.3
pygments 2.19.1
pyparsing 3.2.1
python-dateutil 2.9.0.post0
pytz 2025.1
pyyaml 6.0.2
pyzmq 26.2.1
setuptools 76.0.0
six 1.17.0
stack-data 0.6.3
tornado 6.4.2
traitlets 5.14.3
tzdata 2025.1
wcwidth 0.2.13
xyzservices 2025.1.0
```
Contributor guide
Research direction
Start at backtesting/lib.py's resample_apply wrapper, especially the handling of results returned by ta.atr versus ta.sma. Reproduce the supplied minute-level example with the shown strategy and pandas data, then verify that ATR resampling no longer raises the reported error and that the indicators' daily start times are consistent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- pandas, python
- Domain
- data
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100