How to show only the latest four bars at a time when a new bar is updated everytime?

Hi, How to show only the latest four bars at a time when a new bar is updated everytime?The old bars should be kept.

from dash import Dash, dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime

app = Dash(external_stylesheets = [dbc.themes.CYBORG])

candles = go.Figure(
                data = [
                    go.Candlestick(
                        x = [],
                        open = [],
                        high = [],
                        low = [],
                        close = [],
                        )])



app.layout = html.Div([dcc.Graph(id='graph', figure=candles), dcc.Interval(id="interval", interval = 2000)])


index = 0
@app.callback(Output('graph', 'extendData'), [Input('interval', 'n_intervals')])
def update_data(n_intervals):
    global index
    index += 1

    now = datetime.now()
    dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

    return (
        dict(
            x = [[ dt_string ]],
            open  = [[ 4 ]],
            close = [[ 2]],
            high  = [[ 7]],
            low   = [[ 1]]
 
        ),
        [0],
        index
    )


if __name__ == '__main__':
    app.run_server(debug=True)

Hi @HAHA6666

Welcome to the community!

Please check if the code below achieves what you have in mind

from dash import Dash, dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
from datetime import datetime

app = Dash(external_stylesheets=[dbc.themes.CYBORG])

candles = go.Figure(
    data=[
        go.Candlestick(
            x=[],
            open=[],
            high=[],
            low=[],
            close=[]
        )
    ]
)

app.layout = html.Div([
    dcc.Graph(id='graph', figure=candles),
    dcc.Interval(id="interval", interval=2000)
])

data = {'x': [], 'open': [], 'high': [], 'low': [], 'close': []}

@app.callback(Output('graph', 'figure'), [Input('interval', 'n_intervals')])
def update_data(n_intervals):
    now = datetime.now()
    dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

    # Append new data
    data['x'].append(dt_string)
    data['open'].append(4)
    data['high'].append(7)
    data['low'].append(1)
    data['close'].append(2)

    # Keep only the last 4 bars
    if len(data['x']) > 4:
        data['x'] = data['x'][-4:]
        data['open'] = data['open'][-4:]
        data['high'] = data['high'][-4:]
        data['low'] = data['low'][-4:]
        data['close'] = data['close'][-4:]

    # Update figure
    candles = go.Figure(
        data=[
            go.Candlestick(
                x=data['x'],
                open=data['open'],
                high=data['high'],
                low=data['low'],
                close=data['close']
            )
        ]
    )

    return candles

if __name__ == '__main__':
    app.run_server(debug=True)

1 Like

thanks for your replay,sir

I have two questions

  1. While appending a new bar,your code create a new figure just containing the lasted four bars. Could you keep all the old bars in the figure,just show the lasted four bars?
  2. When there is a lot of bars,I think using extendData is more efficient. Could you use extendData instead of creating a new figure?

I am trying to change the RangeSlider‘s range to achieve my goal,but it does not work

Hi @HAHA6666

Regrading point 1, if I understood you correctly, you want to keep the data intact but only use a slice of the last 4 bars to display on the graph. If so, the code below achieves this. You’d only see the last 4 bars in the view (I don’t understand how you can only view the last 4 but also keep the old ones in the view)

from dash import Dash, dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
from datetime import datetime

app = Dash(external_stylesheets=[dbc.themes.CYBORG])

candles = go.Figure(
    data=[
        go.Candlestick(
            x=[],
            open=[],
            high=[],
            low=[],
            close=[]
        )
    ]
)

app.layout = html.Div([
    dcc.Graph(id='graph', figure=candles),
    dcc.Interval(id="interval", interval=2000)
])

# Store all data
data = {'x': [], 'open': [], 'high': [], 'low': [], 'close': []}

@app.callback(Output('graph', 'figure'), [Input('interval', 'n_intervals')])
def update_data(n_intervals):
    now = datetime.now()
    dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

    # Append new data
    data['x'].append(dt_string)
    data['open'].append(4)
    data['high'].append(7)
    data['low'].append(1)
    data['close'].append(2)

    # Keep only the latest 4 bars for display
    display_data = {
        'x': data['x'][-4:],
        'open': data['open'][-4:],
        'high': data['high'][-4:],
        'low': data['low'][-4:],
        'close': data['close'][-4:]
    }

    # Update figure
    candles = go.Figure(
        data=[
            go.Candlestick(
                x=display_data['x'],
                open=display_data['open'],
                high=display_data['high'],
                low=display_data['low'],
                close=display_data['close']
            )
        ]
    )

    return candles

if __name__ == '__main__':
    app.run_server(debug=True)

in the code above all the bars are stored in the data dictionary and only the latest four bars are selected using slicing (-4:) and used to update the figure.