index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html
![]()
本教程详细介绍了如何使用Dash、Plotly和Bootstrap构建一个高级的交互式金融仪表盘。文章重点阐述了如何设计仪表盘的布局和可视化图表,并通过Dash的callback机制实现控件与输出的联动,从而达到实时响应的效果。我们探讨了结合本地执行与云平台(如Google Colab)部署的工作流程,展示了其灵活性和实用性。教程涵盖了数据生成、技术指标计算、仪表盘布局设计以及核心回调函数的实现,为用户提供了一个完整且可扩展的解决方案。
📊 **交互式仪表盘构建**:教程展示了如何利用Dash、Plotly和Bootstrap搭建一个功能丰富的金融仪表盘。通过`dash_bootstrap_components`,可以轻松创建响应式布局,实现多组件的集成,包括图表、数据表格和用户控件。
⚙️ **核心Callback机制**:Dash的核心在于其`callback`函数,它能动态地连接用户交互(如下拉菜单选择、日期范围选择)与仪表盘的更新。本教程详细演示了如何通过`callback`函数实现图表(股价、交易量、收益率分布)、统计数据(平均价格、总交易量、价格范围、数据点数)和数据表格的实时更新。
📈 **数据可视化与技术指标**:文章介绍了如何生成合成的股票数据,并计算了如20日移动平均线(MA_20)和波动率等技术指标。利用Plotly Express,可以创建多种类型的图表,如折线图、面积图和散点图,并支持叠加移动平均线,为金融数据分析提供了直观的视图。
☁️ **灵活的部署选项**:教程强调了该仪表盘既可以在本地开发环境中运行,也能轻松部署到云平台(如Google Colab),提供了本地执行与在线部署的灵活工作流程,满足不同用户的需求。
📊 **数据洞察与用户控件**:仪表盘提供了多种用户控件,包括股票选择下拉菜单、日期范围选择器、图表样式切换(线图、面积图、散点图)以及显示移动平均线的选项。这些控件使得用户能够根据自己的需求定制查看的数据和图表类型,从而进行深入的金融数据分析。
In this tutorial, we set out to build an advanced interactive dashboard using Dash, Plotly, and Bootstrap. We highlight not only how these tools enable us to design layouts and visualizations, but also how Dash’s callback mechanism links controls to outputs, allowing for real-time responsiveness. By combining local execution with the ability to run in cloud platforms like Google Colab, we explore a workflow that is both flexible and practical. Check out the FULL CODES here.
!pip install dash plotly pandas numpy dash-bootstrap-componentsimport dashfrom dash import dcc, html, Input, Output, callback, dash_tableimport plotly.express as pximport plotly.graph_objects as goimport pandas as pdimport numpy as npfrom datetime import datetime, timedeltaimport dash_bootstrap_components as dbcprint("Generating sample data...")np.random.seed(42)
We begin by installing and importing the necessary components, including Dash, Plotly, Pandas, NumPy, and Bootstrap, to set up our dashboard environment. We also initialize random seeds and generate sample data so that we can consistently test the interactive features as we build them. Check out the FULL CODES here.
start_date = datetime(2023, 1, 1)end_date = datetime(2024, 12, 31)dates = pd.date_range(start=start_date, end=end_date, freq='D')stock_names = ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'TSLA']all_data = []base_prices = {'AAPL': 150, 'GOOGL': 120, 'MSFT': 250, 'AMZN': 100, 'TSLA': 200}for stock in stock_names: print(f"Creating data for {stock}...") base_price = base_prices[stock] n_days = len(dates) returns = np.random.normal(0.0005, 0.025, n_days) prices = np.zeros(n_days) prices[0] = base_price for i in range(1, n_days): prices[i] = prices[i-1] * (1 + returns[i]) volumes = np.random.lognormal(15, 0.5, n_days).astype(int) stock_df = pd.DataFrame({ 'Date': dates, 'Stock': stock, 'Price': prices, 'Volume': volumes, 'Returns': np.concatenate([[0], np.diff(prices) / prices[:-1]]), 'Sector': np.random.choice(['Technology', 'Consumer', 'Automotive'], 1)[0] }) all_data.append(stock_df)df = pd.concat(all_data, ignore_index=True)df['Date'] = pd.to_datetime(df['Date'])df_sorted = df.sort_values(['Stock', 'Date']).reset_index(drop=True)print("Calculating technical indicators...")df_sorted['MA_20'] = df_sorted.groupby('Stock')['Price'].transform(lambda x: x.rolling(20, min_periods=1).mean())df_sorted['Volatility'] = df_sorted.groupby('Stock')['Returns'].transform(lambda x: x.rolling(30, min_periods=1).std())df = df_sorted.copy()print(f"Data generated successfully! Shape: {df.shape}")print(f"Date range: {df['Date'].min()} to {df['Date'].max()}")print(f"Stocks: {df['Stock'].unique().tolist()}")
We generate synthetic stock data, including prices, volumes, and returns, for multiple tickers across a specified date range. We calculate moving averages and volatility to enrich the dataset with useful technical indicators, providing a strong foundation for building interactive visualizations. Check out the FULL CODES here.
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])app.layout = dbc.Container([ dbc.Row([ dbc.Col([ html.H1(" Advanced Financial Dashboard", className="text-center mb-4"), html.P(f"Interactive dashboard with {len(df)} data points across {len(stock_names)} stocks", className="text-center text-muted"), html.Hr() ]) ]), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardBody([ html.H5(" Dashboard Controls", className="card-title"), html.Label("Select Stocks:", className="fw-bold mt-3"), dcc.Dropdown( id='stock-dropdown', options=[{'label': f'{stock} ({base_prices[stock]})', 'value': stock} for stock in stock_names], value=['AAPL', 'GOOGL'], multi=True, placeholder="Choose stocks to analyze..." ), html.Label("Date Range:", className="fw-bold mt-3"), dcc.DatePickerRange( id='date-picker-range', start_date='2023-06-01', end_date='2024-06-01', display_format='YYYY-MM-DD', style={'width': '100%'} ), html.Label("Chart Style:", className="fw-bold mt-3"), dcc.RadioItems( id='chart-type', options=[ {'label': ' Line Chart', 'value': 'line'}, {'label': ' Area Chart', 'value': 'area'}, {'label': ' Scatter Plot', 'value': 'scatter'} ], value='line', labelStyle={'display': 'block', 'margin': '5px'} ), dbc.Checklist( id='show-ma', options=[{'label': ' Show Moving Average', 'value': 'show'}], value=[], style={'margin': '10px 0'} ), ]) ], className="h-100") ], width=3), dbc.Col([ dbc.Card([ dbc.CardHeader(" Stock Price Analysis"), dbc.CardBody([ dcc.Graph(id='main-chart', style={'height': '450px'}) ]) ]) ], width=9) ], className="mb-4"), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardBody([ html.H4(id="avg-price", className="text-primary mb-0"), html.Small("Average Price", className="text-muted") ]) ]) ], width=3), dbc.Col([ dbc.Card([ dbc.CardBody([ html.H4(id="total-volume", className="text-success mb-0"), html.Small("Total Volume", className="text-muted") ]) ]) ], width=3), dbc.Col([ dbc.Card([ dbc.CardBody([ html.H4(id="price-range", className="text-info mb-0"), html.Small("Price Range", className="text-muted") ]) ]) ], width=3), dbc.Col([ dbc.Card([ dbc.CardBody([ html.H4(id="data-points", className="text-warning mb-0"), html.Small("Data Points", className="text-muted") ]) ]) ], width=3) ], className="mb-4"), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader(" Trading Volume"), dbc.CardBody([ dcc.Graph(id='volume-chart', style={'height': '300px'}) ]) ]) ], width=6), dbc.Col([ dbc.Card([ dbc.CardHeader(" Returns Distribution"), dbc.CardBody([ dcc.Graph(id='returns-chart', style={'height': '300px'}) ]) ]) ], width=6) ], className="mb-4"), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader(" Latest Stock Data"), dbc.CardBody([ dash_table.DataTable( id='data-table', columns=[ {'name': 'Stock', 'id': 'Stock'}, {'name': 'Date', 'id': 'Date'}, {'name': 'Price ($)', 'id': 'Price', 'type': 'numeric', 'format': {'specifier': '.2f'}}, {'name': 'Volume', 'id': 'Volume', 'type': 'numeric', 'format': {'specifier': ',.0f'}}, {'name': 'Daily Return (%)', 'id': 'Returns', 'type': 'numeric', 'format': {'specifier': '.2%'}} ], style_cell={'textAlign': 'center', 'fontSize': '14px', 'padding': '10px'}, style_header={'backgroundColor': 'rgb(230, 230, 230)', 'fontWeight': 'bold'}, style_data_conditional=[ { 'if': {'filter_query': '{Returns} > 0'}, 'backgroundColor': '#d4edda' }, { 'if': {'filter_query': '{Returns} < 0'}, 'backgroundColor': '#f8d7da' } ], page_size=15, sort_action="native", filter_action="native" ) ]) ]) ]) ])], fluid=True)
We define the app layout with Bootstrap rows and cards, where we place controls (dropdown, date range, chart style, MA toggle) alongside the main graph. We add metric cards, two secondary graphs, and a sortable/filterable data table, so we organize everything into a responsive, clean interface that we can wire up to callbacks next. Check out the FULL CODES here.
@callback( [Output('main-chart', 'figure'), Output('volume-chart', 'figure'), Output('returns-chart', 'figure'), Output('data-table', 'data'), Output('avg-price', 'children'), Output('total-volume', 'children'), Output('price-range', 'children'), Output('data-points', 'children')], [Input('stock-dropdown', 'value'), Input('date-picker-range', 'start_date'), Input('date-picker-range', 'end_date'), Input('chart-type', 'value'), Input('show-ma', 'value')])def update_all_charts(selected_stocks, start_date, end_date, chart_type, show_ma): print(f"Callback triggered with stocks: {selected_stocks}") if not selected_stocks: selected_stocks = ['AAPL'] filtered_df = df[ (df['Stock'].isin(selected_stocks)) & (df['Date'] >= start_date) & (df['Date'] <= end_date) ].copy() print(f"Filtered data shape: {filtered_df.shape}") if filtered_df.empty: filtered_df = df[df['Stock'].isin(selected_stocks)].copy() print(f"Using all available data. Shape: {filtered_df.shape}") if chart_type == 'line': main_fig = px.line(filtered_df, x='Date', y='Price', color='Stock', title=f'Stock Prices - {chart_type.title()} View', labels={'Price': 'Price ($)', 'Date': 'Date'}) elif chart_type == 'area': main_fig = px.area(filtered_df, x='Date', y='Price', color='Stock', title=f'Stock Prices - {chart_type.title()} View', labels={'Price': 'Price ($)', 'Date': 'Date'}) else: main_fig = px.scatter(filtered_df, x='Date', y='Price', color='Stock', title=f'Stock Prices - {chart_type.title()} View', labels={'Price': 'Price ($)', 'Date': 'Date'}) if 'show' in show_ma: for stock in selected_stocks: stock_data = filtered_df[filtered_df['Stock'] == stock] if not stock_data.empty: main_fig.add_scatter( x=stock_data['Date'], y=stock_data['MA_20'], mode='lines', name=f'{stock} MA-20', line=dict(dash='dash', width=2) ) main_fig.update_layout(height=450, showlegend=True, hovermode='x unified') volume_fig = px.bar(filtered_df, x='Date', y='Volume', color='Stock', title='Daily Trading Volume', labels={'Volume': 'Volume (shares)', 'Date': 'Date'}) volume_fig.update_layout(height=300, showlegend=True) returns_fig = px.histogram(filtered_df.dropna(subset=['Returns']), x='Returns', color='Stock', title='Daily Returns Distribution', labels={'Returns': 'Daily Returns', 'count': 'Frequency'}, nbins=50) returns_fig.update_layout(height=300, showlegend=True) if not filtered_df.empty: avg_price = f"${filtered_df['Price'].mean():.2f}" total_volume = f"{filtered_df['Volume'].sum():,.0f}" price_range = f"${filtered_df['Price'].min():.0f} - ${filtered_df['Price'].max():.0f}" data_points = f"{len(filtered_df):,}" table_data = filtered_df.nlargest(100, 'Date')[ ['Stock', 'Date', 'Price', 'Volume', 'Returns'] ].round(4).to_dict('records') for row in table_data: row['Date'] = row['Date'].strftime('%Y-%m-%d') if pd.notnull(row['Date']) else '' else: avg_price = "No data" total_volume = "No data" price_range = "No data" data_points = "0" table_data = [] return (main_fig, volume_fig, returns_fig, table_data, avg_price, total_volume, price_range, data_points)
We wire up Dash’s callback to connect our controls to every output, so changing any input instantly updates charts, stats, and the table. We filter the dataframe by selections and dates, build figures (plus optional MA overlays), and compute summary metrics. Finally, we format recent rows for the table so we can inspect the latest results at a glance. Check out the FULL CODES here.
if __name__ == '__main__': print("Starting Dash app...") print("Available data preview:") print(df.head()) print(f"Total rows: {len(df)}") app.run(mode='inline', port=8050, debug=True, height=1000) # app.run(debug=True)
We set up the entry point for running the app. We print a quick preview of the dataset to determine what’s available, and then launch the Dash server. In Colab, we can run it inline. For local development, we can simply switch to the regular app.run(debug=True) for desktop development.
In conclusion, we integrate interactive charts, responsive layouts, and Dash’s callback mechanism into a cohesive application. We see how the callbacks orchestrate communication between user input and dynamic updates, turning static visuals into powerful interactive tools. With the ability to operate smoothly both locally and online, this approach provides a versatile foundation that we can extend for broader applications.
Check out the FULL CODES here. Feel free to check out our GitHub Page for Tutorials, Codes and Notebooks. Also, feel free to follow us on Twitter and don’t forget to join our 100k+ ML SubReddit and Subscribe to our Newsletter.
The post How to Design an Interactive Dash and Plotly Dashboard with Callback Mechanisms for Local and Online Deployment? appeared first on MarkTechPost.