電通総研 テックブログ

電通総研が運営する技術ブログ

yfinanceとAWSで未来の株価を予測する(後編)

こんにちは。コミュニケーションIT事業部 ITソリューション部の英です。

普段はWebアプリやスマホアプリの案件などを担当しています。あと、趣味でAIを勉強しています。

前回はSageMakerの線形学習モデルを使って、S&P500の100日後のスコアを予測しました。
今回は同じデータを使って、Amazon Forecastで予測をしてみましょう。
前回の記事

Amazon Forecastはマネージド型の機械学習サービスです。
これにより、専門的な機械学習の知識がなくても、需要予測、在庫管理、収益予測などを簡単に行うことができます。

ちなみに、Amazon Forecastは新規ユーザーへの提供終了が発表されており、後続のサービスはSageMaker Canvasだそうです。SageMaker Canvasは、また別の記事で解説したいと思います。
SageMaker Canvas

今回の検証では、過去の株価の数値だけを参考値として予測するため、決して皆さまの資産運用の参考にはしないようにお願いいたします。
資産運用には世界情勢などの"不確かさ"が付き物です。そこが面白さでもあります。投資は自己責任です。


ここから本題

STEP1:学習用データの準備

学習用データを作成して任意のS3バケットにアップロードしましょう。

!pip install yfinance pandas boto3

import yfinance as yf
import pandas as pd
import boto3
import numpy as np

# データ取得
sp500 = yf.Ticker('^GSPC')
df = sp500.history(period='10y')

# すべての日付を取得
full_date_range = pd.date_range(start=df.index.min(), end=df.index.max(), freq='D')

# インデックスを再設定
df = df.reindex(full_date_range)

# データの補間
df['Close'].ffill(inplace=True) 

# 特徴量の計算
def calculate_features(df):
    df['MA_50'] = df['Close'].rolling(window=50).mean()
    df['MA_100'] = df['Close'].rolling(window=100).mean()
    df['MA_200'] = df['Close'].rolling(window=200).mean()
    df['BB_MID'] = df['Close'].rolling(window=20).mean()
    df['BB_STD'] = df['Close'].rolling(window=20).std()
    df['BB_UPPER'] = df['BB_MID'] + (df['BB_STD'] * 2)
    df['BB_LOWER'] = df['BB_MID'] - (df['BB_STD'] * 2)

calculate_features(df)

# 最初の200行を削除
df = df.iloc[200:]

# 日付フォーマットをyyyy-MM-ddに変更
df['Date'] = df.index.strftime('%Y-%m-%d')
df.reset_index(drop=True, inplace=True)

# item_id列に単一のアイテムIDを設定
df['item_id'] = 'sp500'

# 必要な列のみ選択し、target_valueとしてCloseを設定
df = df[['item_id', 'Date', 'Close', 'MA_50', 'MA_100', 'MA_200', 'BB_MID', 'BB_UPPER', 'BB_LOWER']]
df.rename(columns={'Close': 'target_value', 'Date': 'timestamp'}, inplace=True)

# CSVに保存
df.to_csv('sp500_features.csv', index=False)

# S3にデータをアップロード
s3 = boto3.client('s3')
bucket_name = '(バケット名)'
file_name = 'sp500_features.csv'

s3.upload_file(file_name, bucket_name, file_name)
print(f"データをS3にアップロードしました: s3://{bucket_name}/{file_name}")

STEP2:データセットの作成

データセットグループという分析用の箱を用意します。

ドメインでは様々なビジネスケースを選択できますが、株価予測はフレームワークとして用意がなかったので「Custom」を選択しておきます。

スキーマを以下のように設定します。 予約型以外はStringにすることが必須のため、移動平均線などのような数値もStringとして取り込みます。

先ほど作成したCSVファイルを選択します。

データセットグループを作成すると、インポートが始まります。
今回のケースでは約30分ほどかかりました。

STEP3:トレーニングの開始

Startを押してトレーニングの開始設定に進みます。

以下のとおり設定してみます。
予測対象は100日後の株価なので、Forecast horizonは「100」を設定します。
今回は終値のみでトレーニングしたいので、特徴量の次元(Forecast dimensions)については、「設定なし」とします。

以前はここにアルゴリズム選択があったのですが、2024年8月の現在は選択できなくなっていますね。
米国の株式市場は休場の概念があるので、米国のHolidaysを選択しておきます。

今回の設定ではトレーニングに3時間31分かかるようです。待ちましょう。

Activeになりました。

STEP4:予測データの作成

さっそく予測を作成します。

予測作成の設定画面では先ほど作成した予測モデルを選択します。

予測の作成が始まりました。1時間ほどかかるので終わるのを待ちます。

Activeになりました。

STEP5:予測データの可視化

最後にQuery forecastから予測値の可視化を行います。

現在から前後100日をプロットします。

いいですね~。100日後は5843ポイントで現在のスコアから1.12%上昇という予測で全体的にポジティブですね。
株式市場は年末に上昇するアノマリーがありますが、そこもしっかり反映されていることが確認できます。
アノマリー:理論の枠組みでは説明することができないものの、経験的に観測できるマーケットの規則性のこと

グラフの見方は以下のとおり。

  • P10: 実際の値が予測値よりも低い確率が10%であることを意味します。つまり、予測値が実際の値よりも高くなる確率が90%です。
  • P50: 実際の値が予測値よりも低い確率が50%であることを意味します。予測値が実際の値よりも高くなる確率も50%です。中央値の予測です。
  • P90: 実際の値が予測値よりも低い確率が90%であることを意味します。つまり、予測値が実際の値よりも高くなる確率が10%です。
    Evaluating Predictor Accuracy

おわりに

現在、Amazon Forecastは新規ユーザーには提供されておらず、後継サービスはSageMaker Canvasとのこと。
次回の記事ではSageMaker Canvasを使ってみようかと思います。
少し期間が空いてしまうかもですがご期待ください。

これからもAWS×AI関連の検証記事をたくさん書いていきます。
↓ のスターを押していただけると嬉しいです。励みになります。
最後まで読んでいただき、ありがとうございました。

私たちは一緒に働いてくれる仲間を募集しています!

コミュニケーションIT事業部

執筆:英 良治 (@hanabusa.ryoji)、レビュー:@handa.kenta
Shodoで執筆されました