From 4fdcb4ce0f00bc8f62d50ba5d352dd2fe01cd7e7 Mon Sep 17 00:00:00 2001 From: Openclaw Date: Sun, 29 Mar 2026 13:21:39 -0700 Subject: Add historical ratios, forward estimates, insider transactions, SEC filings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - services/fmp_service.py: add get_historical_ratios, get_historical_key_metrics, get_analyst_estimates, get_insider_transactions, get_sec_filings - components/valuation.py: add Historical Ratios and Forward Estimates subtabs - components/insiders.py: new — insider buy/sell summary, monthly chart, detail table - components/filings.py: new — SEC filings with type filter and direct links - app.py: wire in Insiders and Filings top-level tabs --- services/fmp_service.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'services/fmp_service.py') diff --git a/services/fmp_service.py b/services/fmp_service.py index 4dea211..0a3419d 100644 --- a/services/fmp_service.py +++ b/services/fmp_service.py @@ -117,3 +117,46 @@ def get_company_news(ticker: str, limit: int = 20) -> list[dict]: if data and isinstance(data, list): return data return [] + + +@st.cache_data(ttl=86400) +def get_historical_ratios(ticker: str, limit: int = 10) -> list[dict]: + """Annual historical valuation ratios (P/E, P/B, P/S, EV/EBITDA, etc.).""" + data = _get(LEGACY_BASE, f"/ratios/{ticker.upper()}", params={"limit": limit}) + return data if isinstance(data, list) else [] + + +@st.cache_data(ttl=86400) +def get_historical_key_metrics(ticker: str, limit: int = 10) -> list[dict]: + """Annual historical key metrics (ROE, ROA, margins, debt/equity, etc.).""" + data = _get(LEGACY_BASE, f"/key-metrics/{ticker.upper()}", params={"limit": limit}) + return data if isinstance(data, list) else [] + + +@st.cache_data(ttl=3600) +def get_analyst_estimates(ticker: str) -> dict: + """Return annual and quarterly forward analyst estimates.""" + annual = _get(LEGACY_BASE, f"/analyst-estimates/{ticker.upper()}", params={"limit": 5}) + quarterly = _get( + LEGACY_BASE, + f"/analyst-estimates/{ticker.upper()}", + params={"limit": 10, "period": "quarter"}, + ) + return { + "annual": annual if isinstance(annual, list) else [], + "quarterly": quarterly if isinstance(quarterly, list) else [], + } + + +@st.cache_data(ttl=3600) +def get_insider_transactions(ticker: str, limit: int = 50) -> list[dict]: + """Return recent insider buy/sell transactions.""" + data = _get(LEGACY_BASE, "/insider-trading", params={"symbol": ticker.upper(), "limit": limit}) + return data if isinstance(data, list) else [] + + +@st.cache_data(ttl=3600) +def get_sec_filings(ticker: str, limit: int = 30) -> list[dict]: + """Return recent SEC filings (10-K, 10-Q, 8-K, etc.).""" + data = _get(LEGACY_BASE, f"/sec_filings/{ticker.upper()}", params={"limit": limit}) + return data if isinstance(data, list) else [] -- cgit v1.3-2-g0d8e