投資のためのデータサイエンス

個人の投資活動に役立つデータ分析にまつわる話題を綴ります。

機械学習を用いた株価予測のデモ

今回は実用性とは若干乖離しますが、機械学習を用いた株価予測について調べましたので、関連コードを紹介します。
今回紹介するコードは英文のgitリポジトリのサイトからの引用です。
ここではLSTMという機械学習手法を用いています。LSTM(Long Short Term Memory) ネットワークは、長期的な依存関係を学習することのできる、RNN(リカレントニューラルネットワーク)の特別な一種です。

まずライブラリをインポートして、次に株価データを獲得します。

# ライブラリのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.optimizers import Adam
from pandas_datareader import data as pdr
from datetime import date, datetime, timedelta
import yfinance as yf

# yahooサイトからデータをダウンロード
ticker = '9984.T' # 9984はソフトバンクグループ
end_date = datetime.today()
start_date = end_date - timedelta(days=180)
yf.pdr_override()
data = pdr.get_data_yahoo(ticker, start_date, end_date)
close_prices_AAPL = data['Close']

次にデータの前処理を行います。一般に機械学習モデルにかけるためにデータの標準化が必要です。そしてデータの次元をモデルにかけれらるように変形し、さらに学習用データとテスト用データに分けます。

# Reverse the order of the data
close_prices_AAPL_reverse = close_prices_AAPL # No Reverse
#close_prices_AAPL_reverse = close_prices_AAPL.iloc[::-1]

# Reset index to maintain the correct time series order in the plot
close_prices_AAPL_reverse.reset_index(drop=True, inplace=True)

# Data preprocessing
data = close_prices_AAPL_reverse.values.reshape(-1, 1)  # Reshape the data
data_normalized = data / np.max(data)  # Normalize the data

# Split the data into training and testing sets
train_size = int(len(data_normalized) * 0.8)
train_data = data_normalized[:train_size]
test_data = data_normalized[train_size:]

続いてLSTMモデルを構築します。モデルの構造はさらに改良することが可能とみられます。

# Function to create LSTM model
def create_lstm_model(units, activation, learning_rate):
    model = Sequential()
    model.add(LSTM(units=units, activation=activation, input_shape=(1, 1)))
    model.add(Dense(units=1))
    optimizer = Adam(learning_rate=learning_rate)
    model.compile(optimizer=optimizer, loss='mean_squared_error')
    return model

続いて学習用データを使い、評価基準としてRMSE(平均二乗誤差の平方根)を採用してパラメータのチューニングを行います。

# Define hyperparameters for tuning
lstm_units = [50, 100, 200]
lstm_activations = ['relu', 'tanh']
learning_rates = [0.001, 0.01, 0.1]
epochs = 100
batch_size = 32

# Perform hyperparameter tuning for LSTM model
best_rmse = float('inf')
best_lstm_model = None

for units in lstm_units:
    for activation in lstm_activations:
        for learning_rate in learning_rates:
            # Create and train LSTM model
            model = create_lstm_model(units=units, activation=activation, learning_rate=learning_rate)
            model.fit(train_data[:-1].reshape(-1, 1, 1), train_data[1:], epochs=epochs, batch_size=batch_size, verbose=0)

            # Predict on test data
            test_predictions = model.predict(test_data[:-1].reshape(-1, 1, 1)).flatten()

            # Calculate RMSE
            rmse = np.sqrt(mean_squared_error(test_data[1:], test_predictions))

            # Check if current model has lower RMSE
            if rmse < best_rmse:
                best_rmse = rmse
                best_lstm_model = model

# Predict on the entire dataset using the best LSTM model
all_lstm_predictions = best_lstm_model.predict(data_normalized[:-1].reshape(-1, 1, 1)).flatten()

# Inverse normalize the LSTM predictions
all_lstm_predictions = all_lstm_predictions * np.max(data)

# Calculate the scaling factor based on the maximum value of the original data
scaling_factor = np.max(close_prices_AAPL_reverse)

最後にモデルを用いて直近の将来10時点の値を予測します。

# Function to predict future stock prices using the LSTM model
def predict_future_lstm(model, data, num_predictions, scaling_factor):
    predictions = []

    # Get the last data point from the input data
    last_data_point = data[-1]

    for _ in range(num_predictions):
        # Predict the next time step
        prediction = model.predict(last_data_point.reshape(1, 1, 1))
        predictions.append(prediction[0, 0])

        # Update last_data_point to include the predicted value for the next iteration
        last_data_point = np.append(last_data_point[1:], prediction)

    # Inverse normalize the predictions
    predictions = np.array(predictions) * scaling_factor

    return predictions

# Predict the next 10 days using the LSTM model
num_predictions = 10
lstm_predictions = predict_future_lstm(best_lstm_model, data_normalized, num_predictions, scaling_factor)

# Plot the LSTM predictions for the next 10 days
plt.figure(figsize=(10, 6))
plt.plot(close_prices_AAPL_reverse, label='Actual')
plt.plot(np.arange(len(close_prices_AAPL_reverse), len(close_prices_AAPL_reverse) + num_predictions), lstm_predictions, label='LSTM Predicted')
plt.title(f"LSTM Model - RMSE: {best_rmse:.2f}")
plt.xlabel('Time')
plt.ylabel('Stock Price')
plt.legend()
plt.show()

# Print the predicted stock prices for the next 10 days using LSTM
print("Predicted stock prices for the next 10 days:")
for i, prediction in enumerate(lstm_predictions, start=1):
    print(f"Day {i}: {prediction:.2f}")


オリジナルのコードでは、他の手法による予測も行っています。この手の手法の実用性についてはさらなる調査が必要です。
※ローカルPCで本コードを実行する場合は機械学習ライブラリのインストールが必要ですが、Google Colabではyfinanceライブラリを事前にインストールすれば動きます。