見出し画像

ディープラーニングで株価予測を試しました。

はじめに

こんにちは、やまほんです。
今年30歳という節目を迎え、自身のキャリアと向き合って、場当たり的に営業を行っている現状に不安を感じたおっさんです。
これからの時代、ビッグデータをどう活かすかで仕事も人生も変わってくると考え一念発起し、AidemyでPythonの勉強を行っています。
今回は、学んだことを活かし、株価予測に取り組もうと思います。

実行環境

Python3
Windows10
Chrome
Google Colaboratory

私のレベル

2022年8月に全くの未経験から、Aidemyのデータ分析講座を受講開始。
データ分析においては統計学の知識を使いますが、学生時代の大学の講義で一応軽く触れました。が、そこから全く触れてないのでゼロに近いと思います。
社会人になってからは営業一筋で、関連するような業務は一切ありませんでした。

主旨

株価や為替の予測には大きく分けて
ファンダメンタル分析(相場の大きな方向性を掴むために景気動向、金融政策、財政政策等の変化が市場全体にどのような影響を及ぼすのかを分析するもの)
テクニカル分析(過去の値動きをチャートで表して、そこからトレンドやパターンなどを把握し、今後の株価、為替動向を予想するもの)
の2種類あります。
今回は後者のテクニカル分析を試みます。
具体的には終値に注目しディープランニングのLSTMを使い予想させていきます。

全体の流れ

・ライブラリの準備
 ↓
・株価データの読み込み
 ↓
・データの前処理
 ↓
・モデルの作成、精度・予測結果の確認

セットアップ

まず必要になりそうなライブラリの準備と、インストールを行います。
今回はpandas datareaderとyahooからデータを用意します。
しらべたところ、環境によっては先に下記二つを先に実行する必要があるそうです。(私は必要でした。)

pip install pandas-datareader
pip install yfinance

それでは必要になりそうなライブラリの準備をしていきます。

import math
from pandas_datareader import data as pdr
import yfinance as yf
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM
import matplotlib.pyplot as plt
import datetime
from sklearn.metrics import r2_score

今回は、愛すべき故郷奈良県の経済を牛耳っていると言っても過言ではない、私も大変お世話になっていた近鉄(近鉄グループホールディングス (9041/T))の株価予想を行いたいと思います。
奈良県の、電車やバスの交通網からスーパー、百貨店、遊園地、不動産・・・etcまで近鉄が無いと奈良県民は死ぬんじゃないかと私界隈では言われていますが、そんな近鉄への愛を語ると長くなるので割愛します。


#近鉄(9041.T)の株価を取得 2016/01/01から2022/09/30まで利用

start = "2016-1-1"
end = "2022-9-30"
ticker = "9041.T"

yf.pdr_override()
df = pdr.get_data_yahoo(ticker, start, end)
 #試しに先頭10個のデータを表示してみます df.head(10)


出力結果

今回使用するのは終値(Close)なので、終値だけのデータフレームを作成し、確認のため簡単にグラフで表示させます。

 #dfから終値だけのデータフレームを作成する 。(インデックスは残っている)
data = df.filter(['Close'])
print(data)
data.plot()
plt.xlabel("Date")
plt.ylabel("Close price")
plt.show()


出力結果

ディープランニングモデルの作成

まずはデータの前処理から行っていきます。

 #dataをデータフレームから配列に変換する
dataset = data.values
 #トレーニングデータを格納するための変数を作る#データの80 %をトレーニングデータとして使用する。 #math .ceil()は小数点以下の切り上げ
training_data_len = math.ceil(len(dataset) * .80)
 #データセットを正規化する
scaler = MinMaxScaler(feature_range=(01))  #fitは変換式を計算する  #transform  は fit の結果を使って、実際にデータを変換する
scaled_data = scaler.fit_transform(dataset)
 #正規化されたデータセットを作る 。データ数はトレーニングデータ数にする
len(scaled_data)
train_data = scaled_data[0:training_data_len:]
len(scaled_data)
 #121番目の終値を予測するため 、過去120日間の終値を含むトレーニングデータセットを作成します。 #x_trainデータセットの最初の列には 、インデックス0からインデックス119までのデータセットの値(合計120個の値)が含まれ、 #2番目の列にはインデックス1からインデックス120までのデータセットの値 (120個の値)が含まれます。 #y_trainデータセットには 、最初の列のインデックス120にある121番目の値と、 #2番目の値のデータセットのインデックス121にある122番目の値が含まれます
 #データをx_trainとy_trainのセットに分ける 
x_train = []
y_train = []
for i in range(120, len(train_data)):
    x_train.append(train_data[i-120:i0])
    y_train.append(train_data[i, 0])

x_train, y_train = np.array(x_train), np.array(y_train)

次にLTSMの形式で学習させます。

 #LSTMに受け入れられる形にデータをつくりかえます 
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
 #LSTMモデルを構築して 、50ニューロンの2つのLSTMレイヤーと2つの高密度レイヤーを作成します。(1つは25ニューロン、もう1つは1ニューロン)

model = Sequential()
model.add(LSTM(units=50, return_sequences=True,input_shape=(x_train.shape[1],1)))
model.add(LSTM(units=50, return_sequences=False))
model.add(Dense(units=25))
model.add(Dense(units=1))
 #平均二乗誤差 (MSE)損失関数とadamオプティマイザーを使用してモデルをコンパイルします。
model.compile(optimizer='adam', loss='mean_squared_error')
 #モデルをトレーニングする 
model.fit(x_train, y_train, batch_size=1, epochs=1)

テストデータを用いて株価予測します

 #test_dataはtraining_dataから120コ減らしたデータ  #つまり120日間の終値から将来の終値を予測するためにtest_dataを用意する 
test_data = scaled_data[training_data_len - 120: , : ]
 #テストデータをx_trainとy_trainのセットに分ける 
x_test = [] #予測値をつくるために使用するデータを入れる
y_test = dataset[training_data_len : , : ] #実際の終値データ

for i in range(120,len(test_data)):
    x_test.append(test_data[i-120:i,0]) #正規化されたデータ
 #x_testをNumpy配列に変換する  
x_test = np.array(x_test)
 #LSTMで受け入れられる形状にデータを再形成します 
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
 #テストデータを使用してモデルから予測値を取得します#モデルの予測価格値の取得 
pred = model.predict(x_test)
pred = scaler.inverse_transform(pred)

最後に上記結果をグラフ化します。

train = data[:training_data_len]
valid = data[training_data_len:]
valid['Predictions'] = pred #データをグラフ化します
plt.figure(figsize=(24,12))
plt.title('Model')
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price ', fontsize=18)
plt.plot(train['Close'])
plt.plot(valid[['Close''Predictions']])
plt.legend(['Train''Val''Predictions'], loc='lower right')
plt.show()


出力結果

青色の線が実際のデータとして学習させた部分、黄色の線が予測期間の間の実際の株価のデータ、緑の線が青色の部分で学習させた部分からの予測となります。
視覚的には全体の流れとしては大きくずれてないにしても、やはり詳細まで一致していることはないので、このモデルを用いて短期的にデイトレードなどをするのは非常に怖いですが、中長期的に考えるのであれば参考にできるのではないでしょうか。

精度の検証

最後に予測の精度を確認したいと思います。
今回は、簡易的にRSMEと、モデルの適合性を測るR²を使っていきたいと思います。
RSMEとは二乗平均平方根誤差というもので

このような式で表せます。誤差、と名前があるように0に近ければ近いほどいいものです。
R2は決定件数と呼ばれるもので

と表せます。こちらはモデルの当てはまり具合を示すもので、1に近ければ近いほどいいものになります。

コードは以下のようになります。

# 二乗平均平方根誤差(RMSE): 0に近いほど良い
rmse = np.sqrt(np.mean(((pred - y_test) ** 2)))
print("rmse")
print(rmse)

# 決定係数(r2) : 1に近いほど良い

r2s = r2_score(y_test, pred)
print("r2s")
print(r2s)

出力結果
rmse 
100.2618598477448
 r2s 
0.9437583769847337

上記から、ざっくりまとめると今回のモデルは、
大体3000円から5000円の間で値動きしていた株価に対し、約100円ほどの誤差で予想されていて
学習したモデルとはそれなりの寄与率があったということを示されています。

最後に

今回は、あくまで簡易的な予測になります。企業や期間、エポック数を変えたり、日経平均株価を用いること、また近鉄の場合は近鉄公式Twitter(@kintetsu_2sn)のツイート内容での感情分析などを盛り込んで予測を立てるとさらに精度があげることが出来るかもしれません。
今後はいろんな説明変数を試したモデルを構築し、自身の資産の運用に用いようと思えるようなものを作り上げたいと思います。

この記事が気に入ったらサポートをしてみませんか?