医mportブログ

雑記っき

SARIMAXで株価予測してみた

こんにちは。
株価って一概にグラフ理論だけじゃ未来予測できないだろうな、、と思いつつ敢えて今回は挑戦してみました。




SARIMAXは、パラメータがorder =(p,d,q)、seasonal_order = (P,D,Q,s)があり、pは自己回帰係数、qは移動平均係数(厳密にはどちらも次数)とdは差分の距離です。
数2の数列を思い出しますね、等差数列ってd使ってましたよね。





そして、時系列データは自然要因による季節に特有の変化と、社会的慣習や制度による季節 変化を含んでいます。夏にはエアコンが売れたり、ボーナス時期には売り上げが増えたりすることはよく知られていますね。これらの季節要因を考慮して調整を入れるものを季節調整と言います。P,D,Qは季節調整を入れたp,d,qの値で、sは季節調整の周期を決定する要素です。
p,d,qは0から2、P,D,Qは0か1がいいようです。
だいたい1年ごとに周期があるのでsは12が通常なようです。




自己回帰モデルは時点 t におけるモデル出力が時点 t 以前のモデル出力に依存する確率過程で、移動平均モデルは将来の予測値は過去の予測値と実績値との誤差により決まるとしたときの分析対象予測過程です。これらを組み合わせたのがARMA、季節調整を入れたものがSARIMAXとなります。


数学的な説明は省きましたが、さらに数式から理解したい方はこのサイトを参考にするとよいでしょう。
to-kei.net


今回はstatsmodelsというライブラリを主に用いるのでpip installを済ませておく必要があります。

import pandas as pd
import numpy as np
import io
from statsmodels import api as sm
from datetime import datetime
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.arima_model import ARIMA
import warnings
import itertools

次に、株価のcsvファイルをダウンロードしてきます。
こちらのサイトから引っ張ってきました。
欠損値処理をdropnaでおこないます。
kabuoji3.com

kabu_data = pd.read_csv("csv")
kabu_ = kabu_data.drop(columns = ["date","start","high","low","close","dekidaka","end"])
kabu_.dropna()

次に、ADF検定をします。
ADF検定とは、単位根過程(yt が非定常過程、また差分系列yt−yt−1=Δytが定常過程である時、ytは単位根過程である)に従うxt,yt を回帰分析を行うと、まったく関係のないxt,ytの間に有意な相関を見出してしまう「見せかけの回帰」が行われます。「見せかけの回帰」は、例えば株価と二酸化炭素濃度という関係のない2つの間に相関性を導き出してしまいます。

そのため時系列データに対して回帰分析を行う時は「見せかけの回帰」に気を付ける必要があります。

adf_result = sm.tsa.stattools.adfuller(kabu_data["ave"],autolag='AIC')
adf = pd.Series(adf_result[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
print(adf)

結果はこちら
f:id:doinakadoctor:20200107164206p:plain

注目すべきはp値とAIC値で、単位根過程の帰無仮説を棄却できる範囲にp値があるのでok、一方でAIC値はちょっと大きめ。一桁台なら理想だけど。

あとは学習させてしばらく先を予測して見ます。

100個学習して100個先を予測、ですね。
forecast( )関数の引数に100を入れます。

N = 100

test = kabu_data.loc[:,'ave']
kabu = kabu_data.loc[:N,'ave']
print(kabu)

SARIMA_kabu = sm.tsa.statespace.SARIMAX(kabu.astype(float),order=(1,0,1),seasonal_order = (1,1,1,12), enforce_stationarity = False, enforce_invertibility = False,trend = "n").fit(trend='nc',disp=False)
print(SARIMA_kabu.summary())
pred = SARIMA_kabu.predict()
pred2 = SARIMA_kabu.forecast()


kabu_diff = kabu_.diff()
kabu_diff.index = kabu_data.index
kabu_diff = kabu_diff.dropna()

plt.plot(kabu_,color = "b")
plt.plot(pred,color = "r")
plt.plot(pred2,color="y")
plt.ylim([2000,3000])
plt.show()

結果はこちら。

f:id:doinakadoctor:20200107170322p:plain

青が元データ、赤が学習過程、黄色が予測です。

ぜんっぜんグラフの形似てませんね



次数をいじったりなんらかのパラメータを変えていく必要はありそうですね、、、とりあえず予測モデルとして理論上可能ということはわかりました。
もう少し外乱の少ないネタならSARIMAXは予測機能としては遜色ないのでしょう。