aboutsummaryrefslogtreecommitdiff
path: root/components/top_movers.py
blob: ac765043df2ee5f0634cf645017df3403213f6c9 (plain)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""Top Movers component — day gainers, losers, most active."""
import streamlit as st
import yfinance as yf


@st.cache_data(ttl=180)
def _fetch_movers(screen: str, count: int = 8) -> list[dict]:
    try:
        result = yf.screen(screen, count=count)
        return result.get("quotes", [])
    except Exception:
        return []


def _fmt_pct(val) -> str:
    try:
        return f"{float(val):+.2f}%"
    except Exception:
        return "—"


def _fmt_price(val) -> str:
    try:
        return f"${float(val):,.2f}"
    except Exception:
        return "—"


def _mover_row(q: dict):
    symbol = q.get("symbol", "")
    name = q.get("shortName") or q.get("longName") or symbol
    price = q.get("regularMarketPrice")
    chg_pct = q.get("regularMarketChangePercent")
    chg_abs = q.get("regularMarketChange")

    try:
        chg_f = float(chg_pct)
        color = "#2ecc71" if chg_f >= 0 else "#e74c3c"
        sign = "+" if chg_f >= 0 else ""
        pct_str = f"{sign}{chg_f:.2f}%"
    except Exception:
        color = "#9aa0b0"
        pct_str = "—"

    try:
        abs_str = f"({'+' if float(chg_abs) >= 0 else ''}{float(chg_abs):.2f})"
    except Exception:
        abs_str = ""

    col_sym, col_name, col_price, col_chg = st.columns([1, 3, 1.5, 1.5])
    with col_sym:
        st.markdown(f"**{symbol}**")
    with col_name:
        st.caption(name[:40])
    with col_price:
        st.markdown(_fmt_price(price))
    with col_chg:
        st.markdown(
            f"<span style='color:{color};font-weight:600'>{pct_str}</span>"
            f"<span style='font-size:0.75rem;color:#9aa0b0'> {abs_str}</span>",
            unsafe_allow_html=True,
        )


def render_top_movers():
    st.markdown("#### 🔥 Top Movers")

    tab_gainers, tab_losers, tab_active = st.tabs([
        "📈 Gainers", "📉 Losers", "⚡ Most Active"
    ])

    screens = {
        "gainers": "day_gainers",
        "losers": "day_losers",
        "active": "most_actives",
    }

    with tab_gainers:
        quotes = _fetch_movers(screens["gainers"])
        if quotes:
            for q in quotes:
                _mover_row(q)
        else:
            st.caption("No data available.")

    with tab_losers:
        quotes = _fetch_movers(screens["losers"])
        if quotes:
            for q in quotes:
                _mover_row(q)
        else:
            st.caption("No data available.")

    with tab_active:
        quotes = _fetch_movers(screens["active"])
        if quotes:
            for q in quotes:
                _mover_row(q)
        else:
            st.caption("No data available.")