From bfa2ad1e839b88313a2abeae26ddcd7e9beacd85 Mon Sep 17 00:00:00 2001 From: Tyler Date: Mon, 30 Mar 2026 12:14:56 -0700 Subject: Fix forward estimates field name mismatch with FMP stable API FMP stable /analyst-estimates returns revenueAvg, epsAvg, ebitdaAvg, etc. but the code was looking for estimatedRevenueAvg, estimatedEpsAvg, etc. Updated _build_estimates_table and the EPS chart to read both field name variants so the Forward Estimates tab now renders correctly. Co-Authored-By: Claude Sonnet 4.6 --- components/valuation.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/components/valuation.py b/components/valuation.py index 4dea754..5536818 100644 --- a/components/valuation.py +++ b/components/valuation.py @@ -739,14 +739,15 @@ def _render_forward_estimates(ticker: str): table = [] for row in sorted(rows, key=lambda r: str(r.get("date", ""))): date = str(row.get("date", ""))[:7] - rev_avg = row.get("estimatedRevenueAvg") - rev_lo = row.get("estimatedRevenueLow") - rev_hi = row.get("estimatedRevenueHigh") - eps_avg = row.get("estimatedEpsAvg") - eps_lo = row.get("estimatedEpsLow") - eps_hi = row.get("estimatedEpsHigh") - ebitda_avg = row.get("estimatedEbitdaAvg") - num_analysts = row.get("numberAnalystEstimatedRevenue") or row.get("numberAnalysts") + # FMP stable endpoint uses revenueAvg / epsAvg (no "estimated" prefix) + rev_avg = row.get("revenueAvg") or row.get("estimatedRevenueAvg") + rev_lo = row.get("revenueLow") or row.get("estimatedRevenueLow") + rev_hi = row.get("revenueHigh") or row.get("estimatedRevenueHigh") + eps_avg = row.get("epsAvg") or row.get("estimatedEpsAvg") + eps_lo = row.get("epsLow") or row.get("estimatedEpsLow") + eps_hi = row.get("epsHigh") or row.get("estimatedEpsHigh") + ebitda_avg = row.get("ebitdaAvg") or row.get("estimatedEbitdaAvg") + num_analysts = row.get("numAnalystsRevenue") or row.get("numAnalystsEps") or row.get("numberAnalystEstimatedRevenue") or row.get("numberAnalysts") table.append({ "Period": date, "Rev Low": fmt_large(rev_lo) if rev_lo else "—", @@ -766,9 +767,9 @@ def _render_forward_estimates(ticker: str): fwd_dates, fwd_eps = [], [] for row in sorted(rows, key=lambda r: str(r.get("date", ""))): date = str(row.get("date", ""))[:7] - eps = row.get("estimatedEpsAvg") - eps_lo = row.get("estimatedEpsLow") - eps_hi = row.get("estimatedEpsHigh") + eps = row.get("epsAvg") or row.get("estimatedEpsAvg") + eps_lo = row.get("epsLow") or row.get("estimatedEpsLow") + eps_hi = row.get("epsHigh") or row.get("estimatedEpsHigh") if eps is not None: fwd_dates.append(date) fwd_eps.append(float(eps)) @@ -787,10 +788,10 @@ def _render_forward_estimates(ticker: str): if fwd_dates: # Low/high band - fwd_lo = [float(r["estimatedEpsLow"]) for r in sorted(rows, key=lambda r: str(r.get("date", ""))) - if r.get("estimatedEpsLow") is not None] - fwd_hi = [float(r["estimatedEpsHigh"]) for r in sorted(rows, key=lambda r: str(r.get("date", ""))) - if r.get("estimatedEpsHigh") is not None] + fwd_lo = [float(r.get("epsLow") or r.get("estimatedEpsLow")) for r in sorted(rows, key=lambda r: str(r.get("date", ""))) + if (r.get("epsLow") or r.get("estimatedEpsLow")) is not None] + fwd_hi = [float(r.get("epsHigh") or r.get("estimatedEpsHigh")) for r in sorted(rows, key=lambda r: str(r.get("date", ""))) + if (r.get("epsHigh") or r.get("estimatedEpsHigh")) is not None] if fwd_lo and fwd_hi and len(fwd_lo) == len(fwd_dates): fig.add_trace(go.Scatter( -- cgit v1.3-2-g0d8e