💰

新卒IBD→エンジニアが語る、DCFモデルとプログラミングの共通点

に公開

この記事は、ナウキャスト Advent Calendar 2025 の17日目の記事です。

はじめに

こんにちは。ナウキャストのエンジニアのふじいと申します。

私は新卒で入社した某大手証券会社の投資銀行部門(IBD)に3年弱ほど務めた後、未経験でエンジニアに転身して早くも3年が経ちました。とても珍しいキャリアだと思いますし、今思い返してもよく転職の決断をしたと、過去の自分をカッコいいと思ってます。

今回は、そんな稀有なキャリアだからこそ語ることができる、「DCFモデル(Discounted Cash Flow Model)とプログラミングの共通点」 について、少しマニアックに語ろうと思います。
(エクセルに埋め込む関数やコードはわかりやすさを重視で簡略化している点があります)

そもそも「DCFモデル」とは何か?

本題に入る前に、少しだけドメイン知識の解説をします。DCF(Discounted Cash Flow)法とは、 「企業の『将来の稼ぎ』を、今の価値に換算するアルゴリズム」 です。M&Aや株式投資において、「この会社はいくらで買うべきか?」という適正価格を算出するための計算ロジックになります。

核心にあるロジックは「お金の時間的価値」です。今手元にある100万円は、運用すれば増える可能性があるため、1年後に貰える100万円よりも価値が高いとされます。逆に言うと、将来の稼ぎを現在の価値に見積もるには、「割り引く(Discount)」必要があります。

PV = \frac{CF}{(1+r)^t}
PV: 現在価値(今の株価)
CF: 将来のキャッシュフロー(未来の稼ぎ)
r: 割引率(リスクの大きさ / 金利)
t: 年数

エンジニア的に翻訳すると、DCFモデルは以下のような定義の 「関数」 です。

  • Input(入力データ):
    • 今後5〜10年の事業計画(売上、コスト、設備投資など)の配列データ
    • 割引率等のリスク関連のグローバル変数
  • Process(処理):
    • 配列データをループ処理し、年数ごとのリスク係数で割り算(デクリメント)して総和(Sum)をとる
  • Output(戻り値):
    • 「企業価値(Enterprise Value)」 という単一の数値

投資銀行マンは、この「Input(事業計画)」のパラメータを微調整したり、「Risk(割引率)」の設定を議論したりしながら、妥当な「Output(株価)」を探るために、巨大なExcelファイルを叩いているわけです。

DCFモデルとプログラミングの共通点

1. 「Assumptionシート」は、ハードコーディングの排除

DCFモデルには「Assumptionシート」という、モデルの前提条件を纏めたシートが用意されてます。そして、計算式を作成する際には、数値を直接入れるのではなく、そのセルにある値を参照するようにします。

例えば、n期の売上(A1にある値)からn+1期の売上を計算するセルでは、

= A1 * 1.05

でははなく、

= A1 * Assumption!A1

のように記述します。

これはプログラミングにおける、 ハードコーディングの排除とconstants定義と同じです。

const GROWTH_RATE = 1.05

def calc_projection_sales(current_sales):
    return current_sales * GROWTH_RATE

上記のコードのように変数を定義して、ロジック内に値をハードコーディングをしないようにするという、プログラミングの鉄則と同じになります。

また、DCFモデルには文字の色に関するルールもあります。

  • 黒色:関数で計算した結果
  • 青色:ベタ打ちした数値
  • 緑色:別シートからのリンク

このルールは、投資銀行マンがデバックをする際に用いる、シンタックスハイライトの役目を果たしていると言えます。

2. 「シート分け」は、オブジェクト指向のクラス設計そのもの

投資銀行のDCFモデルは、決して一枚の巨大なシートで作られているわけではありません。「前提条件(Assumptions)」「損益計算書(P/L)」「貸借対照表(B/S)」「キャッシュフロー計算書(C/F)」と、機能ごとにシートが明確に分かれています。

これはプログラミングにおける 「モジュール分割」や「クラス設計」 と似ています。

良いモデルの条件は、一つのシートが「一つの役割」に集中していることです。これは、エンジニアリングにおける 「単一責任の原則(Single Responsibility Principle)」 と同じです。

  • Assumptionシート: 定数の管理だけを行う。計算はしない
  • P/Lシート: 利益の計算だけを行う。現預金の推移(B/S)は管理しない
  • B/Sシート: 資産・負債のストックだけを管理する

もし、これらを一枚のシートに混ぜて書けば、それはエンジニア用語で言う 「スパゲッティコード(Spaghetti Code)」 です。どこで何が計算されているか追えず、修正すると別の場所が壊れます。シートを分けることで、 「関心の分離(Separation of Concerns)」 を実践し、保守性の高いアーキテクチャを構築できます。

そして、シート間のリンク(P/Lの当期純利益をC/Fの最上段に埋め込む)はクラス間の 「パブリックメソッド」や「APIコール」 にあたります。①で述べた「別シートの参照は緑色にする」というルールは、「ここが他のクラスとのインタフェースです」と明示するための、APIドキュメントのような役割を果たしています。

3. 「反復計算」は、高度な数値計算ライブラリのimport

DCFモデルで避けて通れないのが 「循環参照(Circular Reference)」問題です。特に、LBOモデルなどを組むと、必ずこの論点にぶつかります。

  1. 支払利息を計算したい → 借入金の平均残高が必要
  2. 借入金の期末残高を知りたい → 返済原資となるキャッシュフローが必要
  3. キャッシュフローを知りたい → 当期純利益が必要
  4. 当期純利益を知りたい → 費用である支払利息が必要
  5. 1に戻る(無限ループ)...

Excelでこれを行うと「循環参照エラー」が出ますが、オプションで 「反復計算(Iterative Calculation)」 をオンにするとエラーが消え、計算が完了します。

この「チェックボックスをオンにする」という行為は、プログラミングで言えば 「数値解析ライブラリを import して、最適化アルゴリズムを実行する」 のと同じです。自分でゼロからループ処理を書くのではなく、Excelという巨大なミドルウェアに搭載された 「ソルバー(Solver)」 に計算を丸投げしているのです。

# 自分でループを書くのではなく、既存の強力なライブラリを使う
from scipy.optimize import fixed_point

# 循環するビジネスロジックを定義
def dcf_logic(interest):
    net_income = ebit - interest
    cash_flow = net_income + d_and_a
    debt_balance = initial_debt - cash_flow
    new_interest = (initial_debt + debt_balance) / 2 * interest_rate
    return new_interest

# ライブラリに計算を任せる(反復計算の実行)
result = fixed_point(dcf_logic, x0=1000, xtol=0.001, maxiter=100)

Excelのオプション設定にある「最大反復回数:100回」「変化の最大値:0.001」という数値。 これは、機械学習やアルゴリズム実装における 「ハイパーパラメータ(Hyperparameter)」のチューニングそのものです。

  • 回数が少なすぎると、収束する前に計算が止まってしまう(Underfitting)。
  • 閾値(変化の最大値)が厳しすぎると、いつまでも計算が終わらない(Performance Issue)。

バンカーは、裏側で動いている「ニュートン法」や「不動点反復法」といった数学的アルゴリズムの詳細は知らなくとも、「適切なパラメータを設定して、ブラックボックス化されたライブラリから正しい解を得る」 という、極めて現代的なエンジニアリングを行っていたわけです。

4.「行末のCheck」は、常時稼働するユニットテスト

DCFモデルを組み上げた後に必須になるのは、「バランスチェック」です。B/Sはバランスしているか、キャッシュの増減がC/Fと一致してるか等、複式簿記の制約をクリアしているかをCheckセルを作成することで確認しています。

=IF(Total Assets - (Total Liabilities + Equity) = 0, "OK", "ERROR")

例えば、前提が変更になったり、モデルに修正を加えた際には、必ずこのCheckセルでバランスチェックをしており、OKになるまでモデルを修正することが求められます。

これは常時稼働する 「ユニットテスト(Unit Test)」 であり、Checkセルは 「CI(Continuous Integration)パイプライン」 として機能していると言えます。

コードをデプロイする前に自動テストが走り、バグがないかを検証する、という現代的なエンジニアリングを、DCFモデルではCheckセルを使って実現していたのです。

ツールは異なるが、やっていることは「論理構築」

上記のように、DCFモデリングとプログラミングはツールが異なるだけで、やっていることは「論理構築」です。巨大な財務モデルを、他人に見やすく(可読性)、変更に強く(保守性)、ミスなく動く(堅牢性)ように設計する能力。これはそのままエンジニアリングの資産になります。

もし、今キャリアチェンジを迷っている金融パーソンがいるなら、自信を持って伝えたいです。あなたはすでに、Excelという言語を使ってプログラミングをしています。

一つだけ異なるのは、エンジニアにはGit という強力なバージョン管理ツールがあるということです。xxxx_vf_20251217_final_fujii(2).xlsxという地獄のファイル管理から解放される喜びだけで、エンジニアになる価値は十分にあります!

最後に

プログラミングの世界では、AIによる業務効率化が急速に進んでおり、claude code等のAIコーディングエージェントで業務を進めることがかなり多くなっていると思います。

情報管理等の観点からIBD業務へのAI導入は遅れてはいますが、以下のようにAIによる業務効率化が急速に進んでいくことが予想されます。

そこで、IBD業務のドメイン知識を持ちながら、エンジニアリングスキルもあれば市場で重宝される人材になること間違いなしです!もし、金融パーソンでエンジニアへのキャリアチェンジに興味がある!という方がいたら、是非お声がけいただければ嬉しいです!

Finatext Tech Blog

Discussion