finplot icon indicating copy to clipboard operation
finplot copied to clipboard

Problems with Updating finplot Chart When Switching DataFrames

Open IlanKalendarov opened this issue 1 year ago • 11 comments

Requirements (place an x in each of the [ ])**

  • [ x] I realize finplot is not a web lib. (Hint: it's native!)
  • [x ] I've read the snippets and not found what I'm looking for.
  • [x ] I've searched for any related issues and avoided creating a duplicate issue.
  • [x ] I've updated finplot (pip install -U finplot).
  • [x ] I've supplied the required data to run my code below.

Code to reproduce

def update_chart(self, df):
    print("updating chart..")
    self.ax.reset()
    self.axo.reset()
    for item in self.ax.items:
         if isinstance(item, fplt.FinLine):
             fplt.remove_primitive(item)
    self.df = df
    fplt.candlestick_ochl(
        self.df[['date', 'open', 'close', 'high', 'low']], ax=self.ax)

    fplt.refresh()
    print("done updating chart")

Describe the bug

Sometimes, a random pattern of lines or candles appear on top of the chart after switching DataFrames. This pattern doesn't correspond to any data in the DataFrame, and it doesn't happen when the DataFrame is loaded for the first time. It only occurs when I switch DataFrames by clicking on a button in my GUI.

I suspect that finplot might be keeping a reference to the old DataFrame somewhere, which could be causing these issues. However, I'm not sure how to solve this. I would appreciate any help or guidance.

The part where I tried removing the lines did not work and this is what i got inside self.ax.items: [<pyqtgraph.graphicsItems.InfiniteLine.InfiniteLine object at 0x14ca05c10>, <pyqtgraph.graphicsItems.InfiniteLine.InfiniteLine object at 0x14ca05ca0>, <pyqtgraph.graphicsItems.TextItem.TextItem object at 0x14ca05d30>, <pyqtgraph.graphicsItems.TextItem.TextItem object at 0x14ca05e50>]

Note that i used fplt.add_rect and fplt.add_line and labels. I just want to be able to remove those 3 objects from the entire chart when switching between the dfs.

Screenshots

image

Reproducible in:

OS: Mac OS finplot version: 1.9.2 pyqtgraph version: 0.13.3 pyqt version: PyQt6

IlanKalendarov avatar Aug 05 '23 13:08 IlanKalendarov

Looks like you need to run your for loop for removing the primitives before ax.reset().

highfestiva avatar Aug 06 '23 00:08 highfestiva

Looks like you need to run your for loop for removing the primitives before ax.reset().

if I inspect self.ax.items before the reset I do see some finplot object but the reset seems to clear all of those objects and what will be left after are those objects:

[<pyqtgraph.graphicsItems.InfiniteLine.InfiniteLine object at 0x14ca05c10>, <pyqtgraph.graphicsItems.InfiniteLine.InfiniteLine object at 0x14ca05ca0>, <pyqtgraph.graphicsItems.TextItem.TextItem object at 0x14ca05d30>, <pyqtgraph.graphicsItems.TextItem.TextItem object at 0x14ca05e50>] Note that these objects are not of finplot type.

Which I don't use directly on my code, I just use what I said on my first comment. It looks that these objects are the one left on my chart after the reset. Oh I also get this error after switching timeframe and then hovering over the candles:

Inspection error: <class 'RuntimeError'> wrapped C/C++ object of type QGraphicsTextItem has been deleted

IlanKalendarov avatar Aug 06 '23 07:08 IlanKalendarov

Did you try it? Has to do with internal state of finplot.

highfestiva avatar Aug 14 '23 12:08 highfestiva

Also check 3c0f3c63ac46654299ec3e5a40eaa92d4a649990, so you won't have to remove the primitives yourself.

highfestiva avatar Aug 14 '23 16:08 highfestiva

I do it like so:

for item in self.ax.items:
    if isinstance(item, fplt.FinLine) or isinstance(item, fplt.FinPolyLine):
        fplt.remove_primitive(item)

And still get the same results

IlanKalendarov avatar Sep 26 '23 14:09 IlanKalendarov

Did you try 3c0f3c6? Please send me a minimal piece of code that I can use to reproduce the issue.

highfestiva avatar Sep 27 '23 07:09 highfestiva

Did you try 3c0f3c6? Please send me a minimal piece of code that I can use to reproduce the issue.

I don't get what you meant by this because I think I did try. Here is a piece of code, For example I am adding trend lines over the candle tails then I try to delete them

    def add_trend(self):
        for x, (date, high, low, trend) in enumerate(self.df[['date', 'high', 'low', 'trend']].values):
            # Plotting trendlines
            if trend == 'up':
                fplt.add_line((date, low), (date, high),
                              color='#00FF00', width=3, ax=self.ax)
            elif trend == 'down':
                fplt.add_line((date, low), (date, high),
                              color='#FF0000', width=3, ax=self.ax) 

And I try to reset the chart to a different df like so

    def update_chart(self, df):
        print("updating chart..")
        self.ax.reset()
        self.axo.reset()
        self.df = df
        for item in self.ax.items:
            if isinstance(item, fplt.FinLine) or isinstance(item, fplt.FinPolyLine):
                fplt.remove_primitive(item)
        fplt.candlestick_ochl(
            self.df[['date', 'open', 'close', 'high', 'low']], ax=self.ax)
        fplt.refresh()
        print("done updating chart")

IlanKalendarov avatar Sep 27 '23 17:09 IlanKalendarov

I need a complete, minimal example of your problem, including the data required to run it. Otherwise I can't help, sorry.

highfestiva avatar Sep 28 '23 09:09 highfestiva

I need a complete, minimal example of your problem, including the data required to run it. Otherwise I can't help, sorry.

Sorry but the code is kind of complex and I won't be able to just copy and paste it. But, I did some checking and I found something weird. I changed the add_trend function I gave you before to add the lines to a list In order to keep track of them. The list had around 15,000 lines but when inspecting self.ax I had just 80 objects

image

Why can't I see those line objects inside self.ax I add them just like I showed you in the add_trend function.

IlanKalendarov avatar Sep 30 '23 10:09 IlanKalendarov

finplot adds them to the viewport, not the axis, that's why. Try ax.vb to get ahold of those objects.

highfestiva avatar Oct 01 '23 17:10 highfestiva

@IlanKalendarov I'm only able to help if I have some test code to work with. Could you please make a reproducible piece of code that highlights the error?

highfestiva avatar Dec 01 '23 22:12 highfestiva