ストックドッグ

KatoTakahiro。金融系の会社で働くSEが株やPython、その他諸々について書いています。サービスも運営してます→http://fmbrain.work

個別株と市場のボラティリティの関係性を示すβをPythonで計算する

βとは

βは、CAPMというポートフォリオ理論に出てくる概念であり、個別株と市場のボラティリティの関係性を示します。

日本経済新聞のサイトでは、銘柄のβランキングが公表されています。

www.nikkei.com



個別株とは、TOYOTAであったりNTTデータであったり、ひとつひとつの会社のことです。

市場とは、株式市場全体のことです。日本では、TOPIX = 市場 として扱われることが多いと思います。


βは高ければ、高いほど市場より高いボラティリティがあり、低ければ低いほど市場より低いボラティリティということになります。

ボラティリティ = リスク であるため、言い換えるとβが高い株は、リスクの高い株、ということにもなります。

β = 1.0 : 株式が市場と同じボラティリティ
β = 2.0 : 株式が市場より高いボラティリティ
β = 0.5 : 株式が市場より低いボラティリティ


TOYOTAとさくらネットの株価の日々のリターンをビジュアル化してみます。



それぞれのβは以下になります。

銘柄名 β
さくらネット(3778) 1.54
TOYOTA(7203) 1.02

βがさくらネットのほうが高く、ボラティリティが高いことがわかると思います。

言うても、0.5ほどしか差がないので、微妙な差ですが....


βの求め方

β = 個別株と市場ポートフォリオの相関 × 個別株の標準偏差 / 市場ポートフォリオの標準偏差		

この式が何をしているかと言うと...

個別株の値動きのうち、市場と連動している部分のみをβとしています。


個別株の値動きは、大きく2つにわけることができます。

1つは、市場の動き。もう1つは、個別株特有の動きです。

TOPIXが上昇すれば、個別株もそれに応じて上昇します。

これが市場の動きです。


逆に個別株特有の動きとは、決算の結果が良かったや、粉飾決算がバレた、などです。

これらのイベントによって個別株は、特有の値動きをするので、この値動きは市場の動きとは別です。


市場の動きと個別株特有の動きが合わさって、個別株の値動きになります。

個別株の値動きの中から個別株特有の動きを控除したものを、個別株のβとしているのです。

どうやって個別株特有の動きを控除するかと言うと、個別株と市場の相関係数を使います。

個別株と市場ポートフォリオの相関 × 個別株の標準偏差


個別株と市場の値動きの相関係数が0.7だった場合は、0.7は市場の動き、残りの0.3は個別株特有の動きであると。

そういった解釈になります。


個別株の標準偏差に市場との相関係数を乗算することで、市場と連動している部分のみ、を抜き取っています。


Pythonで実装する

株価を取得するプログラミングは、現代ポートフォリオ理論をPythonで実装したときと同じものを利用しるので割愛します。

www.stockdog.work



βの計算対象は、さくらネット(3778)にします。

市場は、TOPIX(998405)にしています。

とりあえず、pandasのDataFrameでさくらネットとTOPIXを統合したものを作成します。

Close_998405  Close_3778
1800.44         850
1783.49         852
1778.87         843
1744.01         811
1761.71         816
1763.76         817
1759.65         823
1771.13         831
1777.08         839
1780.56         820
1776.73         831
1772.07         816
1786.15         820
1792.08         833
1792.66         854


上記のデータが master_df に入っています。


returns_daily = master_df.pct_change()

# β = 証券iと市場ポートフォリオの相関 × 証券i の標準偏差 / 市場ポートフォリオの標準偏差			
tmp_df = returns_daily.loc[:, ["Close_998405", "Close_3778"]]

# 相関係数を計算
corr = tmp_df.corr().iloc[0, 1]

# それぞれの標準偏差を計算
std_i = returns_daily["Close_3778"].std()
std_m = returns_daily["Close_998405"].std()

# βの計算
beta = std_i * corr / std_m
# print("beta : ", beta)

プログラミング全体は、gitlabにおいています。

gitlab.com


上のコードでは、愚直にpandasで式を再現しています。

scipyの単回帰でもβを求めることができますし、こっちのほうがコードが短くてスマートです。

tmp_df = returns_daily.loc[:, ["Close_998405", "Close_3774"]]
x = [i[0] for i in tmp_df.iloc[:, [0]].values]
y = [i[0] for i in tmp_df.iloc[:, [1]].values]

slope, intercept, r_value, p_value, std_err = stats.linregress(x[1:len(x)], y[1:len(y)])
print("β : ", slope)


計算の結果は、どちらも以下になります。

β :  1.54465802366


計算期間は、2017/11/04 ~ 2018/07/12にしています。

まとめ

特になし!

以上おわり!