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
101
102
103
104
105
106
107
108
|
"""SEC filings — recent 10-K, 10-Q, 8-K and other forms with direct links."""
import streamlit as st
from services.data_service import get_sec_filings
_FORM_DESCRIPTIONS = {
"10-K": "Annual report",
"10-Q": "Quarterly report",
"8-K": "Material event disclosure",
"DEF 14A": "Proxy statement",
"S-1": "IPO registration",
"S-3": "Securities registration",
"4": "Insider ownership change",
"SC 13G": "Beneficial ownership (passive)",
"SC 13D": "Beneficial ownership (active)",
}
_FORM_COLORS = {
"10-K": "rgba(74,120,181,0.15)",
"10-Q": "rgba(79,140,94,0.15)",
"8-K": "rgba(196,149,69,0.15)",
}
def render_filings(ticker: str):
with st.spinner("Loading SEC filings…"):
filings = get_sec_filings(ticker)
if not filings:
st.info("No SEC filing data available for this ticker.")
return
# yfinance returns: date (datetime.date), type, title, edgarUrl, exhibits (dict)
form_types = sorted({str(f.get("type", "")).strip() for f in filings if f.get("type")})
priority = [t for t in ["10-K", "10-Q", "8-K"] if t in form_types]
other = [t for t in form_types if t not in ("10-K", "10-Q", "8-K")]
filter_options = ["All"] + priority + other
filter_col, _ = st.columns([1, 3])
with filter_col:
selected_type = st.selectbox("Form type", options=filter_options, index=0, key="filings_filter")
# Summary counts
counts = {}
for f in filings:
ft = str(f.get("type", "Other")).strip()
counts[ft] = counts.get(ft, 0) + 1
if priority:
cols = st.columns(len(priority))
for col, ft in zip(cols, priority):
col.metric(ft, counts.get(ft, 0))
st.write("")
filtered = filings if selected_type == "All" else [
f for f in filings if str(f.get("type", "")).strip() == selected_type
]
if not filtered:
st.info("No filings match the current filter.")
return
for item in filtered[:40]:
form = str(item.get("type", "—")).strip()
date = str(item.get("date", ""))[:10]
title = item.get("title") or _FORM_DESCRIPTIONS.get(form, "")
edgar_url = item.get("edgarUrl", "")
exhibits = item.get("exhibits") or {}
color = _FORM_COLORS.get(form, "rgba(255,255,255,0.05)")
with st.container():
left, right = st.columns([5, 1])
with left:
st.markdown(
f"<div style='"
f"background:{color};"
f"border:1px solid rgba(194,170,122,0.12);"
f"padding:8px 12px;border-radius:2px;margin-bottom:2px;"
f"display:flex;align-items:baseline;gap:10px;"
f"'>"
f"<span style='"
f"font-family:IBM Plex Mono,monospace;"
f"font-size:11px;color:#C2AA7A;"
f"background:rgba(194,170,122,0.07);"
f"border:1px solid rgba(194,170,122,0.25);"
f"padding:2px 6px;border-radius:2px;"
f"white-space:nowrap;"
f"'>{form}</span>"
f"<span style='font-family:IBM Plex Sans,sans-serif;font-size:0.8125rem;color:#F2ECDC;'>{title}</span>"
f"<span style='font-family:IBM Plex Mono,monospace;font-size:11px;color:#5E5849;margin-left:auto;white-space:nowrap;'>{date}</span>"
f"</div>",
unsafe_allow_html=True,
)
with right:
doc_url = exhibits.get(form) or edgar_url
if doc_url:
st.markdown(
f"<div style='padding-top:8px;text-align:right;'>"
f"<a href='{doc_url}' target='_blank' style='"
f"font-family:IBM Plex Sans,sans-serif;"
f"font-size:11px;color:#C2AA7A;"
f"text-decoration:none;"
f"border-bottom:1px solid #8F7A50;"
f"'>View ↗</a></div>",
unsafe_allow_html=True,
)
|