若葉の技術メモ

コンピュータやプログラミングに関して調べたり、取り組んだりしたことをまとめる若葉のノート📓。コンピュータ・プログラミング初めてって方も一緒に勉強していきましょう!初心は大事!いつでも若葉☘のような意気込みで!

  • No.   

若葉の技術メモ

コンピュータやプログラミング・数理に関して調べたり、取り組んだりしたことをまとめる若葉のノート。

コンピュータ・プログラミング・数理が初めてって方も一緒に勉強していきましょう!

初心は大事!いつでも若葉☘のような意気込みで!

【株価のデータ解析を考えている方必見!】相関係数の信じられない罠:見せかけの相関

全く無関係なものの間に関係性が見えてしまう

こんなこと絶対にないと思いますよね?

無関係であればその関係性が見えるはずがないと思いますよね?

ですが、驚くことに...

実際のデータ解析においてはこの信じられないことが起こってしまうのです。

今回の記事では株価のデータ解析の際に注意しないと騙される見せかけの相関についてご紹介いたします!


相関係数とは

相関とは2つの変量(確率変数)が従う分布の間の関係性を表し、相関係数とは特にその関係性の中でも線形な関係性をの強さを表す指標です。

まずは簡単な確率論の復習。

準備(平均・分散・共分散)
  • 2つの確率変数 X, Y(X社の株価とY社の株価に相当)

  •  X,Yの分布を p_X, p_Y

  •  X,Yが同時に起こる分布、同時分布 p_{X,Y}

このとき、平均・分散・共分散は次のように定義されます。

  • 平均

    •  \mu_X  = \int xp_X(x) dx

    •  \mu_Y = \int yp_Y(y) dy

  • 分散

    •  \sigma_X^{2} = \int (x-\mu_X)^{2} p_X(x) dx

    •  \sigma_Y^{2} = \int (y-\mu_Y)^{2} p_Y(y) dy

  • 共分散 X, Yの関係性の1つの指標)

    •  {\rm cov}(X,Y) = \int \int (x-\mu_X)(y-\mu_Y) p_{X,Y}(x,y)dxdy
相関係数

以上の設定のもとで、2つの確率変数 X,Yの間の相関係数は分散共分散を以て、


\rho(X,Y) = \frac{{\rm cov}(X,Y)}{\sigma_X \sigma_Y}

と定義されます。

つまり、「2つの確率変数が同時にどれくらいそれぞれの平均からブレるのか(これを偏差いいます)」を「それぞれの確率変数が個別にどれくらい平均からブレるのか」で規格化している指標です!

相関係数の性質

相関係数の簡単な性質をご紹介しておきます

  1. 相関係数は−1〜1の範囲

  2.  X, Yが独立(  \Leftrightarrow p_{X,Y} (x,y)=p_X (x)p_Y (y))ならば相関係数は0

  3. 相関係数が±1となるのは X, Yの偏差に線形な関係がある場合に限る

  4. 相関係数が0よりも

    • 大きいとき→ X,Yは同じような動き

       Xが平均よりも大きい(小さい)値を取ると Yも平均よりも大きい(小さい)値を取りやすい

    • 小さいとき→ X,Yは逆の動き

       Xが平均よりも大きい(小さい)値を取ると Yも平均よりも小さい(大きい)値を取りやすい

つまり、これらの性質から2つの変量の線形な関係性を調べたければ、相関係数が0よりも有意に大きいか0よりも有意に小さいかを調べればOKということになります。

経済データにおける相関係数

というわけで、早速2つの株価の間の相関係数を測ってみましょう!

今回もPythonさんを使っていきます

環境
  • Python 3.7.0

  • scipy >= 1.1.0

  • pandas >= 0.23.4

  • pandas-datareader >= 0.7.0

  • matplotlib >= 2.2.3

pandas-datareaderに関しては

wakaba-mafin.hatenablog.com

で執筆しています!

アマゾンとアップルの株価の相関係数

まずはライブラリをインポートしましょう

# ライブラリのインポート
import scipy as sp
import pandas_datareader.data as web
from datetime import datetime
import matplotlib.pyplot as plt

次にpandas-datareaderを使って過去5年間における一日の終値のデータをダウンロード

df_x = web.DataReader(
    'AMZN', 'iex',
    datetime(2014, 11, 18),
    datetime(2018, 11, 18)
)

df_y = web.DataReader(
    'AAPL', 'iex',
    datetime(2014, 11, 18),
    datetime(2018, 11, 18)
)
time = df_x.index.values
x = df_x["close"].values # アマゾンの株価
y = df_y["close"].values # アップルの株価

一度、プロット。

# 時系列
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
axd = ax.twinx()
ax.plot(x, "r-", label="AMZN")
axd.plot(y, "b-", label="AAPL")
ax.legend(loc="upper left")
axd.legend(loc="lower right")
ax.set_xticks(sp.arange(0,len(time),200))
ax.set_xticklabels(time[::200], rotation=45)
plt.show()
# 同時の株価
plt.scatter(x, y, c="k", alpha=0.25)
plt.xlabel("AMZN")
plt.ylabel("AAPL")
plt.show()

f:id:wakaba-mafin:20181118203251j:plain

f:id:wakaba-mafin:20181118203423j:plain

これを見る限り、かなり強い関係性がありそうですね!ではでは、相関係数の計算。 相関係数はscipyのstatsに入っているpearsonrを使えば計算できます!

from scipy.stats import pearsonr
rho, p = pearsonr(x,y)
print("correlation=", rho, ", p-value=", p)
correlation= 0.909645694490647 , p-value= 0.0

これはすごい!アマゾンとアップルの間では、p値(これがある基準(0.05や0.01などが一般的)よりも小さければ相関係数が0である仮説が棄却される)が0.0(!?)相関係数0.9を超えてますね!

なるほど。これは、ハイリスク・ハイリターンを追求するのであれば、ポートフォリオにアマゾンとアップルを組み入れるのがよいということを表しています!

アマゾンとアップルの収益率の相関係数

では次に中期的な投資を考えて、アマゾンとアップルのそれぞれの120営業日間(約半年)の収益率についても相関係数を計算しましょう!

約半年間における収益率(半年で何%変化するのか)は

x_return = (x[120:]-x[:-120])/x[:-120] # アマゾン株の半年収益率
y_return = (y[120:]-y[:-120])/y[:-120] # アップル株の半年収益率

で計算できます。これで120営業日前と比較してアマゾン・アップルそれぞれの株価が何%変化したのかがわかるようになります。プロットするとこんな感じ。

# 時系列
plt.plot(x_return, "r-", label="AMZN(return)")
plt.plot(y_return, "b-", label="AAPL(return)")
plt.legend()
plt.gca().set_xticks(sp.arange(0,len(time),200))
plt.gca().set_xticklabels(time[120::200], rotation=45)
plt.show()

f:id:wakaba-mafin:20181118203326j:plain

あれ?何か嫌な予感。同じように半年収益率の相関係数

rho_return, p_return = pearsonr(x_return, y_return)
print("correlation=", rho_return, ", p-value=", p_return)
correlation= -0.0539232639034853 , p-value= 0.10832180228035448

あれれー?株価自体には相関があったはずなのに...半年間のリターンで考えると、相関が有意ではなくなってしまいました...

せっかく、アマゾンとアップルを組み入れたポートフォリオでハイリスク・ハイリターンの投資ができると思ったのに...

一体なんでなんでしょう?

見せかけの相関

というわけでアマゾンとアップルの株価の間には相関関係があったのに、収益率で考えると相関が有意ではなくなってしまうという一見摩訶不思議な事実について考えていきましょう!

実はというと、この問題は「見せかけの相関(spurious regression)」という問題で、

Granger`Newbold, "SPURIOUS REGRESSIONS IN ECONOMETRICS," Journal of Econometrics, 1974

でシミュレーションによって見つかった問題です。 そして、理論的には

Phillips, "UNDERSTANDING SPURIOUS REGRESSIONS IN ECONOMETRICS," Journal of Econometrics, 1986

において示されました。

歴史的にはかなり古くに見つかった問題なのです。

単位根過程

見せかけの相関がなぜ生じるのかを考えてみましょう。

まず、ARモデルを導入します。ARモデルとはいわゆる線形の時間発展方程式で


x_t = \sum _{i=1}^{T}  a_i x_{t-i} + \epsilon _t

 \epsilon_tは自己相関がなく、平均0、分散 \sigma^{2}ガウス雑音)で表されるモデルです。 つまり、過去のデータをある重みで足し合わせたところにノイズが加わって次の時刻の値が決まるようなモデルです。

このようなモデルで特性方程式と呼ばれる方程式


\xi^{T} - \sum _{i=1}^{T}  a_i \xi ^{T-i}  = 0

 \xi=1を解に持つときにこのARモデルは単位根過程であるといいます。

この単位根の存在は過去から現在までの推移で何かしら全く変化しないものが存在することを意味しており、このような単位根過程では次のような性質が成り立ちます:

  1. 単位根過程に与えた影響が今後永久に残る

  2. 単位根過程は t\rightarrow \inftyで発散するような分散を持つ

  3. 単位根過程では、 x_tは非定常(平均もしくは自己共分散が時間に依存する)だが、差分 \Delta x_t := x_t - x_{t-1}は定常(平均・自己共分散が時間によらず一定)

があります。そして、特に2つの単位根過程があったときに、その2つの間には見せかけの相関が生じることが知られています

つまり、株価の時系列が単位根過程になっている可能性があるから、見せかけの相関が発生したということです!

2つの単位根過程の間の相関

というわけで、実際に簡単なモデルで見せかけの相関が発生することを確認しましょう!

最も簡単な単位根過程はランダムウォークです。それは


x_t = x_{t-1} + \epsilon_t

 \epsilon_tは自己相関がなく、平均0、分散 \sigma^{2}ガウス雑音)で表されます。

ここでは2本の無相関のランダムウォーク


x_t = x_{t-1} + \epsilon_t^{x}


y_t = y_{t-1} + \epsilon_t^{y}

 \epsilon_t^{x}, \epsilon_t^{y}は自己相関がなく、平均0、分散1の独立なガウス雑音)を考えて、この2つの間の相関をPythonで見てみましょう。

# ライブラリのインポート
import scipy as sp
from scipy.stats import pearsonr
import matplotlib.pyplot as plt

2つの独立なランダムウォーク(長さ10000)の発生

x = sp.cumsum(sp.random.randn(10000))
y = sp.cumsum(sp.random.randn(10000))

そして、プロット

plt.plot(x, "r-", label="x")
plt.plot(y, "b-", label="y")
plt.show()

f:id:wakaba-mafin:20181118203503j:plain

2つ独立に発生させたランダムウォークです。そして、この相関係数

rho, p = pearsonr(x, y)
print("correlation=", rho, ", p-value=", p)
correlation= -0.23962765434176556 , p-value= 1.3653880126926588e-130

た、確かに!p値が非常に小さく、有意な相関が出ています。全く独立にさせたはずなのに、有意な相関が出てしまうなんて💦

もう少しサンプルを発生させてみましょう。

num_of_samples = 1000
Xs = [sp.cumsum(sp.random.randn(10000)) for i in range(num_of_samples)]
Ys = [sp.cumsum(sp.random.randn(10000)) for i in range(num_of_samples)]

そして、相関係数とp値を計算

correlations = sp.zeros(num_of_samples)
p_values = sp.zeros(num_of_samples)

for i in range(num_of_samples):
    correlations[i], p_values[i] = pearsonr(Xs[i], Ys[i])

そして、相関係数ヒストグラムを見ると...

fig = plt.figure(figsize=(16,6))
ax = fig.add_subplot(1,2,1)
ax.hist(correlations)
ax.set_xlim(-1, 1)
ax.set_xlabel("correlation")
ax = fig.add_subplot(1,2,2)
ax.hist(p_values, bins=sp.arange(0,1,0.01)) #  0.01ごとのビン
ax.set_xlim(0, 1)
ax.set_xlabel("p-value")
plt.show()

f:id:wakaba-mafin:20181118203530j:plain す、すごい。相関係数はプラスマイナス様々にばらけてはいますが、全く独立なランダムウォークのはずなのに、p値はほとんど0.01を下回っています

これは何も知らない人は騙されますねー💦

見せかけの相関への対処

さて、見せかけの相関が発生するという原因の1つは単位根過程であるということが確認できました。

では、見せかけの相関にはどうやって対応したらいいのでしょうか?

基本的にはまずは単位根が存在するかどうかを検定する手法

単位根検定 - Wikipedia

があるので、それで検定して帰無仮説 H_0「単位根が存在する」を棄却できなければ差分系列(差分系列は定常だから)に対して解析をするというのが一番いいと思います。

ですが、検定するという一手間がかかってしまいますので、それが嫌な方は元の時系列に対しても、差分の時系列に対しても解析をしてみればいいとも思います。

株価などの経済データの場合は株価データの場合では収益率対数収益率などを用いて解析しましょう!

まとめ

今回は株価のデータ解析の際に陥る可能性がある落とし穴、見せかけの相関についてお話しました。

そして、そのような罠にかからないためにも株価などのデータそのものを用いるのではなく、差分などをとって収益率の範疇で考えればある程度問題を回避できるということもお伝えしました!

統計的な手法の背後には仮定がいくつかあり、使用する際には十分に注意を払わないと全く逆の結果が出てきたりするので気をつけましょう!

ここまで読んでいただき、ありがとうございました!

間違いのご指摘やご意見等ございましたら、ぜひコメントのほどよろしくお願いします!