bt.plot(): TypeError: float() argument must be a string or a real number, not 'Timestamp'
Expected Behavior
bt.plot()
plot
Actual Behavior
TypeError Traceback (most recent call last)
Cell In[61], 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:613, 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)
611 ohlc_bars = _plot_ohlc()
612 _plot_ohlc_trades()
--> 613 indicator_figs = _plot_indicators()
614 if reverse_indicators:
615 indicator_figs = indicator_figs[::-1]
File ~/miniconda3/envs/tensorflow/lib/python3.10/site-packages/backtesting/_plotting.py:573, in plot.<locals>._plot_indicators()
568 r = fig.line(
569 'index', source_name, source=source,
570 legend_label=LegendStr(legend_label), line_color=color,
571 line_width=1.3)
572 # Add dashed centerline just because
--> 573 mean = float(pd.Series(arr).mean())
574 if not np.isnan(mean) and (abs(mean) < .1 or
575 round(abs(mean), 1) == .5 or
576 round(abs(mean), -1) in (50, 100, 200)):
577 fig.add_layout(Span(location=float(mean), dimension='width',
578 line_color='#666666', line_dash='dashed',
579 line_width=.5))
TypeError: float() argument must be a string or a real number, not 'Timestamp'
stats = bt.run() works fine.. not sure why I can't plot
- Python: 3.10
- Backtesting version: 0.3.3
- bokeh.version: 2.4.3
- OS: MacOS Ventura 13.1
Does one of your indicators return an array of timestamps?
Does one of your indicators return an array of timestamps?
Oh ok, thx, yes i had... Was using
def INDEX():
return mydf.index
def init(self):
super().init()
self.idx = self.I(INDEX)
so I changed it to this to get the values I need
def SIGNAL():
return mydf.TotalSignal
def CLOSE():
return mydf.Close
def init(self):
super().init()
self.signal = self.I(SIGNAL)
self.close = self.I(CLOSE)
Maybe Strategy.I should try to coerce the returned values to floats (or fail).
https://github.com/kernc/backtesting.py/blob/0ce24d80b1bcb8120d95d31dc3bb351b1052a27d/backtesting/backtesting.py#L135
I could take a look at this
Maybe
Strategy.Ishould try to coerce the returned values to floats (or fail).https://github.com/kernc/backtesting.py/blob/0ce24d80b1bcb8120d95d31dc3bb351b1052a27d/backtesting/backtesting.py#L135
option 1. Can someone refresh my memory on the format we are hoping 'Strategy.I' is to keep or use for 'np.asarray', if I understand correctly the proposed solution is to convert the 'Strategy.I' class.function to return the value of 'np.asarray' to floats else fail... but fail if it cannot convert ['int','timestamp'] to a float.
I'm still a noob to the 'Backtesting' package so I haven't read through and memorized this function let alone finished the whole codebase but I had an idea and was curious if this would help.
The places I did find that might make sense were these two screen shots, somewhere starting at line 416

option 2. Would it make sense, and I'm just brainstorming an idea, but what if we added a clean data filter as an assert in '/test/_test.py' that if the data didn't fit the patter 'you specify' the data gets passed to a function that first runs a data_type check and if its wrong it cleans or converts it then passes it was always formatted correctly before being passed to 'Strategy.I'?
or under 'TestUtil' Class with something like 'self.assertdatetime.fromisoformat('2011-11-04T00:05:23+04:00')' per Python 3.11.2

@datatalking Sorry for the late reply (awfully busy these days), and thanks for showing interest. As you can see in the original issue report above, the error happens during plotting, on line:
https://github.com/kernc/backtesting.py/blob/0ce24d80b1bcb8120d95d31dc3bb351b1052a27d/backtesting/_plotting.py#L573
and that only when one of the indicator functions (wrapped in Strategy.I) returns a series of Timestamp values, which then fail since float(mean_timestamp_value) is not defined.
I proposed coercing any indicator-returned values to floats exactly here:
https://github.com/kernc/backtesting.py/blob/0ce24d80b1bcb8120d95d31dc3bb351b1052a27d/backtesting/backtesting.py#L135
(i.e. np.asarray(..., dtype=float, ...)), but I now think it's better to coerce later, on the faulty plotting line itself:
https://github.com/kernc/backtesting.py/blob/0ce24d80b1bcb8120d95d31dc3bb351b1052a27d/backtesting/_plotting.py#L573
(i.e. pd.Series(arr).astype(int).mean()) or some such) so the series of timestamps can remain to be used as such within strategy logic.
In either case, I don't think this has anything to do with tests, other than needing a test to cover this use case when the issue is fixed. :thinking: