ぷそさんのプログラミング研究所

【ソースコードあり】Python|株価予測で学ぶニューラルネットワークの使い方

この記事でわかること
  • ニューラルネットワークの実装方法(ソースコードつき)
  • ニューラルネットワークでの株価予測の方法
目次

ニューラルネットワークによる株価予測の概要

予測は以下の流れで行います。

つまり,30日後の株価を予測する回帰モデルになります!

他の手法でも予測しているので,ぜひご覧ください!

あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶLightGBMの使い方 この記事でわかること LightGBMの実装方法(ソースコードつき) LightGBMでの株価予測の方法 【LightGBMによる株価予測の概要】 予測は以下の流れで行います。 つまり,...
あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶランダムフォレストの使い方 この記事でわかること ランダムフォレストの実装方法(ソースコードつき) ランダムフォレストでの株価予測の方法 【ランダムフォレストによる株価予測の概要】 予測は...
あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶロジスティック回帰の使い方 この記事でわかること ロジスティック回帰の実装方法(ソースコードつき) ロジスティック回帰での株価予測の方法 【ロジスティック回帰による株価予測の概要】 予測は...
あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶディープラーニングの使い方 この記事でわかること ディープニューラルネットワークの実装方法(ソースコードつき) ディープニューラルネットワークでの株価予測の方法 【による株価予測の概要】 ...

事前準備

まずは,環境についてです。

  • Python 3.8.15
  • macOS Monterey 12.5

必要なライブラリは以下のようになります。ない場合にはpipcondaで入れてください。

必要なライブラリ

  • pandas
  • numpy
  • tensorflow
  • datetime
  • pandas_datareader

Macでのtensorflowの入れ方はこちらの記事をご覧ください。

あわせて読みたい
M1 Mac 機械学習環境を作る 【TensorFlow・LightGBM】 【はじめに】 M1 Macでの機械学習環境構築に手間取ったので、備忘録として残しておきます。 この記事で作る環境は以下のようになります。 Pythonのバージョン:3.8 機械...

ライブラリのインポート

データを扱うのに必要なライブラリのインポートを行います。

import pandas as pd
import numpy as np
from datetime import datetime

株価情報の取得

主要な株価指数の取得

予測のための説明変数として,日経平均株価などを取得します。

今回は,日経225S&P500ナスダック総合指数を取得しています。

from pandas_datareader import data
marketData = ['NIKKEI225','SP500','NASDAQCOM']
df_market = data.DataReader(marketData,'fred','2014-01-01', '2023-1-31').asfreq("D")
df_market = df_market.fillna(method='ffill')
df_market = df_market.dropna(how='any')

3行目:df_market = data.DataReader…

指数を2014年1月1日から2023年1月31日まで取得しています。

4行目:df_market = df_market.fillna…

欠損値を埋めています。

5行目:df_market = df_market.dropna…

欠損値がある場所は削除しています。

株価取得の詳しい内容については以下をご覧ください。

あわせて読みたい
【コピペ可】Pythonで株価分析|株価データの取得 Pythonを使った株価分析の基本を解説します! 【株価データを取得する】 株価データを取得するにはpandas-datareaderというライブラリを使用します。 このライブラリで...

主要な株価指数の前処理

株価指数そのままでは学習しにくいので,移動平均との乖離を計算します。

ここは精度に関係するので試行錯誤する必要があります。

# 各指数の移動平均との乖離率を算出する
for index_name in df_market.columns:
    for i in [5,10,30,60,90,120]:
        df_market[index_name + "_" + str(i) + "days_diffrol"] =\
        (df_market[index_name].rolling(i).mean() - df_market[index_name]) / df_market[index_name].rolling(i).mean()
    
    # 生データは削除する
    df_market = df_market.drop(columns=index_name)

予測する企業の株価を取得

予測したい企業の株価を取得します。

CODE=の部分は予測したい企業の株価コードを指定します。

今回は4755の企業の予測をしています。

# 予測する企業の株価データを取得
from pandas_datareader.stooq import StooqDailyReader
CODE = 4755
CODE_str = str(CODE) + ".JP"
start = datetime(2014, 1, 1)
end = datetime(2023, 1, 31)

df_target = StooqDailyReader(CODE_str, start=start, end=end).read()
df_target = df_target.sort_values('Date')
df_target = pd.DataFrame(df_target).asfreq("D", method="ffill")

5行目:start = datetime(2014, 1, 1)

取得する範囲のスタートを設定します。endも同じです。

8行目:df_target = StooqDailyReader…

データを取得します。

9行目:df_target = df_target.sort_values(‘Date’)

df_targetには最近のデータから順番に入っているので昇順にします。

10行目:df_target = pd.DataFrame…

データの欠損値処理をしています。

予測対象の作成

予測するのは,30日後の株価です。

# 目的変数の作成(30日後の終値)
df_target["target"] = df_target["Close"].shift(-30)

# 不要な行と列を削除
df_target = df_target.dropna(how='any')

2行目:df_target[“target”] = …

Closeに入っている終値を30日ずらすことで,30日後の終値を取得しています。

データの整理

データの結合

これまでに作成したデータを結合して1つのdataframeにします。

# データの結合
df = pd.merge(df_target, df_market, how='left', left_index=True, right_index=True)
df = df.dropna(how='any')

学習データとテストデータに分割

今回は,2021年までのデータを使って2022年の予測を行います。

# トレインとテストに分割
df_train = df[:"2021"]
df_test = df["2022":]

# 目的変数と説明変数に分割
X_train = df_train.drop("target", axis=1)
y_train = df_train["target"]
X_test = df_test.drop("target", axis=1)
y_test = df_test["target"]

データを標準化する

ニューラルネットワークに入れる説明変数は標準化正規化といった前処理をする必要があります。

今回はscikit-learnを使って標準化しました。

#標準化を行う
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

4行目:scaler.fit(X_train)

学習データを使って標準化のための変数を取得しています。

6行目:X_train = scaler.transform(X_train)

学習データを標準化しています。

7行目:X_test = scaler.transform(X_test)

テストデータを標準化しています。

モデルの作成

ニューラルネットワークでの学習

いよいよ作成したデータを学習させます。

# 学習
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras.optimizers import Adam
# ニューラルネットワーク
model = Sequential()
# Denseは全結合層
model.add(Dense(128, input_dim=23, activation='relu'))
model.add(Dense(1, activation='relu'))

# パラメタ
loss = 'mean_squared_error'
optimizer = Adam()
metrics = ['accuracy']

model.compile(loss=loss, optimizer=optimizer, metrics=metrics)

history  = model.fit(X_train, y_train, epochs=200, batch_size=32) # 学習

6行目:model = Sequential()

モデルを定義しています。

8行目:model.add(Dense…

説明変数は23個で,中間層は1層で128ノードとしています。

Denseは全結合という意味です。

9行目:model.add(Dense(1, activation=’relu’))

出力層は30日後の株価であるので,出力層は1ノードになります。

12行目:loss = ‘mean_squared_error’

損失関数を定義しています。

13行目:optimizer = Adam()

最適化アルゴリズムを指定しています。今回はAdamを使用しています。

14行目:metrics = [‘accuracy’]

評価関数を定義しています。

16行目:model.compile(…

モデルをコンパイルしています。

18行目:history =

モデルにデータを入れて学習させます。

下のような感じで学習が進めばOKです。

Epoch 195/200
88/88 [==============================] – 0s 638us/step – loss: 12125.3743 – accuracy: 0.0000e+00
Epoch 196/200
88/88 [==============================] – 0s 728us/step – loss: 11865.1447 – accuracy: 0.0000e+00
Epoch 197/200
88/88 [==============================] – 0s 631us/step – loss: 11608.6920 – accuracy: 0.0000e+00
Epoch 198/200
88/88 [==============================] – 0s 549us/step – loss: 11603.5125 – accuracy: 0.0000e+00 Epoch
199/200
88/88 [==============================] – 0s 523us/step – loss: 11968.9549 – accuracy: 0.0000e+00
Epoch 200/200
88/88 [==============================] – 0s 476us/step – loss: 11611.8031 – accuracy: 0.0000e+00

結果の保存

予測結果を保存して精度を確認します。

df_resultに結果をまとめます。

# 予測値と実値との比較
df_result = pd.DataFrame()
df_result["Price"] = df_target["Close"]["2022-01-31":]
df_result["true"] = y_test.values[:366-30]
df_result["pred"] = model.predict(X_test)[:366-30]

結果の確認

matplotlibで結果を表示してみましょう。

import matplotlib.pyplot as plt

plt.figure()
df_result[["true","pred"]].plot(figsize=(6, 4))

青線は実際の株価オレンジ線が予測結果を示しています。

大まかな傾向はなんとなく予測できているようですが,細かい動きは予測がうまくいっていません。

ですので,使えるモデルにするためには,ノード数を変えるなどパラメータチューニングを行う必要があります。

他の精度を上げる方法は以下の方法が考えられます。

精度を上げる方法

  • 他のアルゴリズムを使用する
  • 層数を増やす
  • 他の指標を使って予測する

多層にしたニューラルネットワークは以下の記事で紹介しています!

あわせて読みたい
【ソースコードあり】Python|株価予測で学ぶディープラーニングの使い方 この記事でわかること ディープニューラルネットワークの実装方法(ソースコードつき) ディープニューラルネットワークでの株価予測の方法 【による株価予測の概要】 ...

ソースコードまとめ

今回使用したコードはこちらになります。

import pandas as pd
import numpy as np
from datetime import datetime

# 市場データの取得
from pandas_datareader import data
marketData=['NIKKEI225','SP500','NASDAQCOM']
df_market = data.DataReader(marketData,'fred','2014-01-01', '2023-1-31').asfreq("D")
df_market = df_market.fillna(method='ffill')
df_market = df_market.dropna(how='any')

# 各指数の移動平均との乖離率を算出する
for index_name in df_market.columns:
    for i in [5,10,30,60,90,120]:
        df_market[index_name + "_" + str(i) + "days_diffrol"] =\
        (df_market[index_name].rolling(i).mean() - df_market[index_name]) / df_market[index_name].rolling(i).mean()
    
    # 生データは削除する
    df_market = df_market.drop(columns=index_name)

# 予測する企業の株価データを取得
from pandas_datareader.stooq import StooqDailyReader
CODE = 4755
CODE_str = str(CODE) + ".JP"
start = datetime(2014, 1, 1)
end = datetime(2023, 1, 31)

df_target = StooqDailyReader(CODE_str, start=start, end=end).read()
df_target = df_target.sort_values('Date')
df_target = pd.DataFrame(df_target).asfreq("D", method="ffill")

# 目的変数の作成(30日後の終値)
df_target["target"] = df_target["Close"].shift(-30)

# 不要な行と列を削除
df_target = df_target.dropna(how='any')

# データの結合
df = pd.merge(df_target, df_market, how='left', left_index=True, right_index=True)
df = df.dropna(how='any')

# トレインとテストに分割
df_train = df[:"2021"]
df_test = df["2022":]

# 目的変数と説明変数に分割
X_train = df_train.drop("target", axis=1)
y_train = df_train["target"]
X_test = df_test.drop("target", axis=1)
y_test = df_test["target"]

#標準化を行う
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

# 学習
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras.optimizers import Adam
# ニューラルネットワーク
model = Sequential()
# Denseは全結合層
model.add(Dense(128, input_dim=23, activation='relu'))
model.add(Dense(1, activation='relu'))

# パラメタ
loss = 'mean_squared_error'
optimizer = Adam()
metrics = ['accuracy']

model.compile(loss=loss, optimizer=optimizer, metrics=metrics)

history  = model.fit(X_train, y_train, epochs=200, batch_size=32) # 学習

# 予測値と実値との比較
df_result = pd.DataFrame()
df_result["Price"] = df_target["Close"]["2022-01-31":]
df_result["true"] = y_test.values[:366-30]
df_result["pred"] = model.predict(X_test)[:366-30]

import matplotlib.pyplot as plt

plt.figure()
df_result[["true","pred"]].plot(figsize=(6, 4))
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

このブログでは,PythonやLaTeXの使い方などを紹介しています!
仕事でも趣味でもプログラミングをしています。
ブログは2022年8月にスタートしました。
【経歴】東京大学大学院修了→大手IT企業勤務

コメント

コメントする

目次