はじめに
前回、TimesFMを使ってsin波を予測しました。
sinの単調波では、見事に学習せずに予測が可能でしたが、合成波となると正しい予測はできませんでした。
しかし、ピークや折り返しなどの周波数特性は正しく予期できていたようにも感じます。
そこで、今回は株価に対してTimesFMを使ってみて、ピークや折り返し等が正しく予測できるのかを確かめたいと思います。
環境構築等は前回の記事をご確認ください。
※論文を確認せずにノリでパラメータを弄っているので、適切なパラメータを設定できているのか不明です。
※timesFMの学習データに株価も入っていたと思うので、apple株が学習されていた場合には、学習データをテストデータに利用したということになります。そのため、この記事での話は、そんなに信頼しないでください
実験 Apple株 1日足
以下jupyter notebookの記録です
まず、timesfmやyfinanceをインポートします。
import timesfm
import yfinance as yf
Appleの株価をダウンロードします。
df = yf.download(tickers='AAPL', interval='1d')
df = df.reset_index().rename(columns={'Datetime':'ds'})
df['unique_id'] = 'APPL'
df
yfinanceが問題なければ、数秒でapple株の株価の記録が取得できます。
1980年からの株価が取れました。
[*********************100%%**********************] 1 of 1 completed
Date Open High Low Close Adj Close Volume unique_id
0 1980-12-12 0.128348 0.128906 0.128348 0.128348 0.099058 469033600 APPL
1 1980-12-15 0.122210 0.122210 0.121652 0.121652 0.093890 175884800 APPL
2 1980-12-16 0.113281 0.113281 0.112723 0.112723 0.086998 105728000 APPL
3 1980-12-17 0.115513 0.116071 0.115513 0.115513 0.089152 86441600 APPL
4 1980-12-18 0.118862 0.119420 0.118862 0.118862 0.091737 73449600 APPL
... ... ... ... ... ... ... ... ...
10944 2024-05-13 185.440002 187.100006 184.619995 186.279999 186.279999 72044800 APPL
10945 2024-05-14 187.509995 188.300003 186.289993 187.429993 187.429993 52393600 APPL
10946 2024-05-15 187.910004 190.649994 187.369995 189.720001 189.720001 70400000 APPL
10947 2024-05-16 190.470001 191.100006 189.660004 189.839996 189.839996 52845200 APPL
10948 2024-05-17 189.509995 190.809998 189.179993 189.869995 189.869995 41260800 APPL
10949 rows × 8 columns
データが多すぎると感じたため、2015年以前は切り捨てます。また、モデルにいれるのは2024年までのデータとし、それ以降の推移を予測値と実際の値を比較します。
import pandas as pd
df['ds'] = pd.to_datetime(df['ds'])
input_df = df.loc[('2015-01-01' <= df['ds']) & (df['ds'] <= '2023-01-01'), :]
input_df
ds Open High Low Close Adj Close Volume unique_id
8589 2015-01-02 27.847500 27.860001 26.837500 27.332500 24.402172 212818400 APPL
8590 2015-01-05 27.072500 27.162500 26.352501 26.562500 23.714727 257142000 APPL
8591 2015-01-06 26.635000 26.857500 26.157499 26.565001 23.716957 263188400 APPL
8592 2015-01-07 26.799999 27.049999 26.674999 26.937500 24.049519 160423600 APPL
8593 2015-01-08 27.307501 28.037500 27.174999 27.972500 24.973555 237458000 APPL
... ... ... ... ... ... ... ... ...
10848 2023-12-22 195.179993 195.410004 192.970001 193.600006 193.091385 37122800 APPL
10849 2023-12-26 193.610001 193.889999 192.830002 193.050003 192.542816 28919300 APPL
10850 2023-12-27 192.490005 193.500000 191.089996 193.149994 192.642548 48087700 APPL
10851 2023-12-28 194.139999 194.660004 193.169998 193.580002 193.071426 34049900 APPL
10852 2023-12-29 193.899994 194.399994 191.729996 192.529999 192.024185 42628800 APPL
2264 rows × 8 columns
timesFMのモデルを作ります。入力長は512日、出力長は128日としました
tfm = timesfm.TimesFm(
context_len=512,
horizon_len=128,
input_patch_len=32,
output_patch_len=128,
num_layers=20,
model_dims=1280,
backend="cpu",
)
huggingfaceからモデルの学習済モデルの重みをロードします
import json
with open('/work/api_keys.json', 'r') as f:
api_keys = json.load(f)
from huggingface_hub import login
login(token = api_keys['huggingface_hub'])
tfm.load_from_checkpoint(repo_id="google/timesfm-1.0-200m")
timesFMによる予測をします。入力がDataFrameのときは、forecastではなく、forecast_on_dfを利用できます。
forecast_df = tfm.forecast_on_df(
inputs=input_df,
freq="D",
value_name="Close",
num_jobs=-1,
)
forecast_df
予測値のDataFrameを見てみます
unique_id ds timesfm timesfm-q-0.1 timesfm-q-0.2 timesfm-q-0.3 timesfm-q-0.4 timesfm-q-0.5 timesfm-q-0.6 timesfm-q-0.7 timesfm-q-0.8 timesfm-q-0.9
0 APPL 2023-12-30 193.824905 189.920166 191.067902 192.396881 193.090027 193.824905 194.257050 194.873138 195.946579 196.972046
1 APPL 2023-12-31 193.135178 187.809860 189.859909 191.212402 192.315063 193.135178 193.971436 195.005432 196.001022 197.756500
2 APPL 2024-01-01 193.152405 186.541275 189.248810 190.769104 192.029007 193.152405 194.231079 195.556320 196.747528 199.074417
3 APPL 2024-01-02 192.817001 185.113586 187.716446 189.817917 191.249908 192.817001 194.021362 195.412933 197.100113 199.621582
4 APPL 2024-01-03 192.280167 184.058487 186.997787 189.262711 190.785080 192.280167 193.764771 195.414093 197.317627 199.956375
... ... ... ... ... ... ... ... ... ... ... ... ...
123 APPL 2024-05-01 192.947479 159.177216 171.322449 179.525940 186.530045 192.947479 199.136429 206.269943 214.595337 227.278061
124 APPL 2024-05-02 193.503845 159.004486 171.467606 179.526306 186.967072 193.503845 199.708710 206.847366 215.365814 228.087616
125 APPL 2024-05-03 193.618210 158.960068 171.360428 179.962936 187.098495 193.618210 199.996384 207.489380 215.808807 228.819122
126 APPL 2024-05-04 193.407379 158.507553 171.073883 179.440750 186.996185 193.407379 200.238815 207.045792 215.834259 229.334900
127 APPL 2024-05-05 193.601639 157.930084 170.636337 179.551376 186.643951 193.601639 200.288055 207.499008 216.571320 230.005173
128 rows × 12 columns
予測結果を描画してみます
import matplotlib.pyplot as plt
plot_df = df.loc[df['ds'] > '2022-01-01']
plt.plot(plot_df['ds'], plot_df['Close'], label='raw')
plt.plot(forecast_df['ds'], forecast_df['timesfm'], label='predict')
plt.fill_between(forecast_df['ds'], forecast_df["timesfm-q-0.4"], forecast_df["timesfm-q-0.6"], color='gray', alpha=0.3, label='predict-bounds')
plt.xticks(rotation=30)
plt.legend()
![](https://emoclework.jp/wp-content/uploads/2024/05/image-8.png)
あまり、予測できたとは言いづらい結果になりました。
しかし、下がって、上がって下がって上がるという傾向は確かに合っています。これは偶然でしょうか?
2023年からの予測
2023-01-01から予測してみます
import pandas as pd
df['ds'] = pd.to_datetime(df['ds'])
input_df = df.loc[('2015-01-01' <= df['ds']) & (df['ds'] <= '2023-01-01'), :]
forecast_df = tfm.forecast_on_df(
inputs=input_df,
freq="D",
value_name="Close",
num_jobs=-1,
)
import matplotlib.pyplot as plt
plot_df = df.loc[df['ds'] > '2022-01-01']
plt.plot(plot_df['ds'], plot_df['Close'], label='raw')
plt.plot(forecast_df['ds'], forecast_df['timesfm'], label='predict')
plt.fill_between(forecast_df['ds'], forecast_df["timesfm-q-0.4"], forecast_df["timesfm-q-0.6"], color='gray', alpha=0.3, label='predict-bounds')
plt.xticks(rotation=30)
plt.legend()
![](https://emoclework.jp/wp-content/uploads/2024/05/image-9.png)
株価自体はまたしても、全く一致しませんが、トレンドの上下および傾向はなんとなくあっているような気もします。
2022年からの予測
2022-01-01から予測してみます
import pandas as pd
df['ds'] = pd.to_datetime(df['ds'])
input_df = df.loc[('2015-01-01' <= df['ds']) & (df['ds'] <= '2022-01-01'), :]
forecast_df = tfm.forecast_on_df(
inputs=input_df,
freq="D",
value_name="Close",
num_jobs=-1,
)
import matplotlib.pyplot as plt
plot_df = df.loc[df['ds'] > '2022-01-01']
plt.plot(plot_df['ds'], plot_df['Close'], label='raw')
plt.plot(forecast_df['ds'], forecast_df['timesfm'], label='predict')
plt.fill_between(forecast_df['ds'], forecast_df["timesfm-q-0.4"], forecast_df["timesfm-q-0.6"], color='gray', alpha=0.3, label='predict-bounds')
plt.xticks(rotation=30)
plt.legend()
![](https://emoclework.jp/wp-content/uploads/2024/05/image-10.png)
全く見当違いな予測をしました。2023-01-01と2024-01-01からの予測で、傾向があっていたのは偶然だったかもしれません。
長期間の予測
予測期間を長くしてみて、当たるのかを試してみます。なんとなく512日間を予測期間としてみます。
tfm = timesfm.TimesFm(
context_len=1024,
horizon_len=512,
input_patch_len=32,
output_patch_len=128,
num_layers=20,
model_dims=1280,
backend="cpu",
)
tfm.load_from_checkpoint(repo_id="google/timesfm-1.0-200m")
import pandas as pd
df['ds'] = pd.to_datetime(df['ds'])
input_df = df.loc[('2015-01-01' <= df['ds']) & (df['ds'] <= '2023-01-01'), :]
forecast_df = tfm.forecast_on_df(
inputs=input_df,
freq="D",
value_name="Close",
num_jobs=-1,
)
import matplotlib.pyplot as plt
plot_df = df.loc[df['ds'] > '2022-01-01']
plt.plot(plot_df['ds'], plot_df['Close'], label='raw')
plt.plot(forecast_df['ds'], forecast_df['timesfm'], label='predict')
plt.fill_between(forecast_df['ds'], forecast_df["timesfm-q-0.4"], forecast_df["timesfm-q-0.6"], color='gray', alpha=0.3, label='predict-bounds')
plt.xticks(rotation=30)
plt.legend()
![](https://emoclework.jp/wp-content/uploads/2024/05/image-11.png)
予想通り、長期間(1年と半年程度)の予測はできませんでした。未来視でも持っていない限り、アップルの株価が1年後どうなっているかなんて、正確に予想することが叶うわけがありません。
もう少し企業の成長能力が反映されづらい、為替や石油価格等の予測ではもしかしたら、うまくいくのかもしれません。
続きを書く気が湧いたら、為替の予測もしてみたいと思います
おわりに
株価の予測はできるとは言いづらい結果になりました。
一部の期間で、トレンドが一致している可能性が示唆されましたが、多くの期間で検証実験をしていないため、「予測できる」という結論を今回は導けませんでした。
追記
timesFMで為替予測する話を書きました。