aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorTyler <tyler@tylerhoang.xyz>2026-03-29 15:41:42 -0700
committerTyler <tyler@tylerhoang.xyz>2026-03-29 15:41:42 -0700
commit3e1324eff69e4b121f85223758b872c7fb5dc027 (patch)
treeb9e34a461460036c4aac1fdc7dab33763ef255ce /services
parent4fdcb4ce0f00bc8f62d50ba5d352dd2fe01cd7e7 (diff)
Migrate insiders and filings from FMP to yfinance
FMP v3 insider-trading and sec_filings endpoints are legacy-gated. Switch to yfinance (t.insider_transactions, t.sec_filings) which provides the same data for free with no API key required. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'services')
-rw-r--r--services/data_service.py26
1 files changed, 26 insertions, 0 deletions
diff --git a/services/data_service.py b/services/data_service.py
index 0399c58..5ac8573 100644
--- a/services/data_service.py
+++ b/services/data_service.py
@@ -146,6 +146,32 @@ def get_next_earnings_date(ticker: str) -> str | None:
@st.cache_data(ttl=3600)
+def get_insider_transactions(ticker: str) -> pd.DataFrame:
+ """Return insider transactions from yfinance.
+ Columns: Shares, URL, Text, Insider, Position, Transaction, Start Date, Ownership, Value
+ """
+ try:
+ t = yf.Ticker(ticker.upper())
+ df = t.insider_transactions
+ return df if df is not None and not df.empty else pd.DataFrame()
+ except Exception:
+ return pd.DataFrame()
+
+
+@st.cache_data(ttl=3600)
+def get_sec_filings(ticker: str) -> list[dict]:
+ """Return SEC filings from yfinance.
+ Each dict has: date, type, title, edgarUrl, exhibits.
+ """
+ try:
+ t = yf.Ticker(ticker.upper())
+ filings = t.sec_filings
+ return filings if filings else []
+ except Exception:
+ return []
+
+
+@st.cache_data(ttl=3600)
def get_free_cash_flow_series(ticker: str) -> pd.Series:
"""Return annual Free Cash Flow series (most recent first)."""
t = yf.Ticker(ticker.upper())