highfestiva / finplot

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

If ax.disable_x_index() is set up then the chart is disappeared after update_gfx() #484

Open fmvin opened 10 months ago

fmvin commented 10 months ago

Code to reproduce

def updates():
    # data is updated on each call
    if first_call_flag:
          plots={}
          plots["data"] =fplt.plot(data, width=3, color='magenta', legend='data', style='-',ax=ax)
          fplt.refresh()
    else:
          plots["data"].update_data(data, gfx=False)
          for k in plots:
              plots[k].update_gfx()
    first_call_flag = False
#
first_call_flag = True
plots={}
ax = fplt.create_plot('Test', rows=1, init_zoom_periods=300)
ax.disable_x_index()
fplt.timer_callback(updates, 2)
fplt.show()

Describe the bug

I borrowed chart update logic from the complicated.py example. The X axis is not a time series. Correct plot is shown first time if first_call_flag is True. But after calling update_gfx() the plot becomes empty. Also any realtime plot's updates produce the same result if ax.disable_x_index() is used.

The data looks like this:

             vol
price             
83000        33.18
83500        31.14
84000        29.13
...

price is a index and X axis values, vol is Y axis values

Expected behavior

To see updated data on the plot.

Reproducible in:

OS: Windows 2019 Server finplot version: 1.9.3 pyqtgraph version: 0.13.3 pyqt version: 6.6.1

highfestiva commented 10 months ago

I attempted setting ax.disable_x_index() in the complicated.py example, and that still worked. Please supply a complete, minimal example (containing the required data, if any).

fmvin commented 10 months ago

@highfestiva, for example, I changed line 35 in overlay-correlate.py to:

fp=fplt.plot(dfc, style='o', color=1, ax=ax2)
fp.update_data(dfc,gfx=True)

Dots on subplot 2 have disappeared.

fmvin commented 10 months ago

@highfestiva , this is complete, minimal example. Please comment line 13 ax.disable_x_index() to see a difference.

import pandas as pd
import numpy as np
import finplot as fplt
#
smile = None
def update_data():
    global smile
    smile=smile**1.04
    plots["one"].update_data(smile, gfx=False)
    plots["one"].update_gfx()
#
ax = fplt.create_plot('Smiles', rows=1, init_zoom_periods=300)
ax.disable_x_index()
plots={}
x=np.arange(-20, 20, 1, dtype=int)
y= x**2*1e-2
x=83000+x*500
smile = pd.DataFrame({'price': x, 'vol':y})
smile = smile.set_index('price')
plots['one']=fplt.plot(smile, width=3, ax=ax)
fplt.timer_callback(update_data, 2)
fplt.show()
fmvin commented 10 months ago

Also I noticed that on X axis some labels are missed.

test1

highfestiva commented 10 months ago

Ah, check if 2df5abda6d076222a356b737f5149eb904274dc2 does the trick.

fmvin commented 10 months ago

Good. Charts are shown after update with ax.disable_x_index(). But still some X-axis labels are missed and zoom works strange. I need a time to formulate zoom problem if it's not related to my code.

highfestiva commented 10 months ago

It's caused by pyqtgraph.AxisItem.tickValues() default implementation. As you see in finplot's __init__.py:118, I check if it isn't x-indexed, and if so, I use pyqtgraph's default implementation. If you like, you can inherit the finplot.EpochAxisItem class and override the def tickValues(self, minVal, maxVal, size) function. Then you only need to set the finplot._create_axis method so your override is used instead of the default finplot.EpochAxisItem. GL!

fmvin commented 9 months ago

@highfestiva, please help me with the zoom problem I mentioned before. In the example above the one line was removed to prevent data modifications.

smile=smile**1.04

The problem is if zoom in is made by right mouse then on next update the zoom is reset automatically. How to make the zoom remain in a state I selected?

highfestiva commented 9 months ago

Perhaps you're looking for finplot.y_pad is defaults to 0.03? I.e. 3% margin at the top and the bottom of the charts?

fmvin commented 9 months ago

finplot.y_pad=0.03 by default in my environment. I've tested different values for y_pad right now with no success. Zoom returns to default state back on each update_data() invoke.

fmvin commented 9 months ago

"A picture is worth a thousand words". This gif demonstrates the problem.The zoomed area resets after each data update.

2024-01-28 09-21-23

highfestiva commented 9 months ago

This zoom comes from pyqtgraph, and is not removed by finplot. But also no particular support has been added to it. To disable auto-y-zooming, you could temporarily set ax.vb.update_y_zoom to a dummy function, so no zooming takes place after you manually change the zoom area in both X and Y. You would then have to reset it whenever you'd want to use the auto-y-zoom feature again.