DCF法で企業価値評価を行うツールのプロトタイプをstreamlitで作ってみた

# はじめに
こんにちは（こんばんは、おはようございます）、M&Aクラウドの尾村です。企業価値（バリュエーション）を算出するためのツールをstreamlitというPythonで簡単にwebアプリのプロトタイプが作成できるツールを用いて作ってみました。目的は、完全なる自習用です。コードの意味がわかる（＆私が理解するため）ように、ところどころ解説は入れていますが、正しく知りたい場合、弊社オウンドメディアのM&AtoZの記事や、しっかりした書籍を読んでいただければと思います。弊社の中でも利用されているものではなく、会社とは特に関係ないものだということを強調しておきます。また、こちらのサイトを参考にして、作成されたもので何かしら不都合が生じたとしても、自己責任でお願いします。


この記事を書くにあたって、参考にしたサイトや書籍を参考にさせていただきました。

- [M&AtoZ](https://macloud.jp/media/know-how/17238)
- [streamlit公式ドキュメント](https://docs.streamlit.io/)
- [WACC（加重平均資本コスト）とは　意味や計算手順をわかりやすく解説](https://smbiz.asahi.com/article/14708627)
- [Investment Banking 投資銀行業務の実践ガイド](https://www.amazon.co.jp/Investment-Banking-%E6%8A%95%E8%B3%87%E9%8A%80%E8%A1%8C%E6%A5%AD%E5%8B%99%E3%81%AE%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E3%82%B8%E3%83%A7%E3%82%B7%E3%83%A5%E3%82%A2%E3%83%BB%E3%83%AD%E3%83%BC%E3%82%BC%E3%83%B3%E3%83%90%E3%82%A6%E3%83%A0/dp/4798179779)

# 企業価値評価とは
[wikipedia](https://ja.wikipedia.org/wiki/%E4%BC%81%E6%A5%AD%E4%BE%A1%E5%80%A4)によると、「企業価値とは、企業が持つ有機的一体としての事業の価値を金額で表したものをいう」らしいです。上場企業なら、概ねその企業の時価総額で代替できるのでしょうか？

ただ、世の中の企業ってほとんどは非上場の企業していません。現在日本における上場企業は、４,000社ほどなのに対して、非上場の企業は、[総務省](https://www.stat.go.jp/info/today/pdf/195.pdf)によると、368万社ほどもあるそうなので、その数は0.1%にも満たないということです。

もちろん、上場していないからといって、企業に価値がないわけではないので投資判断やM&Aにおいては何かしらの方法で見積もって上げる必要があります。これまた[wikipedia](https://ja.wikipedia.org/wiki/%E4%BC%81%E6%A5%AD%E4%BE%A1%E5%80%A4)で恐縮ですが、大きくは、「コストアプローチ」、「インカムアプローチ」、「マーケットアプローチ」の3種類の方法があります。その中で今回は、実務でもよく使われるというインカムアプローチのDCF法を使って算出できるように、streamlitでプロトタイプを作ってみました。

# streamlitとは
公式サイトによると、

「A faster way to build and share data apps.
Streamlit lets you turn data scripts into shareable web apps in minutes, not weeks. It’s all Python, open-source, and free」

ということなので、簡単にアプリが作成できて、データと一緒に共有できるオープンソースの無料のツールということです。開発元はsnowflake社に買収されましたので、snowflakeユーザーなら[snowflake上で利用することが可能](https://dev.classmethod.jp/articles/try-streamlit-on-snowflake-from-snowsight/)です。私はsnowflakeユーザーではないので、自作のlocal環境に[dockerを使って準備](https://docs.streamlit.io/knowledge-base/tutorials/deploy/docker)しました。公式サイトの文言にもあるようにデータを共有しやすくするためのアプリで、よく利用されるのが機械学習のモデルを組み込んだアプリのプロトタイピングです。自分でデータや機械学習モデルの確認するだけなら、notebook環境があればOKという方が多いかと思いますが、誰かに共有するときに少し凝った形で、よりイメージしやすくするために利用するのがいいと思います。今回は、特に機械学習とかは出てきません。

# DCF(Discounted Cash Flow)法
私のざっくりした理解を言うと、企業価値を「企業がこの先、生み出す価値（＝FCF:フリーキャッシュフロー）の総和の現在価値」と定義して、算出しようとする手法です。ただし、私が調べた限りで言うといつの時点の数値を用いるか等でいろいろな流儀がありそうなので、ご注意ください。

## 現在価値とは
将来手にいれる100万円と、今手にいれる100万円ではその価値が異なるため（例えば、今手にすれば、銀行に預けることで利子がもらえる等）、将来の価値を現在の価値に換算したものを現在価値と言います。

利率DRで、n年後に手にするV円の現在価値PVは以下の式で表されます。

$$
PV = \frac{V}{(1 + DR)^n}
$$
コードにすると以下のような形になります。

```python
free_cash_flow/(1+discount_rate) ** (n)
```
## 企業価値の算出式
また、将来の生み出すFCFでも、2,3年後は事業計画もあり、一定程度、予測可能ですが、10年後のFCFを正確に算出するのは困難です。そのため、DCF方では、直近のFCF（妥当な算出ができる範囲）では予測値を用いますが、それ以降は継続価値を用います。つまり、企業価値Vは、n年後のFCF(n)と継続価値TVで算出されます。N年後まで予測すると、

$$
V = \sum_{n=1}^{N}\frac{FCC(n)}{(1 + DC)^n} + TV
$$

## 継続価値とは
継続価値は、一定の成長率を仮定した上で、nを無限大まで大きくしたときに生じる現在価値のことです。つまり、N年後以降は永続成長率GR、

$$
TV = \sum_{n=1}^{\infty}FCC(n)(\frac{1+GR}{1 + DC})^n
$$


無限大にまでしたら、発散するのではと思うかもしれませんが、高校数学の無限等比級数を思い出してもらうとわかるかと思いますが、公比が0以上、1以下のときに収束します。初項a,公比rの無限等比級数の和Sは、

$$
S = \frac{a}{(1 - r)} 
$$

で、表せる。今、

$$
a = FCC(N)
$$
$$
r = \frac{1 + GR}{1 + DC} 
$$
なので、

$$
TV = FCC(N)\frac{1 + GR}{DC - GR}
$$
になります。ただし、この式は予測の最終年度N起点での総和なので、現在価値にする場合、もう(1+DC)のN乗で割らないといけません。

見ての通り、現在価値DCの値が小さいと、何倍にも膨れ上がります。また、分子の永続成長率GRは大したことないですが、分母の永続成長率GRは、DCから引かれるため、継続価値、ひいては、企業価値に大きな影響を与えます。また、この値は基本的にはとても大きくなるため、企業価値の大半を継続価値が占めると言うこともあり得ます。あまりに高い場合、算出根拠を見直した方がいいかもしれません。

pythonのコードで表すと下記のような感じです。
```python
def calc_terminal_value(last_year_cash_flow, perpetuality_growth_rate, discount_rate):
    return (last_year_cash_flow * (1 + perpetuality_growth_rate)) / (discount_rate - perpetuality_growth_rate)
```

## WACCの算出
ここまで、利率DCは所与のものとして扱ってきました。しかし、その会社の資金調達がequityで行われているか、debtで行われているかでこの割引率に対する考え方が変わってきます。debtの場合は、実効税率影響後の借入利率RD、実効税率ETRを使えば良いです。したがって、負債コストDCは

$$
DC = RD(1 - ETR)
$$

資本コストは、CAPMと言う理論を使って、以下のように表されます。（次回以降の宿題とさせてください。）資本コストEC(=投資への期待収益率)は、リスクフリーレートRFR、ベータ値、期待収益率ERRを用いて、

$$
EC = RFR + \beta(ERR - RFR)
$$

となります。
pythonコードでは、

```python
def calc_equity_cost(risk_free_rate, beta, expected_rate_of_return):
    return risk_free_rate + beta * (expected_rate_of_return - risk_free_rate)
```

これら、DCとECをそれぞれ、その会社の資本金と、負債で加重平均を取れば良いので、
資本金E,負債Dを用いて、加重平均資本コストWACCは、

$$
WACC = EC\frac{E}{E+D} + DC\frac{D}{E+D}
$$　

となります。
pythonのコード上は、下記のようになります。（実行税率の影響を加味した式になっています。）

```python
def calc_wacc(equity_cost, debt_cost, effective_tax_rate, equity, debt):
    return equity_cost*equity/(equity+debt) + debt_cost*(1.0-effective_tax_rate)*debt/(equity+debt)
```

上記の企業価値の式の割引率をWACCに置き換えれば、算出の部分は完成します。


# streamlitの画面について
サイドバーに、ここまで出てきたパラメータ各種の入力を、また、FCFについては、任意の年数入れられるように、可変的に入力できるようにしました。

値はもちろん、適当です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3091446/23c722ea-1bef-acc3-3d65-e1fc785a684d.png)


最後に全体のサンプルコードを書いておきます。

```python
#参考
#https://docs.streamlit.io/library/get-started

#ライブラリの読み込み
import time
import streamlit as st
import pandas as pd

#タイトル
st.title("DCF法による企業価値評価ツール")
st.markdown("WACCを算出し、永久成長率、フリーキャッシュフローを入力すると、企業価値をDCF(discounted cash flow)法により算出します。")

# 以下をサイドバーに表示
st.sidebar.markdown("### DCF法のパラメータ")

#変数の設定

st.sidebar.markdown("WACCの算出")
risk_free_rate = st.sidebar.number_input("リスクフリーレート(%)", min_value=0.0, max_value=100.0)*0.01
beta = st.sidebar.number_input("ベータ")
expected_rate_of_return = st.sidebar.number_input("期待収益率(%)", min_value=0, max_value=100)*0.01
debt_cost = st.sidebar.number_input("実行税引き前負債コスト(%)", min_value=0, max_value=100)*0.01
effective_tax_rate = st.sidebar.number_input("実行税率(%)",  min_value=0, max_value=100)*0.01
equity = st.sidebar.number_input("株主資本(千円)", min_value=0.01)
debt = st.sidebar.number_input("負債(千円)", min_value=0.00)
perpetuality_growth_rate_text = st.sidebar.selectbox("永久成長率（%）", ("0%", "1%", '2%', '3%', '4%', '5%'))
perpetuality_growth_rate = int(perpetuality_growth_rate_text[0])*0.01

if "list" not in st.session_state:
    st.session_state.list = [0]

st.info("予想フリーキャッシュフロー（千円）を入力し、完了を押してください")

with st.form("form"):
    st_input_area = st.container()
    st_add_button_area = st.container()

    if st_add_button_area.form_submit_button("追加"):
        st.session_state.list.append(0)

    if st_add_button_area.form_submit_button("削除"):
        del st.session_state.list[-1]

    for i in range(len(st.session_state.list)):
        st.session_state.list[i] = st_input_area.number_input(f"{i+1}年目FCF（千円）", step=1, key=i)

    is_calc = st.form_submit_button("完了")

free_cash_flow_list = []
if is_calc:
    sum = 0
    for _value in st.session_state.list:
        sum += _value
        free_cash_flow_list.append(_value)
    st.success(f"FCF合計:{sum}千円")
    
else:
    pass  # DO NOTHING


def calc_terminal_value(last_year_cash_flow, perpetuality_growth_rate, discount_rate):
    return (last_year_cash_flow * (1 + perpetuality_growth_rate)) / (discount_rate - perpetuality_growth_rate)

def calc_corpoeate_value(free_cash_flow_list, discount_rate, perpetuality_growth_rate):
    forecast_term = len(free_cash_flow_list)
    discounted_cash_flow_list = []
    for i, free_cash_flow in enumerate(free_cash_flow_list):
        discounted_cash_flow_list.append(free_cash_flow/ ((1+discount_rate) ** (i+1)))
    last_year_terminal_value = calc_terminal_value(free_cash_flow_list[-1], perpetuality_growth_rate, discount_rate)
    terminal_value = last_year_terminal_value/((1+discount_rate)**forecast_term) #予測最終年基準で算出したため現在まで、価値を戻す必要がある。 
    corporate_value = sum(discounted_cash_flow_list) + terminal_value
    return corporate_value, terminal_value, discounted_cash_flow_list

def calc_equity_cost(risk_free_rate, beta, expected_rate_of_return):
    return risk_free_rate + beta * (expected_rate_of_return - risk_free_rate)

def calc_wacc(equity_cost, debt_cost, effective_tax_rate, equity, debt):
    return equity_cost*equity/(equity+debt) + debt_cost*(1.0-effective_tax_rate)*debt/(equity+debt)

def do_calc():
    free_cash_flow_list = st.session_state.list
    equity_cost = calc_equity_cost(risk_free_rate, beta, expected_rate_of_return)
    wacc = calc_wacc(equity_cost, debt_cost, effective_tax_rate, equity, debt)
    corporate_value, terminal_value, discounted_cash_flow_list = calc_corpoeate_value(free_cash_flow_list, wacc, perpetuality_growth_rate)
    terminal_value_rate = terminal_value/corporate_value
    col_name_list = [f"{el+1}年目" for el in range(len(free_cash_flow_list))]
    df = pd.DataFrame([free_cash_flow_list, discounted_cash_flow_list], columns=col_name_list, index=['FCF（千円）', 'DCF（千円）'])
    #描画
    col1, col2, col3 = st.columns(3)
    col1.metric(label="株主資本コスト", value=f"{equity_cost*100:.2f}%")
    col2.metric(label="負債コスト(実行税率影響後)", value=f"{debt_cost*(1.-effective_tax_rate)*100:.2f}%")
    col3.metric(label="WACC(加重平均資本コスト)", value=f"{wacc*100:.2f}%")
    col1, col2, col3 = st.columns(3)
    col1.metric(label="企業価値", value=f"{corporate_value:.0f}千円")
    col2.metric(label="継続価値", value=f"{terminal_value:.0f}千円")
    col3.metric(label="企業価値における継続価値の割合", value=f"{terminal_value_rate*100:.0f}%")
    st.dataframe(df)

 
if st.button('企業価値の算出', key='main',  help='このボタンをおすと計算が実行されます'):
    do_calc()
```

# 最後に
今回、自らの学習のためにDCF法による企業価値評価ツールを作ってみました。専門用語が多く、最初は苦戦しましたが、慣れてくるとなんとかなりました。本当は感度分析まで、自動で行えるように変数を変えることも考えたのですが、その前に力尽きました。今後、CAPMの理論の部分や企業価値評価のためのマーケットアプローチについても記事にしたいと考えています。繰り返しになりますが、私の勉強のために作成した記事ですので、ご注意ください。