Plotly Python 使用 dropMenu 更新图形

Plotly Python update figure with dropMenu

我目前正在使用 plotly 我有一个名为 plotChart 的函数,它将数据框作为输入并绘制烛台图表。我试图找出一种方法将数据帧列表传递给函数 plotChart 并使用 plotly 下拉菜单按股票名称显示输入列表上的选项。下拉菜单将包含数据框列表,当单击一个选项时,它将更新 plotly 中的图形,以便执行此操作。下面是我必须绘制单个数据帧的代码

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()

我正在尝试向图中添加注释,它对于每个图表都会有所不同,下面是我为单个图表设置的方式 df['superTrend'] 是一个布尔列

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"
            ),)

我将 plotly community 中的示例改编为您的示例并创建了代码。创建的重点是为每个子图创建数据,然后通过按钮在它们之间切换。样本数据是使用美国股票的代表性公司创建的。一个问题是标题已设置但未显示。我们目前正在调查此问题。

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)