A Streamlit dashboard that fetches fundamentals for Nifty 50 constituents and runs a discounted-cash-flow valuation — FCFF, WACC discount, Gordon Growth terminal value, enterprise value, equity value, per-share intrinsic value — flags data-quality issues, and compares intrinsic value against the live market price.
Split out of the old nifty-beta-clustering monorepo, where it lived as dcf_model/.
Verified correct
The terminal-value formula with its WACC ≤ g guard, the discounting periods, and the full enterprise-to-per-share chain were independently re-derived by hand against a synthetic test case and matched exactly. Verified live against real Reliance Industries data (WACC ≈ 8.3%, intrinsic value ≈ ₹604).
Fixed in review
- The most serious finding: an after-hours price fetch could return NaN for the latest session, and since NaN is truthy in Python, every downstream `if price:` check passed — silently producing a confident "🔴 Overvalued" verdict with a nan% margin of safety, a fabricated-looking result with no real number behind it. Fixed by cleaning NaN rows before use.
- A FCFF double-counting bug: when direct EBIT was unavailable, EBITDA was used as EBIT and then depreciation and amortization added again on top — EBITDA already includes D&A — overstating free cash flow by about 18% in the reviewer's test case.
- A stale docstring path left from the repo extraction.
- A mixed string/int table column that Streamlit was silently auto-recovering from, masking a real defect — caught only by actually executing the app through Streamlit's AppTest harness.
DCFFCFFWACCStreamlit