Python Streamlit in Practice; A Use-Case of Visualizing Stock Data

~How to create an ETF portfolio simulator in Python Streamlit~

Streamlit is becoming one of the great options for creating demos only using Python. I will explain how to create an effective dashboard using Streamlit and deploy Streamlit Cloud with actual stock data.

Quick Demo

Here is my demo of the ETF simulator deployed in Streamlit Cloud.

The source code is here.

Let me explain how to build the dashboard one by one.

Development Environment

Before that, I want to mention the development environment. Preparing an organized environment is essential to develop faster and more steadily.

I recommend using Visual Studio Code for coding and Poetry for managing Python and its libraries. I wrote an article about building the environment, so please take a look if you want.

Data Processing

First, we must process raw stock data into the appropriate format to visualize them.

For instance, you need to calculate portfolio value by multiplying each ETF’s value and the quantity you have.

I will visualize this information in the dashboard, so each graph needs correct format data.

  • Time-series change of overall portfolio value
  • Time-series change of the Sharpe ratio
  • Each stock’s ratio in my portfolio

I don’t explain the data processing part in detail. To see this part, you can check my Jupyter Notebook in my source code.


Once you prepare the data, let’s visualize each of them. I use Plotly, a good-looking graph library for Python.

It’s straightforward to plot the line chart in Plotly. You can do that with two lines of code (except import expression).

# you can run this code in Jupyter Notebook
# stocks: dataframe contains daily stock value
# Date: date like '2022-06-01'
# Close_Portfolio: calculated value of portfolio on the date
import as px
fig = px.line(stocks, x="Date", y="Close_Portfolio")
plot portfolio

There is a blank space in 2018 because these values in this period are null. Thus, drop these rows to plot only valid values. In addition, I don’t need grid lines in the graph so omit them.

fig = px.line(stocks.dropna(subset=['Close_Portfolio']), x="Date", y="Close_Portfolio")
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
plot portfolio (improved)

This graph is much better than the former one.

You can plot the Sharpe ratio the same way with the portfolio. It is said that your portfolio is good if the Sharpe ratio is greater than 1. Therefore, add a baseline to the chart.

# you can run this code in Jupyter Notebook
# sharpe: dataframe contains daily sharpe ratio value
# Date: date like '2022-06-01'
# sharpe_ratio_annual: calculated value of sharpe ratio on the date
fig = px.line(sharpe.dropna(subset=['sharpe_ratio_annual']), x="Date", y="sharpe_ratio_annual")
fig.add_hline(1, line_color="red")
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
plot Sharpe ratio

Looks good!

It’s good to use a pie chart to see the ratio of my portfolio. However, I want to see the portion of each asset’s type and the balance. The diversity of the asset type(e.g., stock, bond, commodity) is vital for our portfolio management. Therefore, I will use a sunburst chart this time.

# you can run this code in Jupyter Notebook
# ratio: dataframe contains tickers and those ratio
# type: asset type like 'stock' or 'bond'
# ticker: asset name like 'VOO' or 'BTC-USD'
# ratio_percent: each ticker's ratio [percent]
fig = px.sunburst(
path=["type", "ticker"],
title="Portfolio Recent Value Ratio"
the plot ratio of each asset in my portfolio

Now we can see each asset’s ratio and type of asset’s ratio.

Organize Dashboard

Each graph is prepared now, so let’s place them on the dashboard. I will use Streamlit to create a dashboard. This dashboard consists of the following functions.

  • Load initial data
  • Process data
  • Visualize graphs
  • Arrange components

Load our data generated in the processing part as initial data.

@st.cache can preserve the result of the function so that you don’t have to load this function every time. Streamlit executes the whole program, so we should use these features to reduce the cost of a re-run.

def read_stock_data_from_local():
stocks = pd.read_pickle("data/stocks.pkl")
ratio = pd.read_pickle("data/ratio.pkl")
sharpe = pd.read_pickle("data/sharpe.pkl")
return sharpe, stocks, ratio

Processing data is needed when we push the calculate button. Time-series data of the portfolio and its Sharpe ratio and the ratio of each asset will be calculated.

This component’s code is complicated, so I describe the whole program. Here is the primary process of this function.

# num_holds(dict): assets and each number of holds
# stocks(dataframe): daily close value of each asset
# ratio(dataframe): each asset ratio in portfolio at the most recent date
# sharpe(dataframe): daily sharpe ratio
# portfolio(dict): detail of each asset
def calc_stock(num_holds, stocks, ratio, portfolio):
# calc portfolio value
stocks["Close_Portfolio"] = stocks.apply(
lambda x: calc_portfolio(x, num_holds), axis=1)
# calc sharpe ratio
sharpe = stocks.loc[:, ["Date", "Close_Portfolio"]]
# calc recent value ratio
ratio = pd.DataFrame(data={"ticker": portfolio["ticker"].keys(), "ratio_percent": recent_values})
return sharpe, stocks, ratio

Visualize three graphs; portfolio, Sharpe ratio, and the ratio of assets.

Streamlit can use charts generated by Plotly only using st.plotly_chart function.

# plot sharpe ratio
fig = px.line(sharpe, x="Date", y="sharpe_ratio_annual")
fig.add_hline(1, line_color="red")
fig.update_xaxes(showgrid=False, zeroline=False)
fig.update_yaxes(showgrid=False, zeroline=False)
st.plotly_chart(fig, use_container_width=True)

Place each component(e.g., title, button, input form, and graphs) using Streamlit.

Arranging components is intuitive so that you can place each part easily. If you want to see examples, visit

One tip to make use of Streamlit is that you can use st.session_state to preserve some variables.

For instance, you can save your current size if you want to see a stock line chart with multiple window sizes. Streamlit always re-runs everything, so you can not keep your state unless you use the variable.

You can write a code like this in that case.

# place four button with different window size
# if you push "Year" button, then window size is saved as 360
if st.button("3Year", key="portfolio"):
st.session_state.window_size = 1080
if st.button("Year", key="portfolio"):
st.session_state.window_size = 360
if st.button("Quarter", key="portfolio"):
st.session_state.window_size = 90
if st.button("Month", key="portfolio"):
st.session_state.window_size = 30

This code looks like this.

Save window size as session state

Deploy Streamlit Cloud

Finally, deploy our program to cloud service to share our apps with people. I will use Streamlit Cloud.

All you have to do is select your repository and configure some settings after signing up.

Configure deploy settings

Streamlit Cloud will install the libraries automatically and deploy our app immediately (if you use Poetry or some package management library).

After a while, our app will be deployed like this.

You can choose the privacy of your app by these settings.

Manage option


In this article, I explained how to process the stock data, visualize them, organize the dashboard, and deploy them to the cloud. I hope this article helps you.



Data Scientist in Japan. Write about DS/ML/AI use-cases

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store