Hello.
There is a code that outputs a candlestick chart, and does autorange after zooming or moving.
import plotly.graph_objects as go
from dash import dcc, html, Input, Output, State, Dash
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
fig = go.Figure(data=[go.Candlestick(x=df['Date'],
open=df['AAPL.Open'],
high=df['AAPL.High'],
low=df['AAPL.Low'],
close=df['AAPL.Close'])])
fig.update_layout(dragmode='pan', autosize=True, xaxis_rangeslider_visible=False, )
config = dict({'scrollZoom': True})
app = Dash(__name__)
app.layout = html.Div([
dcc.Graph(figure=fig, animate=True, config=config, id='graph', ),
], )
app.clientside_callback(
"""
function(relOut, Figure) {
if (typeof relOut !== 'undefined') {
if (typeof relOut["xaxis.range[0]"] !== 'undefined') {
console.log('All ok')
//get active filter from graph
fromS = new Date(relOut["xaxis.range[0]"]).getTime()
toS = new Date(relOut["xaxis.range[1]"]).getTime()
xD = Figure.data[0].x
highD = Figure.data[0].high
lowD = Figure.data[0].low
//filter y data with graph display
highFilt = xD.reduce(function (pV,cV,cI){
sec = new Date(cV).getTime()
if (sec >= fromS && sec <= toS) {
pV.push(highD[cI])
}
return pV
}, [])
//filter y data with graph display
lowFilt = xD.reduce(function (pV,cV,cI){
sec = new Date(cV).getTime()
if (sec >= fromS && sec <= toS) {
pV.push(lowD[cI])
}
return pV
}, [])
yMax = Math.max.apply(Math, highFilt)
yMin = Math.min.apply(Math, lowFilt)
Figure.layout.yaxis = {
'range[0]': yMin,
'range[1]': yMax,
'type': 'linear'
}
} else {
console.log('typeof relOut[xaxis.range[0]] !== undefined')
}
} else {
console.log('typeof relOut !== undefined')
}
console.log('return Figure')
return {'data': Figure.data, 'layout': Figure.layout};
}
""",
Output('graph', 'figure'),
[Input('graph', 'relayoutData')], [State('graph', 'figure')]
)
app.run_server(debug=True, use_reloader=True, )
But it does not work quite correctly. Before making the correct autorange, the Y-axis flies somewhere wrong, and only after that sets the correct range. I recorded a video for clarity Plotly Dash problem - YouTube. Specifically here, the graph is running somewhere down. In other cases, it may run upwards, or come very close on the Y-axis.
Part of the code was taken from here. But I had to tweak it a bit, if you leave the “else” from the example, the picture jumps longer and at the end it has a completely wrong range.
What am I doing wrong, and how can I fix it?