i am currently working with plotly i have a function called plotChart that takes a dataframe as input and plots a candlestick chart. I am trying to figure out a way to pass a list of dataframes to the function plotChart and use a plotly dropdown menu to show the options on the input list by the stock name. The drop down menu will have the list of dataframe and when an option is clicked on it will update the figure in plotly is there away to do this. below is the code i have to plot a single dataframe
def make_multi_plot(df):
fig = make_subplots(rows=2, cols=2,
shared_xaxes=True,
vertical_spacing=0.03,
subplot_titles=('OHLC', 'Volume Profile'),
row_width=[0.2, 0.7])
for s in df.name.unique():
trace1 = go.Candlestick(
x=df.loc[df.name.isin([s])].time,
open=df.loc[df.name.isin([s])].open,
high=df.loc[df.name.isin([s])].high,
low=df.loc[df.name.isin([s])].low,
close=df.loc[df.name.isin([s])].close,
name = s)
fig.append_trace(trace1,1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].BbandsMid, mode='lines',name='MidBollinger'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].BbandsUpp, mode='lines',name='UpperBollinger'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].BbandsLow, mode='lines',name='LowerBollinger'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].vwap, mode='lines',name='VWAP'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].STDEV_1, mode='lines',name='UPPERVWAP'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].STDEV_N1, mode='lines',name='LOWERVWAP'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].KcMid, mode='lines',name='KcMid'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].KcUpper, mode='lines',name='KcUpper'),1,1)
fig.append_trace(go.Scatter(x=df.loc[df.name.isin([s])].time, y=df.loc[df.name.isin([s])].KcLow, mode='lines',name='KcLow'),1,1)
trace2 = go.Bar(
x=df.loc[df.name.isin([s])].time,
y=df.loc[df.name.isin([s])].volume,
name = s)
fig.append_trace(trace2,2,1)
# fig.update_layout(title_text=s)
graph_cnt=len(fig.data)
tr = 11
symbol_cnt =len(df.name.unique())
for g in range(tr, graph_cnt):
fig.update_traces(visible=False, selector=g)
#print(g)
def create_layout_button(k, symbol):
start, end = tr*k, tr*k+2
visibility = [False]*tr*symbol_cnt
visibility[start:end] = [True,True,True,True,True,True,True,True,True,True,True]
return dict(label = symbol,
method = 'restyle',
args = [{'visible': visibility[:-1],
'title': symbol,
'showlegend': False}])
fig.update(layout_xaxis_rangeslider_visible=False)
fig.update_layout(
updatemenus=[go.layout.Updatemenu(
active = 0,
buttons = [create_layout_button(k, s) for k, s in enumerate(df.name.unique())]
)
])
fig.show()
i am trying to add annotations to the figure it will be different for each chart below is how i had it setup for the single chart df['superTrend'] is a Boolean column
for i in range(df.first_valid_index()+1,len(df.index)):
prev = i - 1
if df['superTrend'][i] != df['superTrend'][prev] and not np.isnan(df['superTrend'][i]) :
#print(i,df['inUptrend'][i])
fig.add_annotation(x=df['time'][i], y=df['open'][i],
text= 'Buy' if df['superTrend'][i] else 'Sell',
showarrow=True,
arrowhead=6,
font=dict(
#family="Courier New, monospace",
size=20,
#color="#ffffff"
),)
I adapted an example from the plotly community to your example and created the code. The point of creation is to create the data for each subplot and then switch between them by means of buttons. The sample data is created using representative companies of US stocks. one issue is that the title is set but not displayed. We are currently investigating this issue.
import yfinance as yf
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
symbols = ['AAPL','GOOG','TSLA']
stocks = pd.DataFrame()
for s in symbols:
data = yf.download(s, start="2021-01-01", end="2021-12-31")
data['mean'] = data['Close'].rolling(20).mean()
data['std'] = data['Close'].rolling(20).std()
data['upperBand'] = data['mean'] + (data['std'] * 2)
data.reset_index(inplace=True)
data['symbol'] = s
stocks = stocks.append(data, ignore_index=True)
def make_multi_plot(df):
fig = make_subplots(rows=2, cols=1,
shared_xaxes=True,
vertical_spacing=0.03,
subplot_titles=('OHLC', 'Volume Profile'),
row_width=[0.2, 0.7])
for s in df.symbol.unique():
trace1 = go.Candlestick(
x=df.loc[df.symbol.isin([s])].Date,
open=df.loc[df.symbol.isin([s])].Open,
high=df.loc[df.symbol.isin([s])].High,
low=df.loc[df.symbol.isin([s])].Low,
close=df.loc[df.symbol.isin([s])].Close,
name=s)
fig.append_trace(trace1,1,1)
trace2 = go.Scatter(
x=df.loc[df.symbol.isin([s])].Date,
y=df.loc[df.symbol.isin([s])].upperBand,
name=s)
fig.append_trace(trace2,1,1)
trace3 = go.Bar(
x=df.loc[df.symbol.isin([s])].Date,
y=df.loc[df.symbol.isin([s])].Volume,
name=s)
fig.append_trace(trace3,2,1)
# fig.update_layout(title_text=s)
# Calculate the total number of graphs
graph_cnt=len(fig.data)
# Number of Symbols
symbol_cnt =len(df.symbol.unique())
# Number of graphs per symbol
tr = 3
# Hide setting for initial display
for g in range(tr, graph_cnt):
fig.update_traces(visible=False, selector=g)
def create_layout_button(k, symbol):
start, end = tr*k, tr*k+2
visibility = [False]*tr*symbol_cnt
# Number of graphs per symbol, so if you add a graph, add True.
visibility[start:end] = [True,True,True]
return dict(label = symbol,
method = 'restyle',
args = [{'visible': visibility[:-1],
'title': symbol,
'showlegend': True}])
fig.update(layout_xaxis_rangeslider_visible=False)
fig.update_layout(
updatemenus=[go.layout.Updatemenu(
active = 0,
buttons = [create_layout_button(k, s) for k, s in enumerate(df.symbol.unique())]
)
])
fig.show()
return fig.layout
make_multi_plot(stocks)