Amazonの時系列予測モデル「Chronos-T5」で日経株価を予測してみた

# 経緯説明
しゅんです。今回もよろしくお願いします。
[前回の投稿](https://qiita.com/syun88/items/9355dff0e68d806257b2) で、Googleの時系列予測モデルであるTimesFMを使用して株価予測を試してみました。その後、Hugging Faceを再度探索して、実はずっと知ってたAmazonが提供する **Chronos-T5** モデルを試したい気分になったので、やってみました。

![Chronos-T5のHugging Faceページ](https://huggingface.co/amazon/chronos-t5-tiny/resolve/main/figures/main-figure.png)

Chronos-T5は、言語モデルアーキテクチャに基づく事前学習済みの時系列予測モデルであり、時系列データをトークン化して言語モデルとして扱うことで予測を行います。そこで、今回はこのChronos-T5を使用して株価予測を試してみることにしました。

公式資料:

- 論文: [Chronos: Learning the Language of Time Series](https://arxiv.org/abs/2403.07815)
- GitHubリポジトリ: [amazon-science/chronos-forecasting](https://github.com/amazon-science/chronos-forecasting)
- Hugging Faceモデルページ: [amazon/chronos-t5-large](https://huggingface.co/amazon/chronos-t5-large)

# 手順説明

Chronos-T5を使用して株価予測を行う手順を以下に説明します。

## 1. 環境構築

必要なライブラリをインストールします。Chronos-T5はPyTorchを使用しており、`chronos-forecasting`パッケージをGitHubからインストールする必要があります。

```bash
!pip install yfinance matplotlib pandas torch transformers accelerate bitsandbytes
!pip install git+https://github.com/amazon-science/chronos-forecasting.git
```

## 2. データの取得

予測したい株価データを取得します。ここでは、日経平均株価（^N225）を対象とします。

```python
import datetime
import yfinance as yf
import pandas as pd

# 日付の設定
start = datetime.date(2022, 1, 1)
end = datetime.date.today()

# データの取得
codelist = ["^N225"]
data = yf.download(codelist, start=start, end=end)

# データの前処理
data = data['Adj Close'].dropna()
if data.empty:
    raise ValueError("データが空です。期間を変更して再度試してください。")
```

## 3. モデルの準備

Chronos-T5モデルをロードします。今回は最も精度が高いとされる**chronos-t5-large**モデルを使用します。ただし、このモデルは非常に大きく、GPUメモリを多く消費するため、環境に応じてモデルを選択してください。

```python
import torch
from chronos import ChronosPipeline

# モデルのロード
pipeline = ChronosPipeline.from_pretrained(
    "amazon/chronos-t5-large",
    device_map="cuda",  # GPUを使用しない場合は"cpu"に変更
    torch_dtype=torch.float16,  # GPUが半精度浮動小数点をサポートしていない場合はtorch.float32に変更
)
```

## 4. 予測の実行

データをテンソルに変換し、モデルに入力します。Chronos-T5モデルは最大512ステップの入力を受け付けるため、最新の512データポイントを使用します。

```python
import numpy as np

# コンテキスト長の設定
context_len = 512
prediction_length = 128  # 予測したい期間の長さ

# データの長さを確認
if len(data) < context_len:
    context_data = data.values
else:
    context_data = data.values[-context_len:]

# データをテンソルに変換
context_tensor = torch.tensor(context_data, dtype=torch.float32)

# 予測の実行
forecast = pipeline.predict(context_tensor, prediction_length, num_samples=100)
```

## 5. 結果の可視化

予測結果をグラフにプロットして、実際の値と比較します。

```python
import matplotlib.pyplot as plt

# 予測結果の処理
low, median, high = np.quantile(forecast[0].numpy(), [0.1, 0.5, 0.9], axis=0)

# 予測期間の日付インデックスを作成
forecast_dates = pd.date_range(start=data.index[-1] + pd.Timedelta(days=1), periods=prediction_length, freq='B')

# プロット
plt.figure(figsize=(14, 7))
plt.plot(data.index, data.values, label="Actual Prices")
plt.plot(forecast_dates, median, color="tomato", label="Median Forecast")
plt.fill_between(forecast_dates, low, high, color="tomato", alpha=0.3, label="80% Prediction Interval")
plt.xlabel("Date")
plt.ylabel("Price")
plt.legend()
plt.show()
```

## 6. 結果の解釈

以下のグラフは、実際の株価（青）と予測された中央値の株価（オレンジ色）、および80%予測区間（赤の帯）を示しています。

### 日経株価予測全体像
![日経株価予測all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506235/300936b5-3aef-3f54-9621-856fcf99be1d.png)

### 日経株価予測拡大部分
![日経株価予測all2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506235/7230b9df-a0ea-8930-ae16-1d17cb834b0b.png)

### 日経株価予測予測区間全体像

![日経株価予測予測区間1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506235/598d4ddc-90ec-26a5-8d95-9607793b6d09.png)


### 日経株価予測予測区間拡大部分
![日経株価予測予測区間2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3506235/53c99d91-7924-a2e1-b3c8-f90b9de63d15.png)



## 7.FULL CODE
```python
import datetime
import yfinance as yf
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import torch
from chronos import ChronosPipeline

# 日経平均株価のデータ取得
start = datetime.date(2022, 1, 1)
end = datetime.date.today()
codelist = ["^N225"]
data2 = yf.download(codelist, start=start, end=end)

# データの前処理
data2 = data2['Adj Close'].dropna()  # Adjusted Close価格を使用し、欠損値を除去
if data2.empty:
    raise ValueError("データが空です。期間を変更して再度試してください。")

context_len = 512  # コンテキスト長の設定
prediction_length = 5  # 予測する期間の長さの設定（必要に応じて変更可能）

# データの長さに応じてコンテキストを設定
if len(data2) >= context_len:
    context_data = data2[-context_len:]  # 最新の512データポイントを使用
else:
    context_data = data2  # データ全体を使用

context_data = data2[-context_len:]  # 最新の512日分のデータをコンテキストとして使用

# Chronosモデルのロード（chronos-t5-largeを使用）
pipeline = ChronosPipeline.from_pretrained(
    "amazon/chronos-t5-large",
    device_map="cuda",  # GPUを使用する場合は"cuda"、CPUの場合は"cpu"に設定
    torch_dtype=torch.float16,  # GPUが半精度浮動小数点をサポートしていればtorch.float16を使用
)

# データをテンソルに変換
context_tensor = torch.tensor(context_data.values, dtype=torch.float32)

# 予測の実行
# forecast = pipeline.predict(context_tensor, prediction_length)  # 出力形状: [num_series, num_samples, prediction_length]


forecast = pipeline.predict(context_tensor, prediction_length, num_samples=100)


# 予測結果の処理（中央値を計算）
median_forecast = forecast.median(dim=1).values.squeeze().numpy()

# 予測結果の表示
forecast_dates = pd.date_range(start=data2.index[-1] + pd.Timedelta(days=1), periods=prediction_length, freq='B')
forecast_series = pd.Series(median_forecast, index=forecast_dates)

plt.figure(figsize=(14, 7))
plt.plot(data2.index, data2.values, label="Actual Prices")
plt.plot(forecast_series.index, forecast_series.values, label="Forecasted Prices")
plt.xlabel("Date")
plt.ylabel("Price")
plt.legend()
plt.show()
# 複数サンプルから予測区間を計算
low, median, high = np.quantile(forecast[0].numpy(), [0.1, 0.5, 0.9], axis=0)

plt.figure(figsize=(14, 7))
plt.plot(data2.index, data2.values, label="Actual Prices")
plt.plot(forecast_dates, median, color="tomato", label="Median Forecast")
plt.fill_between(forecast_dates, low, high, color="tomato", alpha=0.3, label="80% Prediction Interval")
plt.xlabel("Date")
plt.ylabel("Price")
plt.legend()
plt.show()

```

# 結論

Chronos-T5モデルを使用して株価予測を試みました。予測結果は一定の傾向を示しており、モデルが時系列データのパターンを捉えていることがわかります。

**しかし、株価予測は非常に難しく、多くの不確実性が伴います。** モデルの予測は参考程度にとどめ、実際の投資判断を行う際には、専門家の意見や他の情報源も参考にすることを強くおすすめします。

# 注意事項

:::note alert
このコードやモデルを使用して投資を行う場合、その結果に対する責任はご自身にあります。市場は多くの要因によって変動し、AIモデルがすべてを予測できるわけではありません。投資は慎重に行ってください。
:::

# まとめ

今回、AmazonのChronos-T5モデルを使用して株価予測を試してみました。実際の精度も検証していないので、素晴らしいものできてるのがわからないけど、あくまでも参考用にしてください。株の専門家ではないので、よろしくお願いします。


# 参考資料

- [Chronos: Learning the Language of Time Series](https://arxiv.org/abs/2403.07815)
- [Hugging Face - amazon/chronos-t5-large](https://huggingface.co/amazon/chronos-t5-large)
- [GitHub - amazon-science/chronos-forecasting](https://github.com/amazon-science/chronos-forecasting)
-

# 最後に
今回も読んでくれて、ありがとうございました。記事も主にGPTが手伝って作成した文です。よろしくお願いします。
何か質問や改善点があれば、お気軽にコメントしてください。