Plotting result in TypeError: Index.get_loc() got an unexpected keyword argument 'method'
Expected Behavior
Plotting should work.
Actual Behavior
Fails, but only using large dataframe.
>>> bt.plot()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [86], in <cell line: 1>()
----> 1 bt.plot()
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/backtesting/backtesting.py:1592, in Backtest.plot(self, results, filename, plot_width, plot_equity, plot_return, plot_pl, plot_volume, plot_drawdown, smooth_equity, relative_equity, superimpose, resample, reverse_indicators, show_legend, open_browser)
1589 raise RuntimeError('First issue `backtest.run()` to obtain results.')
1590 results = self._results
-> 1592 return plot(
1593 results=results,
1594 df=self._data,
1595 indicators=results._strategy._indicators,
1596 filename=filename,
1597 plot_width=plot_width,
1598 plot_equity=plot_equity,
1599 plot_return=plot_return,
1600 plot_pl=plot_pl,
1601 plot_volume=plot_volume,
1602 plot_drawdown=plot_drawdown,
1603 smooth_equity=smooth_equity,
1604 relative_equity=relative_equity,
1605 superimpose=superimpose,
1606 resample=resample,
1607 reverse_indicators=reverse_indicators,
1608 show_legend=show_legend,
1609 open_browser=open_browser)
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/backtesting/_plotting.py:203, in plot(results, df, indicators, filename, plot_width, plot_equity, plot_return, plot_pl, plot_volume, plot_drawdown, smooth_equity, relative_equity, superimpose, resample, reverse_indicators, show_legend, open_browser)
201 # Limit data to max_candles
202 if is_datetime_index:
--> 203 df, indicators, equity_data, trades = _maybe_resample_data(
204 resample, df, indicators, equity_data, trades)
206 df.index.name = None # Provides source name @index
207 df['datetime'] = df.index # Save original, maybe datetime index
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/backtesting/_plotting.py:153, in _maybe_resample_data(resample_rule, df, indicators, equity_data, trades)
150 return f
152 if len(trades): # Avoid pandas "resampling on Int64 index" error
--> 153 trades = trades.assign(count=1).resample(freq, on='ExitTime', label='right').agg(dict(
154 TRADES_AGG,
155 ReturnPct=_weighted_returns,
156 count='sum',
157 EntryBar=_group_trades('EntryTime'),
158 ExitBar=_group_trades('ExitTime'),
159 )).dropna()
161 return df, indicators, equity_data, trades
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/resample.py:329, in Resampler.aggregate(self, func, *args, **kwargs)
321 @doc(
322 _shared_docs["aggregate"],
323 see_also=_agg_see_also_doc,
(...)
327 )
328 def aggregate(self, func=None, *args, **kwargs):
--> 329 result = ResamplerWindowApply(self, func, args=args, kwargs=kwargs).agg()
330 if result is None:
331 how = func
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/apply.py:163, in Apply.agg(self)
160 return self.apply_str()
162 if is_dict_like(arg):
--> 163 return self.agg_dict_like()
164 elif is_list_like(arg):
165 # we require a list, but not a 'str'
166 return self.agg_list_like()
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/apply.py:420, in Apply.agg_dict_like(self)
417 results = {key: colg.agg(how) for key, how in arg.items()}
418 else:
419 # key used for column selection and output
--> 420 results = {
421 key: obj._gotitem(key, ndim=1).agg(how) for key, how in arg.items()
422 }
424 # set the final keys
425 keys = list(arg.keys())
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/apply.py:421, in <dictcomp>(.0)
417 results = {key: colg.agg(how) for key, how in arg.items()}
418 else:
419 # key used for column selection and output
420 results = {
--> 421 key: obj._gotitem(key, ndim=1).agg(how) for key, how in arg.items()
422 }
424 # set the final keys
425 keys = list(arg.keys())
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/groupby/generic.py:269, in SeriesGroupBy.aggregate(self, func, engine, engine_kwargs, *args, **kwargs)
266 return self._python_agg_general(func, *args, **kwargs)
268 try:
--> 269 return self._python_agg_general(func, *args, **kwargs)
270 except KeyError:
271 # KeyError raised in test_groupby.test_basic is bc the func does
272 # a dictionary lookup on group.name, but group name is not
273 # pinned in _python_agg_general, only in _aggregate_named
274 result = self._aggregate_named(func, *args, **kwargs)
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/groupby/generic.py:288, in SeriesGroupBy._python_agg_general(self, func, *args, **kwargs)
285 f = lambda x: func(x, *args, **kwargs)
287 obj = self._obj_with_exclusions
--> 288 result = self.grouper.agg_series(obj, f)
289 res = obj._constructor(result, name=obj.name)
290 return self._wrap_aggregated_output(res)
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/groupby/ops.py:994, in BaseGrouper.agg_series(self, obj, func, preserve_dtype)
987 if len(obj) > 0 and not isinstance(obj._values, np.ndarray):
988 # we can preserve a little bit more aggressively with EA dtype
989 # because maybe_cast_pointwise_result will do a try/except
990 # with _from_sequence. NB we are assuming here that _from_sequence
991 # is sufficiently strict that it casts appropriately.
992 preserve_dtype = True
--> 994 result = self._aggregate_series_pure_python(obj, func)
996 npvalues = lib.maybe_convert_objects(result, try_float=False)
997 if preserve_dtype:
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/groupby/ops.py:1015, in BaseGrouper._aggregate_series_pure_python(self, obj, func)
1012 splitter = self._get_splitter(obj, axis=0)
1014 for i, group in enumerate(splitter):
-> 1015 res = func(group)
1016 res = libreduction.extract_result(res)
1018 if not initialized:
1019 # We only do this validation on the first iteration
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/pandas/core/groupby/generic.py:285, in SeriesGroupBy._python_agg_general.<locals>.<lambda>(x)
283 def _python_agg_general(self, func, *args, **kwargs):
284 func = com.is_builtin_func(func)
--> 285 f = lambda x: func(x, *args, **kwargs)
287 obj = self._obj_with_exclusions
288 result = self.grouper.agg_series(obj, f)
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/backtesting/_plotting.py:148, in _maybe_resample_data.<locals>._group_trades.<locals>.f(s, new_index, bars)
145 if s.size:
146 # Via int64 because on pandas recently broken datetime
147 mean_time = int(bars.loc[s.index].view(int).mean())
--> 148 new_bar_idx = new_index.get_loc(mean_time, method='nearest')
149 return new_bar_idx
TypeError: Index.get_loc() got an unexpected keyword argument 'method'
Steps to Reproduce
def CLOSE():
return df.Close
def ATR():
return df.ATR
def SIGNAL():
return df.TRADE_SIGNAL_0
class MyStrategy(Strategy):
def init(self):
super().init()
self.close = self.I(CLOSE)
self.atr = self.I(ATR)
self.signal = self.I(SIGNAL)
def next(self):
global pbar
super().next()
pbar.update(1)
if self.trades:
return
if self.signal == LONG_SIGNAL:
sl = self.close - self.atr * SL_FACTOR
tp = self.close + self.atr * SL_FACTOR * TP_FACTOR
self.buy(sl=sl, tp=tp, size=0.99)
pbar = tqdm(total=len(df))
bt = Backtest(df, MyStrategy, cash=100_000, margin=1/1, commission=0.0)
stats = bt.run()
print(stats)
bt.plot()
[ ! ] Error only occurs when using huge dataframe, in my case it had a length of 499197. Same code however worked when making it smaller.
Additional info
- Backtesting version: 0.3.3
-
bokeh.__version__: 2.4.3 - OS: macOS Ventura (arm64)
hey @trueToastedCode, to save you some time (which I spent digging into this), this issue has been addressed by this commit. Although it is not released, you can just install the most recent version of the library from here
I am getting the same issue on a large dataframe.
When I shrink the dataframe (~1,000 rows), I get a different error message: TypeError: bokeh.models.tools.Toolbar() got multiple values for keyword argument 'logo'
It seems with the latter issue I am also limited by the bokeh developers to release a bug fix.
I have Mac OS Ventura 13.5, M1 chip, Backtesting 0.3.3, Bokeh 3.2.2
To install latest version from repo instead of PYPI, please find instruction in here: https://github.com/kernc/backtesting.py/issues/987#issuecomment-1571602520