Stock Financial Analysis with Streamlit and YFinance API

What is Streamlit?

Streamlit is an open-source Python library that allows you to create and share interactive web apps and data visualisations in Python with ease. It includes built-in support for several data visualisation libraries like matplotlib, pandas, and plotly, making it easy to create interactive charts and graphs that update in real-time based on user input. Streamlit is quite popular among data scientists, machine learning engineers and developers looking to create and share interactive web apps with their audience.

Source: Streamlit.io

Build a Streamlit App for Stock Financial Analysis

In this tutorial, we'll use Streamlit to create a simple app that displays financial metrics for a given stock ticker using the Yahoo Finance API. We'll use the pandas library to render the visualisations, but you can also use matplotlib, plotly or others instead. The data that we need for this sample app, including stock and trade information as well as business metrics, is available via the Ticker endpoint. I'll highlight a few code snippets below, but you can find the entire code in my GitHub repository.

To render the historical stock price information, we'll use a simple line chart.

# Plot historical stock price data
if period == "1D":
    history = stock.history(period="1d", interval="1h")
elif period == "5D":
    history = stock.history(period="5d", interval="1d")
elif period == "1M":
    history = stock.history(period="1mo", interval="1d")
elif period == "6M":
    history = stock.history(period="6mo", interval="1wk")
elif period == "YTD":
    history = stock.history(period="ytd", interval="1mo")
elif period == "1Y":
    history = stock.history(period="1y", interval="1mo")
elif period == "5Y":
    history = stock.history(period="5y", interval="3mo")

chart_data = pd.DataFrame(history["Close"])
st.line_chart(chart_data)

We'll display the financial data in three columns - the first highlighting stock information like the sector, industry, market cap etc. Some fields require additional formatting for better readability.

# Display stock information as a dataframe
country = info.get('country', 'N/A')
sector = info.get('sector', 'N/A')
industry = info.get('industry', 'N/A')
market_cap = info.get('marketCap', 'N/A')
ent_value = info.get('enterpriseValue', 'N/A')
employees = info.get('fullTimeEmployees', 'N/A')

stock_info = [
    ("Stock Info", "Value"),
    ("Country", country),
    ("Sector", sector),
    ("Industry", industry),
    ("Market Cap", format_value(market_cap)),
    ("Enterprise Value", format_value(ent_value)),
    ("Employees", employees)
]

df = pd.DataFrame(stock_info[1:], columns=stock_info[0])
col1.dataframe(df, width=400, hide_index=True)

The second column will highlight price information, rendered as a dataframe. We'll restrict each value to two decimal points only.

# Display price information as a dataframe
current_price = info.get('currentPrice', 'N/A')
prev_close = info.get('previousClose', 'N/A')
day_high = info.get('dayHigh', 'N/A')
day_low = info.get('dayLow', 'N/A')
ft_week_high = info.get('fiftyTwoWeekHigh', 'N/A')
ft_week_low = info.get('fiftyTwoWeekLow', 'N/A')

price_info = [
    ("Price Info", "Value"),
    ("Current Price", f"${current_price:.2f}"),
    ("Previous Close", f"${prev_close:.2f}"),
    ("Day High", f"${day_high:.2f}"),
    ("Day Low", f"${day_low:.2f}"),
    ("52 Week High", f"${ft_week_high:.2f}"),
    ("52 Week Low", f"${ft_week_low:.2f}")
]

df = pd.DataFrame(price_info[1:], columns=price_info[0])
col2.dataframe(df, width=400, hide_index=True)

Finally, we'll highlight a few key business metrics like forward EPS, forward P/E ratio, dividend rate/yield, analyst recommendation etc. Obviously, these are not exhaustive - feel free to explore the Ticker endpoint for more details. Next, let's explore how to deploy this app and play around with it.

# Display business metrics as a dataframe
forward_eps = info.get('forwardEps', 'N/A')
forward_pe = info.get('forwardPE', 'N/A')
peg_ratio = info.get('pegRatio', 'N/A')
dividend_rate = info.get('dividendRate', 'N/A')
dividend_yield = info.get('dividendYield', 'N/A')
recommendation = info.get('recommendationKey', 'N/A')

biz_metrics = [
    ("Business Metrics", "Value"),
    ("EPS (FWD)", f"{forward_eps:.2f}"),
    ("P/E (FWD)", f"{forward_pe:.2f}"),
    ("PEG Ratio", f"{peg_ratio:.2f}"),
    ("Div Rate (FWD)", f"${dividend_rate:.2f}"),
    ("Div Yield (FWD)", f"{dividend_yield * 100:.2f}%"),
    ("Recommendation", recommendation.capitalize())
]

df = pd.DataFrame(biz_metrics[1:], columns=biz_metrics[0])
col3.dataframe(df, width=400, hide_index=True)

Deploy the Streamlit App on Railway

Railway is a modern app hosting platform that makes it easy to deploy production-ready apps quickly. Sign up for an account using GitHub, and click Authorize Railway App when redirected. Review and agree to Railway's Terms of Service and Fair Use Policy if prompted. Launch the Streamlit Apps one-click starter template (or click the button below) to deploy the app instantly on Railway.

This template also deploys a Streamlit app that uses the Polygon API for stock ticker information - see this post for more details. Accept the defaults and click Deploy; the deployment will kick off immediately.

Streamlit Apps one-click template on Railway

Once the deployment completes, the Streamlit apps will be available at default xxx.up.railway.app domains - launch each URL to access the respective app. If you are interested in setting up a custom domain, I covered it at length in a previous post - see the final section here.

Streamlit app for stock financial analysis

That's it! Provide different (valid) ticker symbols and explore the results. Also, explore the stock price changes over time based on selected time frames.

Retrieve Stock Information using Polygon API

If you want to try the Polygon API instead of Yahoo Finance API, see this repository for a sample Streamlit web app. Launch the same one-click starter template (or click the button below) to deploy the app instantly on Railway.