1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
"""Financial statements — Income Statement, Balance Sheet, Cash Flow."""
import pandas as pd
import streamlit as st
from services.data_service import get_income_statement, get_balance_sheet, get_cash_flow
from utils.formatters import fmt_large
def _format_statement(df: pd.DataFrame) -> pd.DataFrame:
"""Format a yfinance financial statement for display."""
if df.empty:
return df
# Columns are datetime; convert to year strings
df = df.copy()
df.columns = [str(c)[:10] for c in df.columns]
# Add YoY % change columns if >= 2 periods
cols = list(df.columns)
result = pd.DataFrame(index=df.index)
for i, col in enumerate(cols):
result[col] = df[col].apply(_fmt_cell)
if i + 1 < len(cols):
prev_col = cols[i + 1]
yoy = df.apply(
lambda row: _yoy_pct(row[col], row[prev_col]), axis=1
)
result[f"YoY {col[:4]}"] = yoy
return result
def _fmt_cell(value) -> str:
try:
v = float(value)
except (TypeError, ValueError):
return "—"
return fmt_large(v)
def _yoy_pct(current, previous) -> str:
try:
c, p = float(current), float(previous)
if p == 0:
return "—"
pct = (c - p) / abs(p) * 100
arrow = "▲" if pct >= 0 else "▼"
return f"{arrow} {abs(pct):.1f}%"
except (TypeError, ValueError):
return "—"
def render_financials(ticker: str):
col1, col2 = st.columns([1, 3])
with col1:
freq = st.radio("Frequency", ["Annual", "Quarterly"], horizontal=False)
quarterly = freq == "Quarterly"
tab_income, tab_balance, tab_cashflow = st.tabs(
["Income Statement", "Balance Sheet", "Cash Flow"]
)
with tab_income:
df = get_income_statement(ticker, quarterly=quarterly)
if df.empty:
st.info("Income statement data unavailable.")
else:
st.dataframe(_format_statement(df), use_container_width=True)
with tab_balance:
df = get_balance_sheet(ticker, quarterly=quarterly)
if df.empty:
st.info("Balance sheet data unavailable.")
else:
st.dataframe(_format_statement(df), use_container_width=True)
with tab_cashflow:
df = get_cash_flow(ticker, quarterly=quarterly)
if df.empty:
st.info("Cash flow data unavailable.")
else:
st.dataframe(_format_statement(df), use_container_width=True)
|