Could you give a link to how to include a standalone app?
And I think I’ve got it.
Thank you so much @Emmanuelle
Now I have bugs with autoscroll
That’s what it looks like:
My full code:
import datetime as dt
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objects as go
import requests
from dash.dependencies import Output, Input, State
from dash.exceptions import PreventUpdate
from dateutil.relativedelta import relativedelta
from django_plotly_dash import DjangoDash
from shares.services import get_board_candles
config = {
'scrollZoom': True,
'staticPlot ': True,
'autosizable': False,
'showAxisRangeEntryBoxes ': True,
'displayModeBar': True,
'displaylogo': False,
'responsive': True,
'modeBarButtonsToRemove': ['toImage',
'select2d',
'lasso2d',
'resetScale2d',
'hoverCompareCartesian',
'hoverClosestCartesian',
'toggleSpikelines',
],
}
def get_data_from_moex(security, start=None, end=None):
interval = 1
data = None
if start is None and end is None:
start = dt.datetime.today()
if start <= dt.datetime.today():
start = start.replace(hour=0, minute=0, second=0)
while not data:
with requests.Session() as session:
data = get_board_candles(session, security, interval, start, end)
if not data:
start = start - relativedelta(days=1)
end = start + relativedelta(days=1)
# Dataframe
df = pd.DataFrame(data)
df['datetime'] = pd.to_datetime(df.begin, format='%Y-%m-%d %H:%M')
if df['datetime'][0].minute == 59:
df['datetime'] += pd.Timedelta('1 minute')
del df['begin'], df['value']
jsonified_df = df.to_json(orient='split')
return jsonified_df
def load_figure(jsonified_df, graph=None):
df = pd.read_json(jsonified_df, orient='split')
fig = go.Figure(
data=[go.Candlestick(
dict(x=df['datetime'], open=df['open'], high=df['high'], low=df['low'],
close=df['close']))],
layout=dict(xaxis=dict(autorange=True, rangeslider=dict(visible=False),
rangebreaks=[
dict(pattern='hour', bounds=[19, 10])]
),
yaxis=dict(autorange=True, overlaying='y', side='right',
position=1, tickformat='.2f', ticksuffix='₽'),
margin=dict(t=0, b=0, r=40, l=0),
autosize=True,
hovermode='x', dragmode='pan'
)
)
return fig
ohlc = DjangoDash('Plot', serve_locally=True, add_bootstrap_links=True)
def serve_layout():
return html.Div([
dcc.Graph(id='graph', animate=True, config=config),
dcc.Store(id='signal', storage_type='media'),
dcc.Interval(
id='interval',
interval=1000,
n_intervals=0),
])
ohlc.layout = serve_layout
@ohlc.callback(Output('graph', 'figure'),
[Input('signal', 'data')])
def load_graph(signal, *args, **kwargs):
if signal:
fig = load_figure(signal)
return fig
@ohlc.expanded_callback(Output('signal', 'data'),
[Input('graph', 'relayoutData')])
def save_in_store(relayout_data, *args, **kwargs):
security = kwargs['session_state']['security']
start = None
end = None
try:
x_start = relayout_data['xaxis.range[0]'].split(sep=' ')
x_end = relayout_data['xaxis.range[1]'].split(sep=' ')
except (TypeError, KeyError, AttributeError):
jsonified_df = get_data_from_moex(security)
return jsonified_df
else:
x_start = f'{x_start[0]} {x_start[1].split(sep=":")[0]}'
x_start = dt.datetime.strptime(x_start, '%Y-%m-%d %H')
x_end = f'{x_end[0]} {x_end[1].split(sep=":")[0]}'
x_end = dt.datetime.strptime(x_end, '%Y-%m-%d %H')
if x_start <= x_start.replace(hour=10):
start = x_start - relativedelta(days=1)
end = start + relativedelta(days=2)
elif x_end >= x_end.replace(hour=19):
start = x_start + relativedelta(days=1)
end = start + relativedelta(days=2)
jsonified_df = get_data_from_moex(security, start, end)
return jsonified_df
@ohlc.callback(Output('graph', 'extendData'),
[Input('signal', 'data'), Input('interval', 'n_intervals')],
[State('graph', 'figure')])
def update_extend_then_add(jsonified_df, n_intervals, graph, *args, **kwargs):
if graph is None:
raise PreventUpdate
if jsonified_df:
# print((len(jsonified_df.encode("utf-8"))) / 1024, 'kBytes')
df = pd.read_json(jsonified_df, orient='split')
x = list(df['datetime'])
opens = list(df['open'])
high = list(df['high'])
low = list(df['low'])
closes = list(df['close'])
retval = [dict(
close=[closes],
high=[high],
low=[low],
open=[opens],
x=[x]
)]
return retval