diff options
| author | Openclaw <openclaw@mail.tylerhoang.xyz> | 2026-03-29 01:12:24 -0700 |
|---|---|---|
| committer | Openclaw <openclaw@mail.tylerhoang.xyz> | 2026-03-29 01:12:24 -0700 |
| commit | 547997cbd069e9b958b12a8da38b3a4a257e29e5 (patch) | |
| tree | dbae519a7c6c8f2d803e58e9a77f9a9db73da969 /components/valuation.py | |
| parent | ad6b0b59c2a4f557d6d9d7fe9810c2ba7627580d (diff) | |
Fix valuation methodology and documentation
Diffstat (limited to 'components/valuation.py')
| -rw-r--r-- | components/valuation.py | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/components/valuation.py b/components/valuation.py index 62ee1e3..82e0f0d 100644 --- a/components/valuation.py +++ b/components/valuation.py @@ -61,7 +61,7 @@ def _render_ratios(ticker: str): rows = [ ("Valuation", [ ("P/E (TTM)", r("peRatioTTM", "trailingPE")), - ("Forward P/E", r("priceEarningsRatioTTM", "forwardPE")), + ("Forward P/E", fmt_ratio(info.get("forwardPE")) if info.get("forwardPE") is not None else "—"), ("P/S (TTM)", r("priceToSalesRatioTTM", "priceToSalesTrailing12Months")), ("P/B", r("priceToBookRatioTTM", "priceToBook")), ("EV/EBITDA", r("enterpriseValueMultipleTTM", "enterpriseToEbitda")), @@ -99,6 +99,15 @@ def _render_dcf(ticker: str): info = get_company_info(ticker) shares = info.get("sharesOutstanding") or info.get("floatShares") current_price = info.get("currentPrice") or info.get("regularMarketPrice") + total_debt = info.get("totalDebt") or 0.0 + cash_and_equivalents = ( + info.get("totalCash") + or info.get("cash") + or info.get("cashAndCashEquivalents") + or 0.0 + ) + preferred_equity = info.get("preferredStock") or 0.0 + minority_interest = info.get("minorityInterest") or 0.0 if not shares: st.info("Shares outstanding not available — DCF cannot be computed.") @@ -143,22 +152,40 @@ def _render_dcf(ticker: str): terminal_growth=terminal_growth, projection_years=projection_years, growth_rate_override=fcf_growth_pct / 100, + total_debt=total_debt, + cash_and_equivalents=cash_and_equivalents, + preferred_equity=preferred_equity, + minority_interest=minority_interest, ) if not result: st.warning("Insufficient data to run DCF model.") return + if result.get("error"): + st.warning(result["error"]) + return iv = result["intrinsic_value_per_share"] m1, m2, m3, m4 = st.columns(4) - m1.metric("Intrinsic Value / Share", fmt_currency(iv)) + m1.metric("Equity Value / Share", fmt_currency(iv)) if current_price: upside = (iv - current_price) / current_price m2.metric("Current Price", fmt_currency(current_price)) m3.metric("Upside / Downside", f"{upside * 100:+.1f}%", delta=f"{upside * 100:+.1f}%") m4.metric("FCF Growth Used", f"{result['growth_rate_used'] * 100:.1f}%") + st.caption( + "DCF is modeled on firm-level free cash flow, so enterprise value is bridged to equity value " + "using cash and debt before calculating per-share value." + ) + + bridge1, bridge2, bridge3, bridge4 = st.columns(4) + bridge1.metric("Enterprise Value", fmt_large(result["enterprise_value"])) + bridge2.metric("Net Debt", fmt_large(result["net_debt"])) + bridge3.metric("Equity Value", fmt_large(result["equity_value"])) + bridge4.metric("Terminal Value PV", fmt_large(result["terminal_value_pv"])) + st.write("") years = [f"Year {y}" for y in result["years"]] @@ -173,7 +200,7 @@ def _render_dcf(ticker: str): textposition="outside", )) fig.update_layout( - title="PV of Projected FCFs + Terminal Value (Billions)", + title="Enterprise Value Build: PV of Forecast FCFs + Terminal Value (Billions)", yaxis_title="USD (Billions)", plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)", |
