DCF 法(Discounted Cash Flow、割引キャッシュフロー法)は、企業の 理論株価 を将来キャッシュフローの現在価値の合計として求める手法です。本記事では、最小構成の DCF を Python の関数で再現し、仮定の壊れやすさを整理します。
目次
- DCF の発想
- DCF の式(2 段階モデル)
- 仮定が結果を強く左右する
- Python で最小 DCF を書く
- 株主価値・1 株あたり理論価値に変換する
- 感応度分析(センシティビティ)
- 「正解の理論株価」は出ない
- DCF を使うときのチェックリスト
- DCF を使わないほうが良いケース
DCF の発想
DCF の根っこは「1 年後の 100 円より、いま手元にある 100 円のほうが価値が高い」という時間価値の発想です。将来のお金は、いまの価値に 割り引いて 評価します。
割り引くときに使う率を 割引率(r) と呼びます。1 年後の 100 円は、現在価値で
になります。 年後なら、
です。これを将来の各年について合計したものが、企業の理論価値の核になります。
DCF の式(2 段階モデル)
最小構成として、よく使われる 2 段階モデル を紹介します。
- 予測期間(数年〜10 年)の各年のフリーキャッシュフロー(FCF)を成長率 で外挿
- 予測期間の終わり以降は、永久成長率 で永続するとして ターミナルバリュー(TV) を計算
- それぞれを割引率 で現在価値に割り引いて合計
予測期間 年・初年度 FCF ・成長率 ・永久成長率 ・割引率 のとき、
ターミナルバリューはゴードンモデルで、
として求めます。
ここから 1 株あたり理論価値を出すには、企業価値から 有利子負債 を差し引いた 株主価値 を、発行済株式数で割ります。
仮定が結果を強く左右する
DCF は「式は単純、仮定が結果を強く左右する」のが特徴です。次のパラメータをわずかに動かすだけで、理論株価は大きく変わります。
- 初年度 FCF の確からしさ
- 予測期間中の成長率
- 永久成長率 (マクロ経済成長率の上限を超えない)
- 割引率 (WACC として算出することが多い)
「仮定の壊れやすさ」を理解しておくのが、DCF を使ううえで一番重要なポイントです。
Python で最小 DCF を書く
最小構成の DCF を関数として実装します。
def dcf_two_stage( fcf0: float, g1: float, g2: float, r: float, years: int = 5,) -> dict: """2 段階 DCF で企業価値を返す(教育目的の最小実装)。
Args: fcf0: 初年度 FCF。 g1: 予測期間中の成長率(0.05 = 5%)。 g2: 永久成長率(0.01 = 1%)。 r: 割引率(0.08 = 8%)。 years: 予測期間の年数。
Returns: 各構成要素を含む dict。 """ if r <= g2: raise ValueError("割引率 r は永久成長率 g2 より大きい必要があります")
# 予測期間中の FCF の現在価値合計 pv_explicit = 0.0 fcf_t = fcf0 for t in range(1, years + 1): fcf_t = fcf0 * (1 + g1) ** t pv_explicit += fcf_t / (1 + r) ** t
# ターミナルバリューの現在価値 tv = fcf_t * (1 + g2) / (r - g2) pv_tv = tv / (1 + r) ** years
return { "pv_explicit": round(pv_explicit, 2), "tv": round(tv, 2), "pv_tv": round(pv_tv, 2), "enterprise_value": round(pv_explicit + pv_tv, 2), }
result = dcf_two_stage(fcf0=100, g1=0.05, g2=0.01, r=0.08, years=5)print(result)実行すると、予測期間の現在価値合計・ターミナルバリュー・その現在価値・企業価値の合計が返ります。r <= g2 のとき式が破綻するので、明示的にエラーを出すようにしています。
株主価値・1 株あたり理論価値に変換する
企業価値から有利子負債を差し引き、現預金を足し戻すと、株主価値 に近づきます。
def fair_value_per_share( enterprise_value: float, interest_debt: float, cash: float, shares: int,) -> float: """企業価値から 1 株あたり理論価値を返す。""" if shares <= 0: raise ValueError("発行済株式数は正の値である必要があります") equity_value = enterprise_value - interest_debt + cash return equity_value / shares
ev = result["enterprise_value"] # 億円単位の想定fv = fair_value_per_share(ev, interest_debt=500, cash=200, shares=10_000_000)print(round(fv, 2))サンプル値は単位の整合さえ取れていれば動きます。実データでは円・百万円・億円の単位を 入力時点で統一 しておくのが安全です。
感応度分析(センシティビティ)
DCF はパラメータに敏感です。感応度表 を作って、仮定が動いたときに理論株価がどう変わるかを見せると、結果の頑健さが分かります。
import pandas as pd
g1_grid = [0.02, 0.04, 0.06, 0.08, 0.10]r_grid = [0.06, 0.07, 0.08, 0.09, 0.10]
rows = []for r_val in r_grid: row = {"r": r_val} for g1_val in g1_grid: ev = dcf_two_stage( fcf0=100, g1=g1_val, g2=0.01, r=r_val, years=5 )["enterprise_value"] row[f"g1={g1_val:.0%}"] = round(ev, 1) rows.append(row)
table = pd.DataFrame(rows).set_index("r")print(table)「割引率 r が 1% 動いた時」と「成長率 g1 が 2% 動いた時」では、企業価値が桁違いに動くことが珍しくありません。感応度表は 仮定が結果を強く左右する ことを視覚的に示してくれます。
「正解の理論株価」は出ない
DCF を使ううえで誤解しやすいのは「精密に計算すれば正しい株価が出る」と考えてしまうことです。
実際は次のような構造です。
- 仮定がぶれれば結果もぶれる
- 仮定の妥当性は 誰にも完全には分からない(将来の話だから)
- DCF が示すのは「この仮定が正しいなら 理論株価はこれ」という 条件付きの数字
DCF 法は「決定的な答えを出す道具」ではなく、「仮定を整理して議論するための共通言語」と捉えるほうが、実用上は正確です。
DCF を使うときのチェックリスト
実用するときに最低限確認したい点を並べます。
- 予測期間の FCF は、過去実績と整合しているか
- 成長率 は、その業種の現実的な水準を超えていないか
- 永久成長率 は、マクロ成長率(2〜3% 程度)を超えていないか
- 割引率 は より大きいか(等号や逆転は破綻)
- 単位(円 / 百万円 / 億円)が混在していないか
- 感応度表で、結果がパラメータにどれだけ敏感かを確認したか
- FCF の定義(営業 CF − 設備投資 / 別の式)を統一したか
これらを通せば、最低限「自分の仮定で計算した結果」と言える段階になります。
DCF を使わないほうが良いケース
DCF が苦手とする領域もあります。
- 赤字 / FCF がマイナスのスタートアップ
- ライフサイクルが短い事業(ゲーム / 流行系)
- M&A の影響が大きい時期(過去 FCF からの外挿が効かない)
- 規制 / 政策で需要構造が大きく変わる業種
これらの領域では、PER / PBR / 比較企業法など別の枠組みも併用します。
生成AI へのプロンプト例
DCF の感応度ヒートマップを描く依頼の例です。
入力:- fcf0 (float): 初年度 FCF- years (int): 予測期間の年数- g2 (float): 永久成長率(固定)
依頼: g1 と r の組み合わせで企業価値を計算し、ヒートマップで描画する関数を書いてください。
仕様:- g1 は 0.00 〜 0.10 を 0.01 刻み、r は 0.04 〜 0.12 を 0.01 刻み- 各セルに企業価値を表示(annot=True)- カラーマップは数値が大きいほど濃く- タイトル・軸ラベルは日本語
要件: pandas 2.2 系 + matplotlib + seaborn(または matplotlib のみ)。docstring は日本語。まとめ
- DCF は「将来 FCF の現在価値の合計」で理論価値を求める方法
- 2 段階モデル: 予測期間の FCF 現在価値 + ターミナルバリューの現在価値
- 仮定(成長率・割引率・期間)が結果を強く左右する
- 感応度表で結果の頑健さを確認する
- 「条件付きの数字」であり、決定的な正解は出ない