highfestiva / finplot

Performant and effortless finance plotting for Python
MIT License
935 stars 187 forks source link

[BUG] Crush when attempting to plot two volumes #505

Closed MarcoTrevisiol closed 8 months ago

MarcoTrevisiol commented 8 months ago

Requirements

Code to reproduce

import finplot as fplt
import pandas as pd

enough_periods = 3073
irrelevant_date = "2000-01-01"

df = pd.DataFrame({"O": 1, "C": 1, "V": 1}, index=(pd.date_range(start=irrelevant_date, periods=enough_periods)))

fplt.volume_ocv(df)
fplt.volume_ocv(df)

finplot.show()

Describe the bug

Application crush when attempting to plot two volumes in the same ax, when there is enough data to issue a resample.

The above example gets me the following exception:

Traceback (most recent call last):
  File "C:\Users\main\source\minimal-example.py", line 12, in <module>
    finplot.show()
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1973, in show
    refresh()
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1965, in refresh
    _repaint_candles()
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 2616, in _repaint_candles
    _end_visual_update(item)
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 2580, in _end_visual_update
    item.repaint()
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1180, in repaint
    self.paint(None)
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1185, in paint
    self.update_dirty_picture(self.viewRect())
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1195, in update_dirty_picture
    self._generate_picture(visibleRect)
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1202, in _generate_picture
    self.generate_picture(self.cachedRect)
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 1246, in generate_picture
    df,origlen = self.datasrc.rows(5, left, right, yscale=self.ax.vb.yscale, resamp=self.resamp)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 497, in rows
    return self._rows(df, colcnt, yscale=yscale, lod=lod, resamp=resamp), origlen
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\main\anaconda3\Lib\site-packages\finplot\__init__.py", line 507, in _rows
    dfr = df.iloc[:,colidxs]
          ~~~~~~~^^^^^^^^^^^
  File "C:\Users\main\anaconda3\Lib\site-packages\pandas\core\indexing.py", line 1184, in __getitem__
    return self._getitem_tuple(key)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\main\anaconda3\Lib\site-packages\pandas\core\indexing.py", line 1690, in _getitem_tuple
    tup = self._validate_tuple_indexer(tup)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\main\anaconda3\Lib\site-packages\pandas\core\indexing.py", line 966, in _validate_tuple_indexer
    self._validate_key(k, i)
  File "C:\Users\main\anaconda3\Lib\site-packages\pandas\core\indexing.py", line 1612, in _validate_key
    raise IndexError("positional indexers are out-of-bounds")
IndexError: positional indexers are out-of-bounds

Findings

The problem is caused by the method PandasDataSource._resample, only when there is more than "lod_candles" in ._rows method, and only when I added the second volume chart. The problem with such method is due to a mismatch between the resample procedure and the computation of the "colidxs" on the basis of "self.col_data_offset", which works correctly if "df" is not resampled.

I think it should be easy to correct this bug by resampling every columns in "df" and not only the required columns, but I do not know the implications of such a change.

Reproducible in:

OS: Windows 11 (conda installation) finplot version: 1.9.4 pyqtgraph version: 0.13.4 pyqt version: 6.4.0

highfestiva commented 8 months ago

You can set your plot.resamp = None temporarily to circumvent the issue, and I'll have a look when I have time. Please keep this issue opened, thanks!

highfestiva commented 8 months ago

Nice catch, sorry about the delay. Fix in 86469fd.

MarcoTrevisiol commented 8 months ago

Now it is working! Thank you very much!