Let’s see how we can create an interactive stock market dashboard using Dash and then embed it into a standalone PyQt5 application using QWebEngineView. This allows you to run the Dash app locally as a desktop application while still you can deploy it online as a web app (e.g., on Render or any other web hosting service).
To follow along, ensure you have the following installed:
pip install dash plotly pandas requests dash-bootstrap-components PyQt5 PyQtWebEngine
The app retrieves the most active stock symbols from Yahoo Finance and allows users to visualize stock price trends over a specified period.
import requests
import pandas as pd
from datetime import datetime
import warnings
"ignore")
warnings.filterwarnings(
= {
headers "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
= 'https://finance.yahoo.com/markets/stocks/most-active/?start=0&count=100'
url_stocks = pd.read_html(requests.get(url_stocks, headers=headers).text)[0]['Symbol'].to_list() stocks
We initialize a Dash application with Bootstrap styling for a responsive UI.
from dash import Dash, html, dcc, callback, Output, Input
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
def common_layout(fig):
"""Applies a consistent layout to all figures."""
fig.update_layout(=0.5,
title_x=800,
width=600,
height="plotly_white"
template
)return fig
def empty_figure():
"""Creates a placeholder figure."""
= go.Figure()
fig =[], y=[], mode="lines"))
fig.add_trace(go.Scatter(x="Loading Data...")
fig.update_layout(titlereturn common_layout(fig)
= Dash(__name__, external_stylesheets=[dbc.themes.JOURNAL])
app = dbc.Container([
app.layout "Stock Market Dashboard", className="text-center mb-4"), width=12)]),
dbc.Row([dbc.Col(html.H1(
dbc.Row([
dbc.Col(["Select a Stock"),
html.H4('AAPL', id='dropdown-selection', className="mb-4"),
dcc.Dropdown(stocks, "Select Start Date"),
html.H4(id='start-date-picker', min_date_allowed=datetime(2000, 1, 1), max_date_allowed=datetime.today(), date="2020-01-01"),
dcc.DatePickerSingle("Select End Date"),
html.H4(id='end-date-picker', min_date_allowed=datetime(2000, 1, 1), max_date_allowed=datetime.today(), date=datetime.today().strftime("%Y-%m-%d"))
dcc.DatePickerSingle(=3, className="bg-light p-3 rounded"),
], width
id="stock-graph", figure=empty_figure())], width=9)
dbc.Col([dcc.Graph(="center")
], align=True) ], fluid
A callback function updates the graph based on user input:
@callback(
'stock-graph', 'figure'),
Output('dropdown-selection', 'value'),
[Input('start-date-picker', 'date'),
Input('end-date-picker', 'date')]
Input(
)def update_graph(symbol, start_date, end_date):
if not symbol or not start_date or not end_date:
return empty_figure()
= int(datetime.strptime(start_date, "%Y-%m-%d").timestamp())
period1 = int(datetime.strptime(end_date, "%Y-%m-%d").timestamp())
period2 = f'https://finance.yahoo.com/quote/{symbol}/history/?period1={period1}&period2={period2}'
url_history
= pd.read_html(requests.get(url_history, headers=headers).text)[0]
data = ['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume']
data.columns 1:] = data.iloc[:, 1:].apply(pd.to_numeric, errors='coerce')
data.iloc[:, 'Date'] = pd.to_datetime(data['Date'])
data[
= go.Figure(data=[go.Scatter(x=data['Date'], y=data["Adj Close"], mode="lines")])
fig =f"Stock Prices: {symbol}")
fig.update_layout(titlereturn common_layout(fig)
We use PyQt5’s QWebEngineView
to create a standalone
desktop application that runs the Dash server locally and loads the
dashboard in a browser widget.
import sys
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtWebEngineWidgets import QWebEngineView
class DashWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Standalone Dash App")
self.setGeometry(100, 100, 1200, 800)
self.browser = QWebEngineView()
self.browser.setUrl(QUrl("http://127.0.0.1:8050/"))
= QVBoxLayout()
layout self.browser)
layout.addWidget(
= QWidget()
container
container.setLayout(layout)self.setCentralWidget(container)
= app.server
server
if __name__ == '__main__':
=True)
app.run_server(debug= QApplication(sys.argv)
app = DashWindow()
main_window
main_window.show()exec()) sys.exit(app.
To run the application locally:
python app.py
This will launch both the Dash web server and the PyQt5 application window displaying the dashboard, which looks like this:
### Step 6: Deploying the Dash
App Online
To deploy the Dash app on platforms like Render or Heroku:
requirements.txt
file with necessary packages.
dash pandas pyqt5 PyQtWebEngine requests datetime plotly dash-bootstrap-components gunicorn lxml
Go to render.com and create an account.
Then go to your dashboard and click “Add new” then choose “Web
Service”
Connect your GitHub Repo.
Set Python runtime and enter:
Build Command: ``` pip install -r requirements.txt
Start Command:
gunicorn app:server
And finally Click Deploy.
By following this guide, you can create a simple dash app that works as both a local standalone app and a web-hosted dashboard. ### Taking Dash Apps to the Next Level
Beyond this basic tutorial, Dash allows you to build highly sophisticated and interactive applications. Here’s what you can explore next:
dcc.Interval
) to fetch and display real-time stock or
cryptocurrency data.dash.Dash.pages
for large-scale applications.dash.dcc.Store
and external JavaScript
libraries.dash.dash_table.DataTable
for complex data
manipulation.dash_clientside.callback
).dcc.Store
or databases to maintain session states.By mastering these features, you can transform a simple dashboard into an enterprise-grade application with real-time analytics, AI-powered insights, and seamless interactivity. Whether you’re building a trading terminal, machine learning dashboard, or data analytics tool, the possibilities with Dash are limitless!