A Python implementation of a Discounted Cash Flow (DCF) valuation model: take a company's fundamentals as input, get an intrinsic value per share as output, and stress-test the result with a two-way sensitivity analysis on WACC and terminal growth.
I built this to put into code the valuation logic I study at Bocconi and encounter in M&A-related research — every intermediate step (cash flows, discount factors, terminal value) is exposed rather than hidden, because in a DCF the assumptions are the analysis.
The model follows the standard unlevered DCF:
1. Project Free Cash Flow to the Firm over an explicit horizon:
FCFF = EBIT × (1 − tax rate) + D&A − CapEx − ΔNWC
Revenue grows at user-defined rates (one per year); margins and reinvestment are modeled as percentages of revenue.
2. Terminal value at the end of the horizon (Gordon Growth):
TV = FCFF_final × (1 + g) / (WACC − g)
3. Discount each cash flow and the terminal value at the WACC.
4. Bridge to equity:
Equity value = Enterprise value − Net debt
Value per share = Equity value / Shares outstanding
5. Sensitivity analysis — value per share across a WACC × terminal growth grid, as a pandas table and a heatmap. In the example, terminal value is ~73% of enterprise value, which is exactly why this table matters.
from dcf import CompanyInputs, run_dcf, sensitivity_table
company = CompanyInputs(
name="Alpina Industries",
revenue=1200.0,
ebit_margin=0.14,
tax_rate=0.26,
depreciation_pct=0.045,
capex_pct=0.055,
nwc_pct=0.10,
revenue_growth=[0.07, 0.06, 0.05, 0.04, 0.03],
terminal_growth=0.02,
wacc=0.09,
net_debt=350.0,
shares_outstanding=100.0,
)
result = run_dcf(company)
print(result.value_per_share) # 14.51
table = sensitivity_table(company,
wacc_range=[0.07, 0.08, 0.09, 0.10, 0.11],
growth_range=[0.010, 0.015, 0.020, 0.025, 0.030])
print(table)Or run the full worked example:
python examples/example_valuation.pyExample sensitivity output (value per share, €):
| WACC \ g | 1.00% | 1.50% | 2.00% | 2.50% | 3.00% |
|---|---|---|---|---|---|
| 7.00% | 18.30 | 19.90 | 21.83 | 24.18 | 27.12 |
| 8.00% | 15.13 | 16.25 | 17.56 | 19.10 | 20.96 |
| 9.00% | 12.75 | 13.57 | 14.51 | 15.59 | 16.85 |
| 10.00% | 10.91 | 11.53 | 12.22 | 13.01 | 13.92 |
| 11.00% | 9.43 | 9.91 | 10.45 | 11.04 | 11.72 |
dcf/
├── model.py # inputs, FCFF projection, terminal value, DCF engine
└── sensitivity.py # two-way sensitivity table + heatmap
examples/
└── example_valuation.py
Python 3.10+, pandas, numpy, matplotlib:
pip install -r requirements.txtThis is deliberately a clean core model, not a terminal. Known simplifications: WACC is an input (no bottom-up beta / capital structure build), FCFF drivers are flat percentages of revenue, and there is no mid-year convention. Natural next steps: exit-multiple terminal value, scenario presets (bull/base/bear), and pulling fundamentals from an API instead of manual input.
Alessandro Gaudio