I've been developing a live-updating cryptocurrency tracker using Plotly's Dash in Python. The application retrieves data from an API and updates the graph every minute. However, I've encountered a problem where the graph does not update in the web browser without manual intervention (e.g., panning the graph). The graph is expected to update automatically every minute.
I've tried clearing the cache, using different browsers (Chrome, Brave, and Edge), and debugging the code to ensure that the data fetching and updating functions are working properly. The code correctly fetches new data and updates the graph internally every minute as it prints the updated timestamps in the console, but these updates do not reflect in the browser. The graph only updates in the browser when it's manually interacted with.
The expected behavior is for the graph in the browser to automatically update every minute without needing any manual interaction.
Here is a simplified version of my code:
import os
import time
import datetime
import pandas as pd
import ccxt
import plotly.graph_objs as go
from dash import Dash, dcc, html
from dash.dependencies import Input, Output
symbol = 'BTC/USDT'
timeframe = '5m'
exchange = ccxt.binance({
'rateLimit': 1200,
'enableRateLimit': True,
})
def fetch_historical_data(symbol, timeframe, start_time, end_time):
historical_data = exchange.fetch_ohlcv(symbol, timeframe, exchange.parse8601(start_time), exchange.parse8601(end_time))
return historical_data
app = Dash(__name__)
app.layout = html.Div(children=[
html.H1(children=f'{symbol} {timeframe} Chart'),
dcc.Interval(id='graph-update', interval=60 * 1000, n_intervals=0),
html.Button('Refresh', id='refresh-button', n_clicks=0),
html.Div(id='graph-container')
])
@app.callback(Output('graph-container', 'children'),
[Input('graph-update', 'n_intervals'),
Input('refresh-button', 'n_clicks')])
def update_graph(interval, n_clicks):
print("Update graph function called")
current_time = datetime.datetime.now(datetime.timezone.utc)
print(f"Current time: {current_time}")
local_time = current_time + datetime.timedelta(hours=0)
end_time = local_time.strftime("%Y-%m-%dT%H:%M:%SZ")
start_time = (local_time - datetime.timedelta(hours=5)).strftime("%Y-%m-%dT%H:%M:%SZ")
print(f"Fetching historical data from {start_time} to {end_time}")
data = fetch_historical_data(symbol, timeframe, start_time, end_time)
print(f"Fetched {len(data)} data points")
timestamps = [kline[0] for kline in data]
dates = [datetime.datetime.fromtimestamp(timestamp / 1000) for timestamp in timestamps]
df = pd.DataFrame(data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = dates
df.set_index('timestamp', inplace=True)
print(f"DataFrame created with {len(df)} rows")
fig = go.Figure(data=[go.Candlestick(x=df.index, open=df['open'], high=df['high'], low=df['low'], close=df['close'])])
fig.update_layout(title=f'{symbol} {timeframe} Chart (Last update: {local_time.strftime("%Y-%m-%d %H:%M")})', yaxis_title='Price')
print("Figure created")
return dcc.Graph(id='live-graph', animate=True, figure=fig)
if __name__ == '__main__':
app.run_server(debug=True)