重線形回帰やってみた

今回は、携帯電話関連会社であるKDDI、ソフトバンク、楽天の株価でNTTの株価を推定する重線形回帰をやってみた。

株価の繊維をグラフで表示すると上記の通りになるので、KDDIとNTTとの関係に比べると、あまり意味のない結果になるかなと思ったのですが、意外とそんな結果にはなりませんでした。

ライブラリのインポート

In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
import seaborn as sns
sns.set()

データの読み込み

In [2]:
data = pd.read_csv('mibile_company_stock_price_2020-10-01_2021-09-30.csv')
In [3]:
data.head()
Out[3]:
date NTT KDDI softbank rakuten
0 2019-10-01 2590.5 2839 1471 1093
1 2019-10-02 2633.5 2924 1500 1041
2 2019-10-03 2624.5 2918 1494 1019
3 2019-10-04 2617.5 2942 1496 1023
4 2019-10-07 2642.0 2939 1496 1036
In [4]:
data.describe()
Out[4]:
NTT KDDI softbank rakuten
count 485.000000 485.000000 485.000000 485.000000
mean 2679.663918 3240.731959 1413.777320 1068.929897
std 223.262123 243.764303 85.015676 159.731409
min 2150.000000 2655.000000 1178.000000 672.000000
25% 2511.000000 3096.000000 1372.000000 949.000000
50% 2720.000000 3244.000000 1431.000000 1030.000000
75% 2835.000000 3391.000000 1471.000000 1183.000000
max 3285.000000 3897.000000 1615.000000 1545.000000

回帰の作成

従属変数と独立変数の宣言

In [6]:
y = data['NTT']
x1 = data[['KDDI','softbank','rakuten']]

回帰

In [7]:
x = sm.add_constant(x1)
results = sm.OLS(y,x).fit()
results.summary()
Out[7]:
OLS Regression Results
Dep. Variable: NTT R-squared: 0.802
Model: OLS Adj. R-squared: 0.800
Method: Least Squares F-statistic: 647.7
Date: Tue, 19 Oct 2021 Prob (F-statistic): 1.84e-168
Time: 01:07:48 Log-Likelihood: -2918.5
No. Observations: 485 AIC: 5845.
Df Residuals: 481 BIC: 5862.
Df Model: 3
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const -588.0258 81.664 -7.201 0.000 -748.487 -427.564
KDDI 0.4863 0.029 16.648 0.000 0.429 0.544
softbank 1.0179 0.077 13.267 0.000 0.867 1.169
rakuten 0.2364 0.034 7.023 0.000 0.170 0.303
Omnibus: 2.426 Durbin-Watson: 0.113
Prob(Omnibus): 0.297 Jarque-Bera (JB): 2.508
Skew: -0.160 Prob(JB): 0.285
Kurtosis: 2.854 Cond. No. 6.68e+04

表の見方

1番目の表
Adj. R-squared: 自由度修正済み決定係数、重回帰分析のように複数の独立変数がある場合にペナルティが与えられるようにR-squaredが計算される。この値が1に近づけば誤差は小さくなっているので、モデルが改善されていると判断できる。前回の単回帰の時の結果が0.727だったので、結果がよくなっていることになる。
F-statistic: F値、大きい方が良い。単回帰分析のF値は1288だったので、単回帰分析の結果の方が優位であると言えるらしい
Prob (F-statistic): F検定のP値、一般的には0.05以下であれば良い。今回もOK
2番目の表
P>|t|
: t検定のP値、前回も説明した通り、一般的には0.05以下であれば意味がある独立変数。ということで、ソフトバンクも楽天もある程度意味があるらしい。

ということで、意外と追加してもパフォーマンスは上がったようです。

ということで、念のため、回帰した結果を用いて、単回帰と重回帰をグラフ表示してみると以下の通り。確かに良くなってそう。

In [22]:
data["single NTT"] = 148.3029 + 0.7811 * data['KDDI']
data["multi NTT"] = -588.0258 + 0.4863 * data['KDDI'] + 1.0179 * data['softbank'] + 0.2364 * data['rakuten']
plt.plot(data["date"],data[["NTT","single NTT","multi NTT"]], label=["NTT","Calculated by KDDI",u"Calculated by KDDI, Softbank, Rakuten"])
#yhat = x1*0.7811+148.3029
#fig = plt.plot(x1,yhat, lw=4, c='orange', label ='regression line')
plt.xlabel('date', fontsize = 20)
plt.legend()
plt.xticks([])
plt.show()

ただ、線形回帰を利用する上での注意点がいくつかあるらしく、そもそも、時系列のデータには使ってはいけないらいい。以下が線形回帰を利用する条件
1, 自己相関がないこと。
時系列データの場合は、週や月など周期性が見られるため、自己相関がないとは言いにくい。
Durbin-Watson: この値は0から4の値を取るが、1以下、または3以上だと自己相関がある可能性が高い
ということで、株価は自己相関があるので、線形回帰は利用できない。実際に上の結果の3番目の表を見るとこの値は0.113になっている。
2, 多重共線性が無いこと。
これは、独立変数間に関連性がないことを意味します。株価の場合は、銘柄間に全く関連性がないことを示すのは難しいですが、銘柄間の相関を調べることによってある程度調べられますね。こちらは、この後で図示してみてます。
3, 線形性が無いこと。
これは独立変数と従属変数の間に線形性がない場合ですね。株価の場合は、ありそうなので、そこは問題ないかと
4, 内成性が無いこと。
独立変数と残差に関係が無いこと。必要な独立変数を除いてしてしまった場合にこれが発生する

結果だけ見るとこの回帰から大幅に外れたら買ってみるとかしてもそんなに悪くなさそうなんだけどなー。

おまけ 独立変数(株価)間の相関

In [30]:
data_corr = data[["KDDI","softbank","rakuten"]].corr()
sns.heatmap(data_corr, vmax=1, vmin=-1, center=0)
Out[30]:
<AxesSubplot:>
In [31]:
data_corr
Out[31]:
KDDI softbank rakuten
KDDI 1.000000 0.655577 0.400873
softbank 0.655577 1.000000 -0.007409
rakuten 0.400873 -0.007409 1.000000

この通り、ソフトバンクと楽天の間の株価の相関は低いが、それ以外はそれなりに相関がありそう。

Follow me!