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.")
|