finplot icon indicating copy to clipboard operation
finplot copied to clipboard

[BUG] Unable to make an animated candle

Open alessandrogiulianelli opened this issue 1 year ago • 3 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

import finplot as fplt
import pandas as pd
from datetime import timezone

ax = None
df = pd.read_csv(f'./data/EURUSD.FXCM/generated/EURUSD.FXCM_1m.csv',
                 parse_dates=['date'],
                 delimiter=',')
df.index = pd.DatetimeIndex(df['date'])

import random


def animate():
    try:
        fplt.autoviewrestore()
        fplt._savewindata(fplt.windows[0])

        # Sample data
        num = random.random()
        data = [["2024-04-16 00:33:00", 1.06100, 1.06126, 1.06106, 1.06106 + (num - 0.5) / 1000, 2.0]]
        # Add more rows if you have additional data
        animated_df = pd.DataFrame(data, columns=('date', 'open', 'high', 'low', 'close', 'volume'))
        animated_df.index = pd.DatetimeIndex(animated_df['date'])

        price = df['open close high low'.split()]
        animated_df = animated_df['open close high low'.split()]
        price2 = pd.concat([price, animated_df])

        fplt.candlestick_ochl(price2)
        fplt.refresh()
    except Exception as e:
        print(e)
        fplt.close()

if __name__ == '__main__':
    fplt.candle_bull_body_color = fplt.candle_bull_color
    fplt.legend_fill_color = '#fff'
    fplt.legend_text_color = '#000'

    fplt.display_timezone = timezone.utc

    ax = fplt.create_plot('beyond_horizon', init_zoom_periods=100, yscale='log')
    ax.showGrid(True, True)

    ax.reset()  # remove previous plots
    price = df['open close high low'.split()]
    fplt.candlestick_ochl(price)

    fplt.timer_callback(animate, 2)
    fplt.show()

Describe the bug

I expect to see the last candle (dummy) to animate and change based on random number, but in reality I see just a very long one with mixed colors. In addition the chart seems to move to left.

Expected behavior

The last candle is animated and the chart keep the zoom and does not move to left

Screenshots

image

Reproducible in:

OS: Windows finplot version: 1.9.4 pyqtgraph version: pyqt version:

EURUSD.FXCM_1m.csv

alessandrogiulianelli avatar Apr 16 '24 17:04 alessandrogiulianelli

You keep adding the same candle to the end of your data. Only add a candle the first time, then update it on subsequent calls.

highfestiva avatar Apr 18 '24 06:04 highfestiva

hi @highfestiva thanks I am not sure to have done it properly because I got the same result `import finplot as fplt import pandas as pd from datetime import timezone import random

class Test:

def __init__(self):
    self.df = pd.read_csv(f'./data/EURUSD.FXCM/generated/EURUSD.FXCM_1m.csv',
                     parse_dates=['date'],
                     delimiter=',')
    self.df.index = pd.DatetimeIndex(self.df['date'])
    fplt.candle_bull_body_color = fplt.candle_bull_color
    fplt.legend_fill_color = '#fff'
    fplt.legend_text_color = '#000'
    fplt.display_timezone = timezone.utc

def plot(self):
    ax = fplt.create_plot('beyond_horizon', init_zoom_periods=100, yscale='log')
    ax.showGrid(True, True)

    ax.reset()  # remove previous plots
    price = self.df['open close high low'.split()]
    fplt.candlestick_ochl(price)

    fplt.timer_callback(self.animate, 2)
    fplt.show()

def animate(self):
    try:
        fplt.autoviewrestore()
        fplt._savewindata(fplt.windows[0])

        # Sample data
        num = random.random()
        data = [["2024-04-16 00:33:00", 1.06100, 1.06126, 1.06106, 1.06106 + (num - 0.5) / 1000, 2.0]]
        # Add more rows if you have additional data
        new_df = pd.DataFrame(data, columns=('date', 'open', 'high', 'low', 'close', 'volume'))
        new_df.index = pd.DatetimeIndex(new_df['date'])

        # Check if the timestamp already exists in the existing DataFrame
        if new_df['date'].isin(self.df['date']).any():
            # Update existing data
            self.df.update(new_df)
        else:
            # Append new data
            self.df = pd.concat([self.df,new_df])

        price = self.df['open close high low'.split()]
        fplt.candlestick_ochl(price)
        fplt.refresh()
    except Exception as e:
        print(e)
        fplt.close()

if name == 'main': t = Test() t.plot() `

alessandrogiulianelli avatar Apr 20 '24 06:04 alessandrogiulianelli

You're creating yet another candlestick plot on every call to your animate() function. Don't do that. Check the bfx.py example. It does exactly what you're trying to do.

highfestiva avatar Apr 20 '24 10:04 highfestiva