diff options
| author | Tyler <tyler@tylerhoang.xyz> | 2026-03-30 18:54:56 -0700 |
|---|---|---|
| committer | Tyler <tyler@tylerhoang.xyz> | 2026-03-30 18:54:56 -0700 |
| commit | 712bbf675cfcb32535d8c494505e566efa347feb (patch) | |
| tree | 539a874eab3c785e2a8ba9209939bdb3fb4ee978 /services | |
| parent | aa3b1a27118ef0efac056ad135a81181bfb15c8e (diff) | |
Fix EV/EBITDA using income statement EBITDA instead of info dict
yfinance's info["ebitda"] is a miscalculated TTM value for many tickers
(e.g. DDOG shows $7.5M when the correct TTM EBITDA is $193.8M). Added
get_ebitda_from_income_stmt() which reads directly from t.income_stmt,
matching the annual and quarterly figures. Key Ratios and DCF EV/EBITDA
valuation now both use this source, with FMP as the preferred override.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'services')
| -rw-r--r-- | services/data_service.py | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/services/data_service.py b/services/data_service.py index 3de2484..acc935f 100644 --- a/services/data_service.py +++ b/services/data_service.py @@ -158,6 +158,28 @@ def get_insider_transactions(ticker: str) -> pd.DataFrame: return pd.DataFrame() +@st.cache_data(ttl=3600) +def get_ebitda_from_income_stmt(ticker: str) -> float | None: + """Return the most recent annual EBITDA from the income statement. + + yfinance's info['ebitda'] can be badly wrong for companies with large + stock-based compensation (e.g. it may deduct SBC, leaving near-zero EBITDA + even when the income statement EBITDA line is hundreds of millions). + The income statement 'EBITDA' row is the standard EBIT + D&A figure. + """ + try: + t = yf.Ticker(ticker.upper()) + inc = t.income_stmt + for label in ("EBITDA", "Normalized EBITDA"): + if label in inc.index: + val = inc.loc[label].iloc[0] + if val is not None and pd.notna(val): + return float(val) + return None + except Exception: + return None + + @st.cache_data(ttl=900) def get_options_chain(ticker: str) -> dict: """Return options chain data for the nearest available expirations. |
