aboutsummaryrefslogtreecommitdiff
path: root/components/overview.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/overview.py')
-rw-r--r--components/overview.py97
1 files changed, 97 insertions, 0 deletions
diff --git a/components/overview.py b/components/overview.py
new file mode 100644
index 0000000..7407753
--- /dev/null
+++ b/components/overview.py
@@ -0,0 +1,97 @@
+"""Company overview — header, key stats, and price chart."""
+import streamlit as st
+import plotly.graph_objects as go
+from services.data_service import get_company_info, get_price_history
+from utils.formatters import fmt_large, fmt_currency, fmt_pct, fmt_ratio
+
+
+PERIODS = {"1 Month": "1mo", "3 Months": "3mo", "6 Months": "6mo", "1 Year": "1y", "5 Years": "5y"}
+
+
+def render_overview(ticker: str):
+ info = get_company_info(ticker)
+ if not info:
+ st.error(f"Could not load data for **{ticker}**. Check the ticker symbol.")
+ return
+
+ # ── Company header ──────────────────────────────────────────────────────
+ name = info.get("longName") or info.get("shortName", ticker.upper())
+ price = info.get("currentPrice") or info.get("regularMarketPrice")
+ prev_close = info.get("regularMarketPreviousClose") or info.get("previousClose")
+
+ price_change = None
+ price_change_pct = None
+ if price and prev_close:
+ price_change = price - prev_close
+ price_change_pct = price_change / prev_close
+
+ col1, col2 = st.columns([3, 1])
+ with col1:
+ st.subheader(f"{name} ({ticker.upper()})")
+ sector = info.get("sector", "")
+ industry = info.get("industry", "")
+ if sector:
+ st.caption(f"{sector} · {industry}")
+
+ with col2:
+ delta_str = None
+ if price_change is not None and price_change_pct is not None:
+ delta_str = f"{price_change:+.2f} ({price_change_pct * 100:+.2f}%)"
+ st.metric(
+ label="Price",
+ value=fmt_currency(price) if price else "—",
+ delta=delta_str,
+ )
+
+ # ── Key stats strip ─────────────────────────────────────────────────────
+ stats_cols = st.columns(6)
+ stats = [
+ ("Mkt Cap", fmt_large(info.get("marketCap"))),
+ ("P/E (TTM)", fmt_ratio(info.get("trailingPE"))),
+ ("EPS (TTM)", fmt_currency(info.get("trailingEps"))),
+ ("52W High", fmt_currency(info.get("fiftyTwoWeekHigh"))),
+ ("52W Low", fmt_currency(info.get("fiftyTwoWeekLow"))),
+ ("Beta", fmt_ratio(info.get("beta"))),
+ ]
+ for col, (label, val) in zip(stats_cols, stats):
+ col.metric(label, val)
+
+ st.divider()
+
+ # ── Price chart ─────────────────────────────────────────────────────────
+ period_label = st.radio(
+ "Period",
+ options=list(PERIODS.keys()),
+ index=3,
+ horizontal=True,
+ label_visibility="collapsed",
+ )
+ period = PERIODS[period_label]
+
+ hist = get_price_history(ticker, period=period)
+ if hist.empty:
+ st.warning("No price history available.")
+ return
+
+ fig = go.Figure()
+ fig.add_trace(
+ go.Scatter(
+ x=hist.index,
+ y=hist["Close"],
+ mode="lines",
+ name="Close",
+ line=dict(color="#4F8EF7", width=2),
+ fill="tozeroy",
+ fillcolor="rgba(79, 142, 247, 0.08)",
+ )
+ )
+ fig.update_layout(
+ margin=dict(l=0, r=0, t=10, b=0),
+ xaxis=dict(showgrid=False, zeroline=False),
+ yaxis=dict(showgrid=True, gridcolor="rgba(255,255,255,0.05)", zeroline=False),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
+ hovermode="x unified",
+ height=320,
+ )
+ st.plotly_chart(fig, use_container_width=True)