"""合成FCFF DCF;年度末折现,金额/股本均以百万计。""" import json from decimal import Decimal as D drivers = [("100", "5", "8", "2"), ("110", "5", "9", "3"), ("120", "6", "10", "3")] def dcf(wacc=D("0.10"), growth=D("0.02"), currency="CNY", debt_currency="CNY", shares=D("100")): if currency != debt_currency: raise ValueError("mixed_currency") if not wacc > growth or shares <= 0: raise ValueError("invalid_terminal_or_shares") flows = [D(ebit) * (1-D("0.25")) + D(da) - D(capex) - D(wc) for ebit, da, capex, wc in drivers] pv = [fcff / (1+wacc)**t for t, fcff in enumerate(flows, 1)] terminal = flows[-1] * (1+growth) / (wacc-growth) terminal_pv = terminal / (1+wacc)**len(flows) enterprise = sum(pv) + terminal_pv equity = enterprise - D("150") + D("30") return {"fcff": flows, "pv": pv, "terminal": terminal, "terminal_pv": terminal_pv, "enterprise": enterprise, "equity": equity, "per_share": equity/shares} base = dcf() assert base["fcff"] == [D("70.00"), D("75.50"), D("83.00")] assert abs(base["enterprise"] - (sum(base["pv"]) + base["terminal_pv"])) < D("0.000001") assert dcf(wacc=D("0.11"))["per_share"] < base["per_share"] sensitivity = {str(w): str(dcf(wacc=w)["per_share"].quantize(D("0.01"))) for w in [D("0.09"), D("0.10"), D("0.11")]} assert sensitivity == {"0.09": "10.06", "0.10": "8.63", "0.11": "7.53"} blocked = [] for kwargs in [{"growth": D("0.10")}, {"debt_currency": "USD"}, {"shares": D("0")}]: try: dcf(**kwargs) except ValueError as exc: blocked.append(str(exc)) assert len(blocked) == 3 print(json.dumps({"fcff": [str(x) for x in base["fcff"]], "enterprise": str(base["enterprise"].quantize(D("0.01"))), "equity": str(base["equity"].quantize(D("0.01"))), "per_share": str(base["per_share"].quantize(D("0.01"))), "terminal_share": str((base["terminal_pv"]/base["enterprise"]).quantize(D("0.0001"))), "sensitivity": sensitivity, "blocked": blocked}, sort_keys=True))