ProphetによるApple株価予測と外部予測変数の影響

今回は、Prophetライブラリを使用して、Apple（AAPL）の株価予測を行い、さらに売上データを外部予測変数（リグレッサー）としてモデルに追加する方法を解説します。この記事では、具体的なコード例とともに、生成されたグラフの読み方についても詳しく説明します。

1. Prophetとは？
Prophetは、Facebookによって開発された時系列予測ツールです。強い季節性があり、複数のシーズンデータが存在する場合に特に効果を発揮します。欠損値や外れ値に強く、簡単に使えるのが特徴です。




2. Apple株価と売上データの取得
まず、Yahoo Finance（yfinance）を利用してAppleの株価データと財務データを取得し、売上を外部予測変数として使用します。月次の売上データを株価データと結合し、Prophetモデルに入力します。




3. Prophetモデルの構築と予測
Prophetモデルに売上データを追加することで、売上が株価に与える影響を考慮した予測が可能となります。予測結果はグラフとして可視化され、予測された株価トレンドと実際のデータが比較されます。

## コードの解説


```python
import yfinance as yf
import pandas as pd
from prophet import Prophet
import matplotlib.pyplot as plt
```
#### ライブラリのインポート:
yfinanceは、Yahoo Financeから株価や財務データを取得するためのライブラリです。
pandasは、データの操作や解析を行うための標準的なライブラリです。
Prophetは、Facebookによって開発された時系列予測のためのライブラリです。
matplotlibは、データを可視化するためのグラフ描画ライブラリです。

```python
# 1. 株価データと売上データの取得
ticker = "AAPL"
stock_data = yf.download(ticker, start="2020-01-01", end="2024-01-01")
financials = yf.Ticker(ticker).financials.T
```
#### 株価データと売上データの取得:
ticker = "AAPL"でAppleのティッカーシンボルを指定します。
yf.download()を使用して、2020年1月1日から2024年1月1日までの株価データを取得します。このデータには日付ごとの終値（調整後終値）などが含まれます。
financials = yf.Ticker(ticker).financials.Tで、Appleの四半期ごとの財務データ（売上など）を取得し、転置して行ごとに整理します。
```python
# 2. 売上データを四半期ごとに月次データにリサンプリングして補完
revenue_data = financials['Total Revenue'].resample('ME').ffill()
```
#### 売上データのリサンプリング:
売上データは四半期ごとに提供されるため、resample('ME')を使用して月末基準でリサンプリングし、ffill()で欠損している月のデータを直前の値で補完します。これにより、Prophetに適した連続的な月次データを生成します。
```python
# 3. 株価と売上を結合してデータフレームを作成
df = stock_data[['Adj Close']].rename(columns={'Adj Close': 'y'}).reset_index()
df['ds'] = df['Date']
df = df.drop(columns=['Date'])

# 売上データの長さを株価データに合わせるためにリサンプリング
# インデックスを合わせるためにデータを再結合
df = df.set_index('ds')
df = df.join(revenue_data)
df = df.reset_index()

# 欠損値を確認し、前方補完または後方補完を行う
df['Total Revenue'] = df['Total Revenue'].fillna(method='ffill').fillna(method='bfill')
```
#### データフレームの作成と結合:
Adj Close（調整後終値）のみを抽出し、Prophetで使用するために列名をyに変更し、日付をdsとして設定します。
売上データと株価データをインデックス（日付）に基づいて結合し、欠損値が存在する場合はffill()とbfill()を用いて前方または後方から補完します。
```python
# 4. Prophetモデルに外部予測変数を追加
model = Prophet()
model.add_regressor('Total Revenue')
model.fit(df)
```
### Prophetモデルの構築:
Prophet()でモデルを初期化します。
add_regressor('Total Revenue')で売上データを外部予測変数としてモデルに追加します。
fit(df)でデータを用いてモデルを訓練します。これにより、モデルは売上が株価に与える影響を考慮して予測を行います。
```python
# 5. 未来のデータフレームを作成して予測
future = model.make_future_dataframe(periods=365)
future = future.set_index('ds')
future = future.join(revenue_data)
future = future.reset_index()

# 欠損値を処理
future['Total Revenue'] = future['Total Revenue'].fillna(method='ffill').fillna(method='bfill')
```
#### 未来のデータフレーム作成と欠損値の処理:
make_future_dataframe(periods=365)で、1年（365日）先までの日付を含むデータフレームを作成します。
未来のデータフレームに売上データを結合し、欠損値が存在する場合は再度補完します。
```python
forecast = model.predict(future)

# 6. 予測結果の可視化
model.plot(forecast)
plt.show()
```
#### 予測と可視化:
predict(future)で未来の株価を予測し、その結果をforecastとして保存します。
plot(forecast)で予測結果をグラフとして可視化し、実際のデータと比較します。
```python
# 7. 成分のプロット
model.plot_components(forecast)
plt.show()
```
#### 成分プロット:
plot_components(forecast)で、予測モデルの各成分（トレンド、季節性、外部予測変数の影響など）を個別にプロットします。これにより、売上が株価予測にどのように影響を与えたかを視覚的に確認できます。

### 予測結果のプロット
#### グラフ1
過去の実際の株価データと将来の予測を示しています。このグラフには以下の要素が含まれています。

黒い点: 実際の株価データ（調整後終値）。
青い線: Prophetによって予測された株価のトレンドライン。
淡い青い帯: 予測の不確実性を示す信頼区間。信頼区間が広い場合、モデルの予測に対する不確実性が高いことを示しています。
![スクリーンショット 2024-09-01 1.07.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398994/3fb3b224-88aa-e3e3-fb11-2205d7d70bc5.png)

#### グラフ2
次に表示されるのは、予測モデルの成分を分解して示したグラフです。通常、以下の成分が表示されます。

トレンド（Trend）:
株価の全体的な上昇・下降の傾向を示しています。長期的なトレンドを視覚化することで、株価の基本的な動きを理解することができます。

季節性（Yearly weekly）:
株価の季節性パターンを示します。例えば、年末や特定の四半期に株価が上がる傾向があるかどうかを視覚化します。

外部予測変数の影響（Revenue）:
売上データが株価に与える影響を示します。このプロットを確認することで、売上の変動が株価予測にどのように影響しているかを把握できます。例えば、売上が増加する時期に株価が上昇するパターンが見られるかもしれません。
![スクリーンショット 2024-09-01 1.09.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398994/2b0b3918-a574-b488-24f4-6684acc502cd.png)

### コード全体
```python
import yfinance as yf
import pandas as pd
from prophet import Prophet
import matplotlib.pyplot as plt

# 1. 株価データと売上データの取得
ticker = "AAPL"
stock_data = yf.download(ticker, start="2020-01-01", end="2024-01-01")
financials = yf.Ticker(ticker).financials.T

# 2. 売上データを四半期ごとに月次データにリサンプリングして補完
# 'M'を'ME'に変更し、月末を基準にリサンプリング
revenue_data = financials['Total Revenue'].resample('ME').ffill()

# 3. 株価と売上を結合してデータフレームを作成
df = stock_data[['Adj Close']].rename(columns={'Adj Close': 'y'}).reset_index()
df['ds'] = df['Date']
df = df.drop(columns=['Date'])

# 売上データの長さを株価データに合わせるためにリサンプリング
# インデックスを合わせるためにデータを再結合
df = df.set_index('ds')
df = df.join(revenue_data)
df = df.reset_index()

# 欠損値を確認し、前方補完または後方補完を行う
df['Total Revenue'] = df['Total Revenue'].fillna(method='ffill').fillna(method='bfill')

# 4. Prophetモデルに外部予測変数を追加
model = Prophet()
model.add_regressor('Total Revenue')
model.fit(df)

# 5. 未来のデータフレームを作成して予測
future = model.make_future_dataframe(periods=365)
future = future.set_index('ds')
future = future.join(revenue_data)
future = future.reset_index()

# 欠損値を処理
future['Total Revenue'] = future['Total Revenue'].fillna(method='ffill').fillna(method='bfill')

forecast = model.predict(future)

# 6. 予測結果の可視化
model.plot(forecast)
plt.show()

# 7. 成分のプロット
model.plot_components(forecast)
plt.show()
```