aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorTyler <tyler@tylerhoang.xyz>2026-05-14 01:01:02 -0700
committerTyler <tyler@tylerhoang.xyz>2026-05-14 01:01:02 -0700
commit764cd69bfc2e5a0cf504c8d6e4f032d35edd9a4c (patch)
tree0143dbd55cceded1b8f4a8c689888fa9a76152ca /services
parent679baae2773dc7eaf419648ac7a59c4734fca735 (diff)
Completely refreshed Key Ratios, Historical Ratios, and DCF/Multiples
tab.
Diffstat (limited to 'services')
-rw-r--r--services/fmp_service.py29
1 files changed, 25 insertions, 4 deletions
diff --git a/services/fmp_service.py b/services/fmp_service.py
index 914c14d..c72524f 100644
--- a/services/fmp_service.py
+++ b/services/fmp_service.py
@@ -2,6 +2,7 @@
import os
import requests
import streamlit as st
+from concurrent.futures import ThreadPoolExecutor, as_completed
from dotenv import load_dotenv
from services.data_service import get_company_info, get_historical_ratios_yfinance, compute_ttm_ratios
@@ -76,6 +77,17 @@ def get_key_ratios(ticker: str) -> dict:
if info.get("forwardPE") is not None:
merged["forwardPE"] = info["forwardPE"]
+ # Growth fields — yfinance info provides these directly
+ for key, alias in (
+ ("revenueGrowth", "revenueGrowthTTM"),
+ ("earningsGrowth", "earningsGrowthTTM"),
+ ):
+ val = info.get(key)
+ if val is not None:
+ try:
+ merged[alias] = float(val)
+ except (TypeError, ValueError):
+ pass
# Fallback: dividends from info dict when cash-flow data is missing
if merged.get("dividendYieldTTM") is None and info.get("dividendYield") is not None:
merged["dividendYieldTTM"] = info["dividendYield"]
@@ -116,13 +128,22 @@ def get_peers(ticker: str) -> list[str]:
@st.cache_data(ttl=3600)
def get_ratios_for_tickers(tickers: list[str]) -> list[dict]:
- """Return merged TTM ratios/metrics rows for a list of tickers."""
- results = []
- for t in tickers:
+ """Return merged TTM ratios/metrics rows for a list of tickers, fetched in parallel."""
+ def _fetch(t: str) -> dict | None:
row = get_key_ratios(t)
if row:
+ row = dict(row)
row["symbol"] = t.upper()
- results.append(row)
+ return row
+ return None
+
+ results = []
+ with ThreadPoolExecutor(max_workers=min(len(tickers), 8)) as pool:
+ futures = {pool.submit(_fetch, t): t for t in tickers}
+ for future in as_completed(futures):
+ result = future.result()
+ if result:
+ results.append(result)
return results