"""Exact-math verification tests for the DCF engine. Each scenario independently recomputes the expected projection, discounting, terminal value, enterprise value, equity value, and per-share intrinsic value, then asserts the implementation matches. This makes the test itself auditable. """ import pandas as pd import pytest from app.services.data_service import _run_dcf def _fcf_series(prior: float, base: float) -> pd.Series: """Return a two-point historical FCF series: prior -> base (most recent).""" return pd.Series([prior, base], index=pd.to_datetime(["2023-09-30", "2024-09-30"])) def _expected_dcf( base_fcf: float, growth_rate: float, wacc: float, terminal_growth: float, projection_years: int, shares_outstanding: float, total_debt: float = 0.0, cash_and_equivalents: float = 0.0, preferred_equity: float = 0.0, minority_interest: float = 0.0, ) -> dict: """Independent reference implementation of the DCF math used by `_run_dcf`.""" projected = [base_fcf * ((1 + growth_rate) ** yr) for yr in range(1, projection_years + 1)] discounted = [fcf / ((1 + wacc) ** (year - 0.5)) for year, fcf in enumerate(projected, start=1)] fcf_pv_sum = sum(discounted) terminal_fcf = projected[-1] * (1 + terminal_growth) terminal_value = terminal_fcf / (wacc - terminal_growth) terminal_value_pv = terminal_value / ((1 + wacc) ** (projection_years - 0.5)) enterprise_value = fcf_pv_sum + terminal_value_pv net_debt = total_debt - cash_and_equivalents equity_value = enterprise_value - net_debt - preferred_equity - minority_interest intrinsic_value_per_share = equity_value / shares_outstanding return { "fcf_pv_sum": fcf_pv_sum, "terminal_value_pv": terminal_value_pv, "enterprise_value": enterprise_value, "net_debt": net_debt, "equity_value": equity_value, "intrinsic_value_per_share": intrinsic_value_per_share, } _APPROX = pytest.approx def test_run_dcf_one_year_with_equity_bridge() -> None: """1-year projection with debt, cash, preferred, and minority claims.""" fcf = _fcf_series(100.0, 105.0) # exact 5% growth expected = _expected_dcf( base_fcf=105.0, growth_rate=0.05, wacc=0.10, terminal_growth=0.03, projection_years=1, shares_outstanding=10.0, total_debt=20.0, cash_and_equivalents=5.0, preferred_equity=2.0, minority_interest=3.0, ) result = _run_dcf( fcf_series=fcf, shares_outstanding=10.0, wacc=0.10, terminal_growth=0.03, projection_years=1, total_debt=20.0, cash_and_equivalents=5.0, preferred_equity=2.0, minority_interest=3.0, ) assert result["base_fcf"] == 105.0 assert result["growth_rate_used"] == _APPROX(0.05) assert result["fcf_pv_sum"] == _APPROX(expected["fcf_pv_sum"]) assert result["terminal_value_pv"] == _APPROX(expected["terminal_value_pv"]) assert result["enterprise_value"] == _APPROX(expected["enterprise_value"]) assert result["net_debt"] == expected["net_debt"] assert result["equity_value"] == _APPROX(expected["equity_value"]) assert result["intrinsic_value_per_share"] == _APPROX(expected["intrinsic_value_per_share"]) def test_run_dcf_three_years_no_claims() -> None: """3-year projection with a clean capital structure.""" fcf = _fcf_series(100.0, 105.0) expected = _expected_dcf( base_fcf=105.0, growth_rate=0.05, wacc=0.10, terminal_growth=0.03, projection_years=3, shares_outstanding=10.0, ) result = _run_dcf( fcf_series=fcf, shares_outstanding=10.0, wacc=0.10, terminal_growth=0.03, projection_years=3, ) assert result["base_fcf"] == 105.0 assert result["fcf_pv_sum"] == _APPROX(expected["fcf_pv_sum"]) assert result["terminal_value_pv"] == _APPROX(expected["terminal_value_pv"]) assert result["enterprise_value"] == _APPROX(expected["enterprise_value"]) assert result["equity_value"] == _APPROX(expected["equity_value"]) assert result["intrinsic_value_per_share"] == _APPROX(expected["intrinsic_value_per_share"]) assert result["net_debt"] == 0.0 def test_run_dcf_five_years_default_horizon() -> None: """5-year projection matching the API default horizon.""" fcf = _fcf_series(100.0, 105.0) expected = _expected_dcf( base_fcf=105.0, growth_rate=0.05, wacc=0.10, terminal_growth=0.03, projection_years=5, shares_outstanding=10.0, ) result = _run_dcf( fcf_series=fcf, shares_outstanding=10.0, wacc=0.10, terminal_growth=0.03, projection_years=5, ) assert result["base_fcf"] == 105.0 assert result["fcf_pv_sum"] == _APPROX(expected["fcf_pv_sum"]) assert result["terminal_value_pv"] == _APPROX(expected["terminal_value_pv"]) assert result["enterprise_value"] == _APPROX(expected["enterprise_value"]) assert result["equity_value"] == _APPROX(expected["equity_value"]) assert result["intrinsic_value_per_share"] == _APPROX(expected["intrinsic_value_per_share"]) def test_run_dcf_zero_growth_flat_fcf() -> None: """Edge of the model: zero growth projects a flat FCF stream.""" fcf = _fcf_series(100.0, 100.0) # exact 0% growth expected = _expected_dcf( base_fcf=100.0, growth_rate=0.0, wacc=0.10, terminal_growth=0.02, projection_years=5, shares_outstanding=10.0, ) result = _run_dcf( fcf_series=fcf, shares_outstanding=10.0, wacc=0.10, terminal_growth=0.02, projection_years=5, ) assert result["growth_rate_used"] == _APPROX(0.0) assert result["fcf_pv_sum"] == _APPROX(expected["fcf_pv_sum"]) assert result["terminal_value_pv"] == _APPROX(expected["terminal_value_pv"]) assert result["enterprise_value"] == _APPROX(expected["enterprise_value"]) assert result["intrinsic_value_per_share"] == _APPROX(expected["intrinsic_value_per_share"]) def test_run_dcf_uses_historical_growth_rate() -> None: """End-to-end check that the growth-rate estimator feeds the projection. A series rising exactly 5% per year should produce the same 5-year result as the hand-computed 5-year scenario (within float tolerance). """ fcf = _fcf_series(100.0, 105.0) expected = _expected_dcf( base_fcf=105.0, growth_rate=0.05, wacc=0.10, terminal_growth=0.03, projection_years=5, shares_outstanding=10.0, ) result = _run_dcf( fcf_series=fcf, shares_outstanding=10.0, wacc=0.10, terminal_growth=0.03, projection_years=5, ) assert result["growth_rate_used"] == _APPROX(0.05) assert result["intrinsic_value_per_share"] == _APPROX(expected["intrinsic_value_per_share"])