Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bt.plot(): TypeError: float() argument must be a string or a real number, not 'Timestamp' #906

Open
trueToastedCode opened this issue Feb 9, 2023 · 5 comments
Labels
help wanted Extra attention is needed

Comments

@trueToastedCode
Copy link

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
@kernc
Copy link
Owner

kernc commented Feb 10, 2023

Does one of your indicators return an array of timestamps?

@kernc kernc added the bug Something isn't working label Feb 10, 2023
@trueToastedCode
Copy link
Author

trueToastedCode commented Feb 10, 2023

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)

@kernc
Copy link
Owner

kernc commented Feb 10, 2023

Maybe Strategy.I should try to coerce the returned values to floats (or fail).

value = try_(lambda: np.asarray(value, order='C'), None)

@kernc kernc reopened this Feb 10, 2023
@kernc kernc added the good first issue Good for newcomers label Feb 10, 2023
@kernc kernc added help wanted Extra attention is needed and removed bug Something isn't working good first issue Good for newcomers labels Mar 2, 2023
@datatalking
Copy link

I could take a look at this

Maybe Strategy.I should try to coerce the returned values to floats (or fail).

value = try_(lambda: np.asarray(value, order='C'), None)

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
Screen Shot 2023-03-19 at 1 40 46 PM

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
Screen Shot 2023-03-19 at 1 42 09 PM

@kernc
Copy link
Owner

kernc commented Apr 1, 2023

@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:

mean = float(pd.Series(arr).mean())

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:

value = try_(lambda: np.asarray(value, order='C'), None)

(i.e. np.asarray(..., dtype=float, ...)), but I now think it's better to coerce later, on the faulty plotting line itself:
mean = float(pd.Series(arr).mean())

(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. 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants