Kismuz / btgym

Scalable, event-driven, deep-learning-friendly backtesting library
https://kismuz.github.io/btgym/
GNU Lesser General Public License v3.0
985 stars 260 forks source link

AttributeError: 'FigureCanvasAgg' object has no attribute 'renderer' / ValueError: Axis limits cannot be NaN or Inf #19

Closed gaitay closed 6 years ago

gaitay commented 6 years ago

Process DrawCerebro-2:1:

Traceback (most recent call last):
  File "/usr/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
    self.run()
  File "/home/git/btgym/btgym/rendering/plotter.py", line 75, in run
    figfilename='_tmp_btgym_render.png',
  File "/home/btgym/lib/python3.5/site-packages/backtrader/cerebro.py", line 991, in plot
    start=start, end=end, use=use)
  File "/home/btgym/lib/python3.5/site-packages/backtrader/plot/plot.py", line 220, in plot
    self.plotdata(data, self.dplotsover[data])
  File "/home/btgym/lib/python3.5/site-packages/backtrader/plot/plot.py", line 634, in plotdata
    data, opens, highs, lows, closes, volumes, vollabel)
  File "/home/btgym/lib/python3.5/site-packages/backtrader/plot/plot.py", line 580, in plotvolume
    ax.set_ylim(0, volylim, auto=True)
  File "/home/btgym/lib/python3.5/site-packages/matplotlib/axes/_base.py", line 3226, in set_ylim
    top = self._validate_converted_limits(top, self.convert_yunits)
  File "/home/btgym/lib/python3.5/site-packages/matplotlib/axes/_base.py", line 2836, in _validate_converted_limits
    raise ValueError("Axis limits cannot be NaN or Inf")
ValueError: Axis limits cannot be NaN or Inf

let self.volume = False then,

Process DrawCerebro-2:1:
Traceback (most recent call last):
  File "/usr/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
    self.run()
  File "/home/git/btgym/btgym/rendering/plotter.py", line 78, in run
    rgb_string = fig.canvas.tostring_rgb()
  File "/home/btgym/lib/python3.5/site-packages/matplotlib/backends/backend_agg.py", line 460, in tostring_rgb
    return self.renderer.tostring_rgb()
AttributeError: 'FigureCanvasAgg' object has no attribute 'renderer'
Kismuz commented 6 years ago

@gaitay , can you provide more details on settings your are running? Does it happens with one of the examples or your own code and data?

gaitay commented 6 years ago

yes it happens with one of the examples, when episode finished.

import gym
from gym import spaces
import backtrader as bt
from btgym import BTgymDataset, BTgymBaseStrategy, BTgymEnv

MyCerebro = bt.Cerebro()
MyCerebro.addstrategy(BTgymBaseStrategy,
                      state_shape={'raw_state': spaces.Box(low=0,high=1,shape=(20,4))},
                      skip_frame=5,
                      state_low=None,
                      state_high=None,
                      drawdown_call=50,
                      )

MyCerebro.broker.setcash(100.0)
MyCerebro.broker.setcommission(commission=0.001)
MyCerebro.addsizer(bt.sizers.SizerFix, stake=10)
MyCerebro.addanalyzer(bt.analyzers.DrawDown)

MyDataset = BTgymDataset(filename='../examples/data/DAT_ASCII_EURUSD_M1_2016.csv',
                         start_weekdays=[0, 1, 2, 4],
                         start_00=True,
                         episode_len_days=0,
                         episode_len_hours=23,
                         episode_len_minutes=55,
                         time_gap_days=0,
                         time_gap_hours=5,
                         )

MyEnvironment = BTgymEnv(dataset=MyDataset,
                         engine=MyCerebro,
                         port=5555,
                         verbose=1,
                         )

observation = MyEnvironment.reset()
for t in range(1000):
    MyEnvironment.render()
    print(observation)
    action = MyEnvironment.action_space.sample()
    observation, reward, done, info = MyEnvironment.step(action)
    if done:
        print("Episode finished after {} timesteps".format(t+1))
tmorgan4 commented 6 years ago

I just spent some time tracking down solutions to both issues.

ValueError: Axis limits cannot be NaN or Inf This is an issue caused by taking max() of an array full of NaNs and appears to be caused by a recent update of matplotlib. It is in the process of being fixed. For the time being, I changed line 130 in backtrader/plot/scheme.py from self.volume = True to self.volume = False to disable volume plots.

AttributeError: 'FigureCanvasAgg' object has no attribute 'renderer' This is an easy fix but took quite a bit of time to track down. Open btgym/rendering/plotter.py and add: fig.canvas.draw() before line 76 where rgb_string is called.

I'm new to Github and not familiar with pull requests so could someone else make this change? Andrew has done an amazing job so far and I'd like to contribute anything I can!

Kismuz commented 6 years ago

@tmorgan4, @gaitay, thank you for tracking this down. Indeed BTgym was developed to use Matplotlib 2.0.2 and crashes when 2.1 version is installed.

Solution: The easiest way until ValueError is not fixed is to use matplotlib v/2.0.2 How to do: It is highly recommended to run BTGym in designated virtual environment. If you reinstalling btgym from scratch - just do nothing as v.2.0.2 is now specified in package dependencies and should install correct version of Matplotlib. Else: downgrade your matplotlib installation (that's where virtual env is handy):

`pip install matplotlib==2.0.2`

Remark to @tmorgan4: I'm a bit paranoid about using fig.canvas.draw() as it potentially can lead to memory leaks. I had very though time fighting that issue when coding it initially. Anyway there is btgym/tests/render_memory_leak_test.ipynb you can try and see if it runs Ok.

gaitay commented 6 years ago

@Kismuz @tmorgan4 Thank you for all your hard work!

gaitay commented 6 years ago

@Kismuz @tmorgan4 Thank you for all your hard work!