回心誌

日々是回心

LSTMでの株価予測を試してみる

LSTMで株価予測入門 [Python,Keras] | スーパーソフトウエア東京

上の記事を参考に進めてみる。

どうも基本的な環境構築はすんでる前提っぽい。
ので、必要なPythonモジュールをpipでインストールする。

pip install scikit-learn
pip install pandas_datareader
pip install  yfinance
pip install kearas
pip install matplotlib

足りないモジュールはひとによると思うので、各自の環境に合わせてインストールする必要がある。

あと、Jupiter Notebookも使う前提っぽい。
自分はAnacondaとか入ってないので、これもpipでインストールする。

pip install jupyter

環境変数のPATHに以下を追加。
%localappdata%\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\Scripts


で、Jupiterを起動して各コードを入れていく。

jupyter notebook

x_trainとy_trainを作成した時点で、一旦データの形式を確認してみる。

改めて、どういう学習するのかというと、

ここで実装する基本的な考え方としては、株価の時系列データをWindow(窓)と呼ばれる期間分ずらしたデータをインプットデータとして学習を行います。例えばWindowサイズが60の場合、過去60日分のデータを学習して61日目のデータを予想する、ということを繰り返して学習するモデルになります。

まず、トレーニングデータとテストデータに分割している。8割がトレーニングデータ、残り2割がテストデータ。


レーニングデータではx_trainとy_trainの2つがあるが、x_trainは予想のための説明変数、y_trainが予想したい目的変数、ということになる。

上の図だと1セット分のデータだけになっているが、実際にはこれを1日ずつずらした1963セットある、という感じになっている。


で、まあこんな感じで実際の値と予測値が重なってますよーってなグラフになるんだけど、これでうまくいってるとみなすことはできないと思ってて、というのも実際には前日までの60日間分のデータから予測しているんだから、ある程度重なるようなグラフになるのは当たり前。
前日と同じ株価を予測値として出力したとしても、グラフの形としては同じような形になる。

決定係数も0.93とか出てて高そうに見えるけど、これも前日と同じにすれば1にかなり近い数字になるので、評価としては役立たない。

実際に投資で使えるかどうか見てみたいので、翌日の株価が当日より高いか低いか判断するバイナリーオプションで成績がどの程度になるかを見てみたい。

とりあえず、データをバイナリーオプションの形式に変換する関数を作る。

# テストデータの目的変数(y)は正規化されたものがなかったので、作成
y_scaled = []
for i in range(window_size, len(test_data)):
    y_scaled.append(test_data[i, 0])
y_scaled = np.array(y_scaled)

# x,yを受け取って、バイナリーオプション形式に変換する
def transform_binaryoption(x, y):
    bo = []
    for i,_ in enumerate(x):
        if x[i][-1][0] > y[i]:
            bo.append(-1)
        else:
            bo.append(1)
    return np.array(bo)

# バイナリーオプションのテストデータ(正解)を作成
bo_test = transform_binaryoption(x_test, y_scaled)

再度予測して、正規化済みの予測値を作成し、同じ関数でバイナリーオプションの予測値を作成する。

# 予測値を再度作成し、バイナリーオプションの形式に変換
predictions_scaled = model.predict(x_test)
bo_predictions = transform_binaryoption(x_test, predictions_scaled)

んで、正答率を計算してみる。

# 予測値を評価
correct_list = []
for i,_ in enumerate(bo_test):
    if bo_test[i] == bo_predictions[i]:
        correct_list.append(1)
    else:
        correct_list.append(0)

correct_rate = sum(correct_list)/len(correct_list)
correct_rate


結果は49.5%だった。
あてずっぽうで50%になるから、これは実際には使い物にならんねw