KRUSTY THE CLOWN: “Let’s just say it moved me… TO A BIGGER HOUSE! Oops! I said the quiet part loud and the loud part quiet.”
— “A Star is Burns” (S06E18)
How do you create an interactive dashboard in Python? How do you deploy and share that dashboard? And, critically, can we do this without being a front-end developer?
Do you…
Then come join us for a session on dashboarding in Python!
Python is a premiere programming language for scientific computation, whether
its used for data exploration, visualization, or reporting. While Python has
always supported interactive visualizations via matplotlib its web-based
dashboarding capabilities have been limited to rendering static plots onto the
web.
In this episode, we will provide an overview of some Python based dashboarding
tools like panel, bokeh, and holoviews. These tools provide a convenient
mechanism to create complex dashboards enabling you to better understand your
data, and even share that understanding with your colleagues. We’ll develop an
understanding about the uses of a data dashboard, the core features of these
Python tools, and how these frameworks are implemented to effectively work with
them without needing to be a front-end developer.
Keywords:
print("Let's take a look!")
What am I here to do? What is the problem at hand?
from pathlib import Path
from pandas import read_pickle
data_dir = Path('data')
prices = read_pickle(data_dir / 'prices.pkl')
trades = read_pickle(data_dir / 'trades.pkl')
industries = read_pickle(data_dir / 'industries.pkl')
print(
prices.head(3),
trades.head(3),
industries.head(3),
sep='\n{}\n'.format('\N{box drawings light horizontal}' * 40),
)
from pathlib import Path
from matplotlib.pyplot import show
from pandas import read_pickle
data_dir = Path('data')
prices = read_pickle(data_dir / 'prices.pkl')
prices.unstack('ticker').iloc[:, :4].plot()
show()
print("Let's take a look!")
from dash import Dash
from dash.html import Div, H1, P
app = Dash(__name__)
app.layout = Div([
H1('Dashboard...'),
P('some description of our problem'),
])
app.run_server(debug=True)
from dash import Dash
from dash.dcc import Input
from dash.html import Div, H1
app = Dash(__name__)
app.layout = Div([
H1('Dashboard'),
Input(),
])
app.run_server(debug=True)
from dash import Dash
from dash.dcc import Dropdown
from dash.html import Div, H1
app = Dash(__name__)
app.layout = Div([
H1('Dashboard'),
Dropdown(options=['a', 'b', 'c']),
])
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle
from dash import Dash
from dash.dcc import Dropdown
from dash.html import Div, H1
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
app = Dash(__name__)
app.layout = Div([
H1('Dashboard'),
Dropdown(sorted(industries.unique())),
])
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle
from dash import Dash, Input, Output
from dash.dcc import Dropdown
from dash.html import Div, H1, H2
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
app = Dash(__name__)
app.layout = Div([
h1 := H1('Dashboard'),
h2 := H2(),
dd := Dropdown(sorted(industries.unique())),
])
@app.callback(
Output(h2, 'children'),
Input(dd, 'value')
)
def callback(value):
return 'All Industries' if value is None else value
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle
from dash import Dash, Input, Output
from dash.dcc import Dropdown, Graph
from dash.html import Div, H1, H2
from plotly.express import line
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
app = Dash(__name__)
app.layout = Div([
h1 := H1('Dashboard'),
h2 := H2(),
dd := Dropdown(sorted(industries.unique())),
gr := Graph(),
])
@app.callback(
Output(h2, 'children'),
Input(dd, 'value')
)
def update_title(value):
return 'All Industries' if value is None else value
@app.callback(
Output(gr, 'figure'),
Input(dd, 'value')
)
def update_graph(value):
return line([1, 2, 3], [4, 5, 6])
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle, IndexSlice
from dash import Dash, Input, Output
from dash.dcc import Dropdown, Graph
from dash.html import Div, H1, H2
# from plotly.express import line
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
# app = Dash(__name__)
# app.layout = Div([
# h1 := H1('Dashboard'),
# h2 := H2(),
# dd := Dropdown(sorted(industries.unique())),
# gr := Graph(),
# ])
# @app.callback(
# Output(h2, 'children'),
# Input(dd, 'value')
# )
# def update_title(industry):
# return 'All Industries' if industry is None else industry
# @app.callback(
# Output(gr, 'figure'),
# Input(dd, 'value')
# )
# def update_graph(industry):
# if industry is not None:
# tickers = industries.loc[lambda s: s == industry].index
# else:
# tickers = industries.index
# data = prices.loc[IndexSlice[:, tickers], 'bid'].groupby('date').mean()
# return line(
# data,
# )
# app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle, IndexSlice
from dash import Dash, Input, Output
from dash.dcc import Dropdown, Graph
from dash.html import Div, H1, H2
from plotly.express import line
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
app = Dash(__name__)
app.layout = Div([
h1 := H1('Dashboard'),
h2 := H2(),
dd := Dropdown(sorted(industries.unique())),
gr := Graph(),
])
@app.callback(
Output(h2, 'children'),
Input(dd, 'value')
)
def update_title(industry):
return 'All Industries' if industry is None else industry
@app.callback(
Output(gr, 'figure'),
Input(dd, 'value')
)
def update_graph(industry):
if industry is not None:
tickers = industries.loc[lambda s: s == industry].index
else:
tickers = industries.index
data = prices.loc[IndexSlice[:, tickers], 'bid'].reset_index('ticker', drop=False)
return line(
data,
line_group='ticker',
)
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle, IndexSlice
from dash import Dash, Input, Output
from dash.dcc import Dropdown, Graph
from dash.html import Div, H1, H2
from plotly.express import line
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
app = Dash(__name__)
app.layout = Div([
h1 := H1('Dashboard'),
h2 := H2(),
dd := Dropdown(sorted(industries.unique())),
gr := Graph(),
])
@app.callback(
Output(h2, 'children'),
Input(dd, 'value')
)
def update_title(industry):
return 'All Industries' if industry is None else industry
@app.callback(
Output(gr, 'figure'),
Input(dd, 'value')
)
def update_graph(industry):
if industry is not None:
tickers = industries.loc[lambda s: s == industry].index
else:
tickers = industries.index
data = prices.loc[IndexSlice[:, tickers], 'bid'].reset_index('ticker', drop=False)
return line(
data,
line_group='ticker',
)
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle, IndexSlice
from dash import Dash, Input, Output
from dash.dcc import Dropdown, Graph
from dash.html import Div, H1, H2
from plotly.express import line
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
app = Dash(__name__)
app.layout = Div([
h1 := H1('Dashboard'),
h2 := H2(),
dd := Dropdown(sorted(industries.unique())),
gr := Graph(),
])
@app.callback(
[Output(h2, 'children'), Output(gr, 'figure')],
Input(dd, 'value')
)
def update(industry):
if industry is not None:
title = industry
tickers = industries.loc[lambda s: s == industry].index
else:
title = 'All industries'
tickers = industries.index
data = prices.loc[IndexSlice[:, tickers], 'bid'].reset_index('ticker', drop=False)
ln = line(
data,
line_group='ticker',
)
return title, ln
app.run_server(debug=True)
from pathlib import Path
from pandas import read_pickle, IndexSlice
from dash import Dash, Input, Output
from dash.dcc import Dropdown, Graph
from dash.html import Div, H1, H2
from plotly.express import line
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
trades = read_pickle(data_dir / 'trades.pkl')
app = Dash(__name__)
app.layout = Div([
h1 := H1('Dashboard'),
prx_h2 := H2(),
prx_dd := Dropdown(sorted(industries.unique())),
prx_gr := Graph(),
trd_h2 := H2(),
trd_dd := Dropdown(),
pf_dd := Dropdown(sorted(trades.index.get_level_values('portfolio').unique())),
trd_gr := Graph(),
])
@app.callback(
[Output(prx_h2, 'children'), Output(prx_gr, 'figure'), Output(trd_dd, 'options')],
Input(prx_dd, 'value')
)
def update_prices(industry):
if industry is not None:
title = industry
tickers = industries.loc[lambda s: s == industry].index
else:
title = 'All industries'
tickers = industries.index
data = prices.loc[IndexSlice[:, tickers], 'bid'].reset_index('ticker', drop=False)
ln = line(
data,
line_group='ticker',
)
return title, ln, sorted(tickers)
@app.callback(
Output(trd_gr, 'figure'),
[Input(trd_dd, 'value'), Input(pf_dd, 'value')]
)
def update_trades(ticker, portfolio):
if ticker is not None and portfolio is not None:
data = trades.loc[IndexSlice[:, portfolio, ticker, :], 'price']
elif ticker is not None:
data = trades.loc[IndexSlice[:, :, ticker, :], 'price']
elif portfolio is not None:
data = trades.loc[IndexSlice[:, portfolio, :, :], 'price']
else:
data = trades.loc[:, 'price']
data = data.groupby(['date']).mean()
return line(data)
app.run_server(debug=True)
from io import BytesIO
from base64 import b64encode
from numpy import linspace
from matplotlib.pyplot import subplots
from dash import Dash, Input, Output
from dash.dcc import Input as dccInput
from dash.html import Div, H1, Img
app = Dash(__name__)
app.layout = Div([
H1('Dashboard'),
inp := dccInput(value=2),
img := Img(),
])
xs = linspace(-100, 100, 1_000)
@app.callback(
Output(img, 'src'),
Input(inp, 'value'),
)
def update(value):
if not value:
return ''
ys = xs ** int(value)
fig, ax = subplots()
ax.plot(xs, ys)
fig.savefig(buf := BytesIO(), format='png')
return f'data:img/png;base64,{b64encode(buf.getbuffer()).decode("utf8")}'
app.run_server(debug=True)
print("Let's take a look!")
```python -m panel serve from panel.pane import HTML
HTML(‘’’ <h1>Dashboard</h1> ‘’’).servable()
```python -m panel serve
from panel import Column
from panel.widgets import TextInput
Column(
'# Dashboard',
TextInput(),
).servable()
```python -m panel serve from matplotlib.pyplot import subplots from numpy import linspace
from panel import Column, bind from panel.widgets import IntSlider
def plot(exp): xs = linspace(-100, +100, 1_001) fig, ax = subplots() ax.plot(xs, xs ** exp) return fig
Column( ‘# Dashboard’, exp := IntSlider(start=2, end=10), bind(plot, exp=exp), ).servable()
```python -m panel serve
from matplotlib.pyplot import subplots
from numpy import linspace
from panel import Column, bind
from panel.widgets import IntSlider
def create_slider(end):
return IntSlider(start=2, end=end + 1)
Column(
'# Dashboard',
inp1 := IntSlider(start=2, end=10),
bind(create_slider, end=inp1),
).servable()
```python -m panel serve from pathlib import Path
from pandas import read_pickle
from panel import Column from panel.widgets import Select
data_dir = Path(‘data’)
industries = read_pickle(data_dir / ‘industries.pkl’)
Column( ‘# Dashboard’, Select(options=sorted(industries.unique())), ).servable()
```python -m panel serve
from pathlib import Path
from pandas import read_pickle, IndexSlice
from panel import Column, bind
from panel.widgets import Select
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
def graph_prices(industry):
if not industry:
return '*Select an industry.*'
tickers = industries.loc[lambda s: s == industry].index
return prices.loc[IndexSlice[:, tickers, :], 'bid'].unstack('ticker').plot()
Column(
'# Dashboard',
sel := Select(options=sorted(industries.unique())),
bind(graph_prices, industry=sel)
).servable()
```python -m panel serve from pathlib import Path
from pandas import read_pickle, IndexSlice from matplotlib.pyplot import subplots
from panel import Column, bind from panel.widgets import Select
data_dir = Path(‘data’)
industries = read_pickle(data_dir / ‘industries.pkl’) prices = read_pickle(data_dir / ‘prices.pkl’)
def graph_prices(industry): if not industry: return ‘Select an industry.’
tickers = industries.loc[lambda s: s == industry].index
data = prices.loc[IndexSlice[:, tickers, :], 'bid'].unstack('ticker').plot()
fig, ax = subplots()
data.plot(ax=ax)
return fig
Column( ‘# Dashboard’, sel := Select(options=sorted(industries.unique())), bind(graph_prices, industry=sel) ).servable()
```python -m panel serve
from panel import Column, Row, bind
Column(
'# Dashboard',
Row(
Column(
'## prices',
),
Column(
'## trades',
),
),
).servable()
```python -m panel serve from pathlib import Path
from pandas import read_pickle, IndexSlice
from panel import Column, Row, bind from panel.widgets import Select
data_dir = Path(‘data’)
industries = read_pickle(data_dir / ‘industries.pkl’) prices = read_pickle(data_dir / ‘prices.pkl’) trades = read_pickle(data_dir / ‘trades.pkl’)
def ticker_select(industry): return Select(options=[industry])
def portfolio_select(industry): return Select(options=[industry])
Column( ‘# Dashboard’, Row( Column( ‘## prices’, ind_sel := Select(options=sorted(industries.unique())), ), Column( ‘## trades’, trd_sel := bind(ticker_select, industry=ind_sel), pf_sel := bind(portfolio_select, industry=ind_sel), ), ), ).servable()
```python -m panel serve
from pathlib import Path
from pandas import read_pickle, IndexSlice
from panel import Column, Row, bind
from panel.widgets import Select
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
trades = read_pickle(data_dir / 'trades.pkl')
def ticker_select(industry):
if not industry:
return '*Please select industry.*'
tickers = industries.loc[lambda s: s == industry].index
return Select(options=sorted(tickers.unique()))
def portfolio_select(industry):
if not industry:
return '*Please select industry.*'
tickers = industries.loc[lambda s: s == industry].index
portfolios = trades.loc[IndexSlice[:, :, tickers, :]].index.get_level_values('portfolio')
return Select(options=sorted(portfolios.unique()))
Column(
'# Dashboard',
Row(
Column(
'## prices',
ind_sel := Select(options=sorted(industries.unique())),
),
Column(
'## trades',
tick_sel := bind(ticker_select, industry=ind_sel),
pf_sel := bind(portfolio_select, industry=ind_sel),
),
),
).servable()
```python -m panel serve from pathlib import Path
from matplotlib.pyplot import subplots from pandas import read_pickle, IndexSlice
from panel import Column, Row, bind from panel.widgets import Select
data_dir = Path(‘data’)
industries = read_pickle(data_dir / ‘industries.pkl’) prices = read_pickle(data_dir / ‘prices.pkl’) trades = read_pickle(data_dir / ‘trades.pkl’)
def ticker_select(industry): if not industry: return ‘Please select industry.’ tickers = industries.loc[lambda s: s == industry].index return Select(options=sorted(tickers.unique()))
def portfolio_select(industry): if not industry: return ‘Please select industry.’ tickers = industries.loc[lambda s: s == industry].index portfolios = trades.loc[IndexSlice[:, :, tickers, :]].index.get_level_values(‘portfolio’) return Select(options=sorted(portfolios.unique()))
def plot_prices(industry): fig, ax = subplots() tickers = industries.loc[lambda s: s == industry].index prices.loc[IndexSlice[:, tickers, :]].unstack(‘ticker’).plot(ax=ax) return fig
def plot_trades(ticker, portfolio): ticker, portfolio = ticker.value, portfolio.value fig, ax = subplots() ( trades.loc[IndexSlice[:, portfolio, ticker, :], ‘price’] .droplevel([‘portfolio’, ‘ticker’]) .plot(ax=ax) ) return fig
Column( ‘# Dashboard’, Row( Column( ‘## prices’, ind_sel := Select(options=sorted(industries.unique())), bind(plot_prices, industry=ind_sel), ), Column( ‘## trades’, tick_sel := bind(ticker_select, industry=ind_sel), port_sel := bind(portfolio_select, industry=ind_sel), bind(plot_trades, ticker=tick_sel, portfolio=port_sel), ), ), ).servable()
```python -m panel serve
from pathlib import Path
from matplotlib.pyplot import subplots
from pandas import read_pickle, IndexSlice
from panel import Column, Row, bind
from panel.widgets import Select
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
trades = read_pickle(data_dir / 'trades.pkl')
def ticker_select(industry):
if not industry:
return '*Please select industry.*'
tickers = industries.loc[lambda s: s == industry].index
return Select(options=sorted(tickers.unique()))
def portfolio_select(industry):
if not industry:
return '*Please select industry.*'
tickers = industries.loc[lambda s: s == industry].index
portfolios = trades.loc[IndexSlice[:, :, tickers, :]].index.get_level_values('portfolio')
return Select(options=sorted(portfolios.unique()))
def plot_prices(industry):
fig, ax = subplots()
tickers = industries.loc[lambda s: s == industry].index
prices.loc[IndexSlice[:, tickers, :]].unstack('ticker').plot(ax=ax)
return fig
def plot_trades(ticker, portfolio):
fig, ax = subplots()
(
trades.loc[IndexSlice[:, portfolio, ticker, :], 'price']
.droplevel(['portfolio', 'ticker'])
.plot(ax=ax)
)
return fig
def trades_col(industry):
return Column(
'## trades',
tick_sel := ticker_select(industry),
port_sel := portfolio_select(industry),
bind(plot_trades, ticker=tick_sel, portfolio=port_sel),
)
Column(
'# Dashboard',
Row(
Column(
'## prices',
ind_sel := Select(options=sorted(industries.unique())),
bind(plot_prices, industry=ind_sel),
),
bind(trades_col, industry=ind_sel),
),
).servable()
```python -m panel serve from numpy import linspace
from bokeh.plotting import figure
from panel import Column, bind from panel.widgets import IntSlider
xs = linspace(-100, +100, 1_001)
def plot(exp): fig = figure(title=’plot’) fig.line(xs, xs**exp) return fig
Column( ‘# Dashboard’, sld := IntSlider(start=1, end=9), bind(plot, exp=sld), ).servable()
```python -m panel serve
from pathlib import Path
from bokeh.plotting import figure
from pandas import read_pickle, IndexSlice
from panel import Column, Row, bind
from panel.widgets import Select
data_dir = Path('data')
industries = read_pickle(data_dir / 'industries.pkl')
prices = read_pickle(data_dir / 'prices.pkl')
trades = read_pickle(data_dir / 'trades.pkl')
def ticker_select(industry):
if not industry:
return '*Please select industry.*'
tickers = industries.loc[lambda s: s == industry].index
return Select(options=sorted(tickers.unique()))
def portfolio_select(industry):
if not industry:
return '*Please select industry.*'
tickers = industries.loc[lambda s: s == industry].index
portfolios = trades.loc[IndexSlice[:, :, tickers, :]].index.get_level_values('portfolio')
return Select(options=sorted(portfolios.unique()))
def plot_prices(industry):
fig = figure(title='prices')
tickers = industries.loc[lambda s: s == industry].index
for t, s in prices.loc[IndexSlice[:, tickers, :], 'bid'].groupby('ticker'):
fig.line(s.index.get_level_values('date'), s.values, legend_label=t)
return fig
def plot_trades(ticker, portfolio):
fig = figure(title='trades')
for (p, t), s in trades.loc[IndexSlice[:, portfolio, ticker, :], 'price'].groupby(['portfolio', 'ticker']):
fig.line(s.index.get_level_values('date'), s.values, legend_label=f'{p}, {t}')
return fig
def trades_col(industry):
return Column(
'## trades',
tick_sel := ticker_select(industry),
port_sel := portfolio_select(industry),
bind(plot_trades, ticker=tick_sel, portfolio=port_sel),
)
Column(
'# Dashboard',
Row(
Column(
'## prices',
ind_sel := Select(options=sorted(industries.unique())),
bind(plot_prices, industry=ind_sel),
),
bind(trades_col, industry=ind_sel),
),
).servable()
print("Let's take a look!")
print("Let's take a look!")
```python -m streamlit run –server.headless true –server.address localhost from streamlit import title
title(‘Dashboard’)
```python -m streamlit run --server.headless true --server.address localhost
from streamlit import title, slider
title('Dashboard')
print(slider('value', 0, 10))
```python -m streamlit run –server.headless true –server.address localhost from numpy import linspace
from bokeh.plotting import figure from streamlit import title, slider, bokeh_chart
xs = linspace(-100, +100, 1_001)
title(‘Dashboard’)
exp = slider(‘value’, 0, 10)
print(f’{exp = }’)
fig = figure(title=’plot’) fig.line(xs, xs ** exp) bokeh_chart(fig)
```python -m streamlit run --server.headless true --server.address localhost
from streamlit import title, multiselect, container, columns
title('Dashboard')
with container():
left, right = columns(2)
with left:
multiselect('industry', options=['a', 'b', 'c'])
with right:
multiselect('portfolio', options=['a', 'b', 'c'])
multiselect('ticker', options=['a', 'b', 'c'])
```python -m streamlit run –server.headless true –server.address localhost from pathlib import Path
from pandas import read_pickle, IndexSlice
from streamlit import title, multiselect, container, columns
data_dir = Path(‘data’)
industries = read_pickle(data_dir / ‘industries.pkl’) prices = read_pickle(data_dir / ‘prices.pkl’) trades = read_pickle(data_dir / ‘trades.pkl’)
title(‘Dashboard’) with container(): left, right = columns(2)
with left:
inds = multiselect('industry', options=sorted(industries.unique()))
ticks = industries.loc[lambda s: s.isin(inds)].index
ports = trades.loc[IndexSlice[:, :, ticks, :]].index.get_level_values('portfolio')
with right:
multiselect('portfolio', options=sorted(ports.unique()))
multiselect('ticker', options=sorted(ticks.unique())) ```
```python -m streamlit run –server.headless true –server.address localhost from pathlib import Path
from pandas import read_pickle, IndexSlice
from bokeh.plotting import figure from streamlit import title, multiselect, container, columns, bokeh_chart
data_dir = Path(‘data’)
industries = read_pickle(data_dir / ‘industries.pkl’) prices = read_pickle(data_dir / ‘prices.pkl’) trades = read_pickle(data_dir / ‘trades.pkl’)
title(‘Dashboard’) with container(): left, right = columns(2, gap=’large’)
with left, container():
inds = multiselect('industry', options=sorted(industries.unique()))
ticks = industries.loc[lambda s: s.isin(inds)].index
ports = trades.loc[IndexSlice[:, :, ticks, :]].index.get_level_values('portfolio')
px_fig = figure()
for t, s in prices.loc[IndexSlice[:, ticks, :], 'bid'].groupby('ticker'):
px_fig.line(s.index.get_level_values('date'), s.values, legend_label=t)
bokeh_chart(px_fig, use_container_width=True)
with right, container():
port = multiselect('portfolio', options=sorted(ports.unique()))
tick = multiselect('ticker', options=sorted(ticks.unique()))
td_fig = figure()
for (p, t), s in (
trades
.loc[IndexSlice[:, port, :, :]]
.loc[IndexSlice[:, :, tick, :]]['price']
.groupby(['portfolio', 'ticker'])
):
td_fig.line(s.index.get_level_values('date'), s.values, legend_label=f'{p}, {t}')
bokeh_chart(px_fig, use_container_width=True) ```
```python -m streamlit run –server.headless true –server.address localhost from pathlib import Path
from pandas import read_pickle, IndexSlice
from bokeh.plotting import figure from streamlit import title, multiselect, container, columns, bokeh_chart, experimental_memo, set_page_config set_page_config(layout=’wide’)
@experimental_memo def load_data(): data_dir = Path(‘data’) return ( read_pickle(data_dir / ‘industries.pkl’), read_pickle(data_dir / ‘prices.pkl’), read_pickle(data_dir / ‘trades.pkl’), ) industries, prices, trades = load_data()
title(‘Dashboard’) with container(): left, right = columns(2, gap=’large’)
with left, container():
inds = multiselect('industry', options=sorted(industries.unique()))
ticks = industries.loc[lambda s: s.isin(inds)].index
ports = trades.loc[IndexSlice[:, :, ticks, :]].index.get_level_values('portfolio')
px_fig = figure()
for t, s in prices.loc[IndexSlice[:, ticks, :], 'bid'].groupby('ticker'):
px_fig.line(s.index.get_level_values('date'), s.values, legend_label=t)
bokeh_chart(px_fig, use_container_width=True)
with right, container():
multiselect('portfolio', options=sorted(ports.unique()))
multiselect('ticker', options=sorted(ticks.unique()))
td_fig = figure()
for (p, t), s in (
trades
.loc[IndexSlice[:, ports, :, :]]
.loc[IndexSlice[:, :, ticks, :]]['price']
.groupby(['portfolio', 'ticker'])
):
td_fig.line(s.index.get_level_values('date'), s.values, legend_label=f'{p}, {t}')
bokeh_chart(px_fig, use_container_width=True) ```