単回帰分析による株価分析

はじめに

何となく、株価の予想をしてみたいと思いました。機械学習の種類についての勉強の記事で調べた通り、株価などの予想には回帰分析が有効であるとのことなので、今回は回帰分析の中で一番単純な単回帰分析について勉強しました。
実装に使用した言語はpytohn3です。

回帰分析とは

参考にしたサイトでは回帰分析について、次のような説明がされていました。
回帰分析とは、説明変数 $x$によって目的変数$y$の変動を $y=f(x)$の形でどの程度説明できるかを分析する手法です。 この回帰分析を行う目的としては、

①数値の予測(xの値からyの値を予測する)
②要因分析(yに影響を与えているxを探し、その影響量を測る)
が挙げられる。
例えば、気象データ(説明変数x)とソフトクリームの販売量(目的変数y)がどのような関係になっているかを調べることで、予測を行うものです。
①、②の具体例については引用元のサイトを見ていただけると分かりやすいです。
また、$y=f(x)$の式のことを回帰方程式や回帰式と呼ぶみたいです。

そして、回帰分析の中で、説明変数xが1つだけの回帰式のことを単回帰分析といいます。代表的なものとしては$y=ax+b$という1次関数があります。この$y=ax+b$という式を求める方法の一つに最小二乗法というものがあります。今回はこの最小二乗法について説明します。

最小二乗法

最小二乗法の考え方としては単回帰分析・最小二乗法の公式はどうすれば求められるのか。統計上の誤差と残差の違いの説明が分かりやすかったので、詳しく知りたい方は参考にしてください。

簡単に株の例で説明すると、最小二乗法を使うことで、株価チャートの中に最もらしいy=ax+bの関数を見つけることが出来ます。このy=ax+bがわかることで、株価のトレンドが分かるのではないかと考えています。図1にイメージを示します。
図1:株価チャートとy=ax+bのイメージ
図1の場合は上昇トレンドであることを示します。
(図1のy=ax+bは手書きのため、適当です)

傾き(aの値)がプラスだと、上昇トレンド、マイナスだと下降トレンド、0に近いと横ばいであることが分かります。また、傾きが分かることで、現在のトレンドの大きさについても定量的に評価することが出来ます。

株価データの準備

今回はquandlで提供されている日経平均株価を使います。このquandlですが、一日に利用できる回数に制限があるみたいなので、株価データを取得したらcsvなどに出力した方がいいかもしれないです。
~(補足)~
quandlに登録することで、この制限が解除されるみたいです。

また、quandlは別途インストールする必要があるので、コマンドライン上でpipを使ってインストールしてください。

>pip install Quandl




quandlの準備が出来たところで、実際に日経平均株価を取得し、中身の確認をしてみましょう。
import quandl
data = quandl.get("NIKKEI/INDEX")#日経平均株価の取得
print(data)
中身を見てみると次のようになりました。
1950年から現在の株価までがあります。しかし、古いデータは一部NaNになっています。
とりあえず、終値はすべて載っていたので、終値だけで株価グラフを作成します。
import quandl
import pandas as pd
import matplotlib.pyplot as plt
import seaborn


data = quandl.get("NIKKEI/INDEX")#日経平均株価の取得
data_date = pd.to_datetime(data["Date"])#日付データが文字列だったので変換

data_close = data["Close Price"]#終値の取得
plt.plot( data_date,data_close)
plt.xlabel("Year")
plt.ylabel("Yen")
plt.show()
図2:日経平均株価の終値(1950~2018年)
今回はこのデータを元に単回帰分析を行ってみます。

株価データを用いて単回帰分析

最小二乗法

まず初めに、最小二乗法を使って単回帰分析をやってみます。
最小二乗法にはscipyの中にあるcurve_fit関数を使います。使い方は以下の通りです。
from scipy.optimize import curve_fit
def func_liner(x,a,b):
    return a*x+b #ここに最小二乗法でフィッティングする関数を記述
param,cov = curve_fit(func_liner, x, y)
curvefitの返り値はaとbの値が入っているparamと、共分散が入っているcovがあります。
今回はparamのみ使います。実際に株価と最小二乗法で求めた直線をプロットしてみます。コードは以下の通りです。
import quandl
import pandas as pd
import matplotlib.pyplot as plt
import seaborn
from scipy.optimize import curve_fit
def func_liner(x,a,b):
    return a*x+b #ここに最小二乗法でフィッティングする関数を記述
data = quandl.get("NIKKEI/INDEX")#日経平均株価の取得
data_date = pd.to_datetime(data["Date"])
data_close = data["Close Price"]
data_num = range(0,16997)#最小二乗法で使うx軸の値(data_closeの要素数と一致)
param,cov = curve_fit(func_liner, data_num, data_close)#最小二乗法によるフィッティング
fitting = param[0]*data_num+param[1]#求めたa、bの値を元にy=ax+bの直線を作成
plt.plot(data_date,data_close,label="NIKKEI")
plt.plot(data_date,fitting,label="fitting",lw=5)
plt.legend()
plt.xlabel("Year")
plt.ylabel("Yen")
plt.show()
図3:日経平均株価と最小二乗法で求めた直線
図3の青線が日経平均株価で、緑色の線が最小二乗法で求めた直線です。
ちなみにこの時のaは1.2256746、bは-761.22523731でした。この結果より、1950年から2018年まで、上昇トレンドであることが分かります。ただ、1990年付近の値が求めた直線と大きく乖離していることから分かる通り、短期的な予測には向いていません。

Scikit-learnのLinerRegression

Scikit-learn内にあるLinerRegressionを使うことで単回帰分析を行うことが出来ます。
sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False,copy_X=True, n_jobs=1)

fit_intercept切片を求める計算を行うかどうか
目的変数が原点を通る場合にはFalseとする
normalize説明変数を事前に正規化するかどうか
copy_Xメモリ内でデータを複製するかどうか
n_jobs計算に使うジョブの数(-1ですべてのCPUを使用)
ここで一つ注意しなければいけないのは、LinerRefressionに用いるデータはdataframe型にする必要があります。実際にLinerRegressionを用いて回帰分析したコードを下に示します。
import pandas_datareader.data as web
import quandl
import pandas as pd
import matplotlib.pyplot as plt
import seaborn
from sklearn import linear_model

data = quandl.get("NIKKEI/INDEX")
data_date = pd.to_datetime(data["Date"])
data_num_df = pd.DataFrame(list(range(0,16997)))#data_closeと同じデータ数をdataframe型で用意
# data_close = data["Close Price"]#こっちはseriesシリーズ
data_close_df = data[["Close Price"]]#これでdataframe型となる

model = linear_model.LinearRegression()#モデルを作成
model.fit(data_num_df, data_close_df)#学習
py = model.predict(data_num_df)

plt.plot(data_date,data_close,label="NIKKEI")
plt.plot(data_date,py,label="LinearRegression",lw=5)
plt.legend()
plt.xlabel("Year")
plt.ylabel("Yen")
plt.show()
図4:日経平均株価とLinerRegressionで求めた直線
図3と図4を比較すると似た結果が出ていることが分かります。
LinerRegressionでは次のようにすることで傾きなどが分かります。

print(model.coef_)#編回帰係数(傾き)
print(model.intercept_)#切片
print(model.score(data_num_df,data_close_df))#決定係数
今回は傾きは1.22567466、切片は-761.22590783となりました。
傾きについては先ほどの値と一致していますが、切片は若干異なるものとなりました(気にするほどの違いではないですが)。また、決定係数は0.5124441166033344となりました。この決定係数は予測した直線と元のデータがどのくらい一致しているかを表しているものみたいで、1に近いほどいいみたいです。

まとめ

今回は日経平均株価を最小二乗法とScikit-learn内にあるLinerRegressionを用いて単回帰分析を行いました。とりあえず、株価のトレンドが分かるようになったので、今後はもう少し詳しく株価の分析を行ってみたいと思います。

0 件のコメント :

コメントを投稿