見出し画像

Pythonで初めての株価分析



自己紹介ときっかけ

文系大卒、現職はWebデザインやエンジニアさんのサポート業務です。
Pythonに興味があるものの、何ができるのか、文系で学べるのか、仕事に活かせるのかと迷いましたが、とにかく始めてみました。
最初は「Python 3 エンジニア認定基礎試験」のテキストを3ヶ月ほど勉強して合格しました。
試験勉強で基礎文法は理解できましたが、独学でデータ分析や機械学習を学ぶのは難しかったので「Aidemyデータ分析講座」を受講しました。
株価分析を試みた内容を下記に記載します。

実行環境

Mac M1
Google Colaboratory

今回のゴール

JAL, ANA, 日経平均の株価の過去3年のデータを取得し、SARIMAXモデルで学習。1ヶ月後の株価を予想してグラフに出力しました。


分析の流れ

yfinanceのライブラリをインストールして、株価データを取得するための準備をします。

!pip install yfinance

使用するライブラリ をインポートします。

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.statespace.sarimax import SARIMAX
from datetime import timedelta
import itertools

yfinanceを使用して、JAL、ANA、日経平均の株価データを取得します。

# データの取得
start_date = pd.Timestamp.now() - pd.DateOffset(years=3)  # 3年前の日付
end_date = pd.Timestamp.now()  # 現在の日付
jal = yf.download("6625.T", start=start_date, end=end_date)
ana = yf.download("9202.T", start=start_date, end=end_date)
nikkei = yf.download("^N225", start=start_date, end=end_date)

取得したデータからAdjusted Close(調整終値)の列を取得して、それぞれの相対株価を計算します。

# Adjusted Close列を取得
jal_adj_close = jal['Adj Close']
ana_adj_close = ana['Adj Close']
nikkei_adj_close = nikkei['Adj Close']

# データを相対化する
jal_relative = jal_adj_close / jal_adj_close.iloc[0]
ana_relative = ana_adj_close / ana_adj_close.iloc[0]
nikkei_relative = nikkei_adj_close / nikkei_adj_close.iloc[0]

なぜ相対株価にしたのか?
そのままそれぞれの株価を表示したところ、下記グラフのようになり視覚的に比較しづらくなりました。同じスケールで比較するため、相対化して表示することにしました。

そのまま株価を表示

次に、SARIMAモデルのトレーニングと予測のための関数train_and_forecastを定義します。
また、パラメーターの範囲を定義するために、p、d、qの各パラメーターの値の組み合わせを生成します。

SARIMAモデルは、時系列データの予測に使われる方法です。過去のデータのパターンを分析し、そのパターンを使って未来のデータを予測します。基本的には、過去の値が将来の値にどのように影響するかを考えることで動作します。そして、時系列データのトレンドや季節性を考慮して予測を行います。

# SARIMAモデルのトレーニングと予測
def train_and_forecast(data, steps, order, seasonal_order):
    model = SARIMAX(data, order=order, seasonal_order=seasonal_order, enforce_stationarity=False, enforce_invertibility=False)
    results = model.fit()
    forecast = results.forecast(steps=steps)
    return forecast

# パラメーターの範囲を定義する
p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in pdq]

各企業(JAL、ANA)と日経平均株価の株価データを取得し、それぞれの相対的な株価の時間系列データを作成します。

# データの取得
jal_series = jal_relative.values
ana_series = ana_relative.values
nikkei_series = nikkei_relative.values

BICを最小化するパラメーターを見つけるために、SARIMAXモデルを構築します。パラメーターの組み合わせを試行して最適なパラメーターと、そのときのBIC値を表示します。

BIC(Bayesian Information Criterion)とは、統計モデルの良さを評価するための指標です。モデルの複雑さと適合度をバランスさせ、最適なモデルを選択する際に利用されます。BICが小さいほど、モデルの良さが高いとされます。

# BICで最適なパラメーターを見つける
bic_list = []
param_list = []
for param in pdq:
    for param_seasonal in seasonal_pdq:
        try:
            mod = SARIMAX(jal_series, order=param, seasonal_order=param_seasonal, enforce_stationarity=False, enforce_invertibility=False)
            results = mod.fit()
            bic = results.bic
            bic_list.append(bic)
            param_list.append((param, param_seasonal))
        except:
            continue

# 最小のBICとそのときのパラメーターを取得する
min_bic = min(bic_list)
best_params = param_list[bic_list.index(min_bic)]

print(f"Best BIC: {min_bic}")
print(f"Best Parameters: {best_params}")

最適なパラメーターを使用して、1ヶ月後までの株価を予測します。

# 1ヶ月後までの株価を相対的に予測
jal_forecast_relative = train_and_forecast(jal_series, steps=30, order=best_params[0], seasonal_order=best_params[1])
ana_forecast_relative = train_and_forecast(ana_series, steps=30, order=best_params[0], seasonal_order=best_params[1])
nikkei_forecast_relative = train_and_forecast(nikkei_series, steps=30, order=best_params[0], seasonal_order=best_params[1])

グラフを描画して、過去3年間の相対株価と予測を可視化します。

# グラフの作成
plt.figure(figsize=(12, 6))

# 過去3年間の相対株価をプロット
plt.plot(jal_relative.index, jal_relative, label='JAL', linestyle='-', color='red')
plt.plot(ana_relative.index, ana_relative, label='ANA', linestyle='-', color='blue')
plt.plot(nikkei_relative.index, nikkei_relative, label='Nikkei', linestyle='-', color='green')

# 予測した相対株価をプロット
jal_forecast_dates = pd.date_range(start=jal_relative.index[-1] + timedelta(days=1), periods=30, freq='D')
ana_forecast_dates = pd.date_range(start=ana_relative.index[-1] + timedelta(days=1), periods=30, freq='D')
nikkei_forecast_dates = pd.date_range(start=nikkei_relative.index[-1] + timedelta(days=1), periods=30, freq='D')

plt.plot(jal_forecast_dates, jal_forecast_relative, label='JAL (Forecast)', linestyle='--', color='#FFC0CB')
plt.plot(ana_forecast_dates, ana_forecast_relative, label='ANA (Forecast)', linestyle='--', color='#ADD8E6')
plt.plot(nikkei_forecast_dates, nikkei_forecast_relative, label='Nikkei (Forecast)', linestyle='--', color='#90EE90')

plt.xlabel('Date')
plt.ylabel('Relative Adjusted Close')
plt.title('Relative Stock Price Forecast (SARIMA)')
plt.legend()
plt.grid(True)
plt.show()

実行結果

Best BIC: -3211.041544730371
Best Parameters: ((1, 0, 0), (0, 0, 0, 12))
JAL, ANA, 日経平均の相対株価と1ヶ月後までの予測

課題と感想

  • 過去3年の株価データについて(素人の感想です)

    • 日経平均株価とANAの株は割と同じような動きに見えます。

    • JALの株は、2023年3月頃にグンと上がっていたので少し調べてみたところ、その時期に配当を再開していました。投資家からのポジティブな反応で、株価上昇につながったのかもしれないです。

  • 1ヶ月後までの予測について

    • 簡単に予測できるものでは無いと分かっていましたが、分析方法の1つを試せたのは良い経験になりました。

    • SARIMAモデル以外にも、時系列データの分析や予測を行うためのさまざまな手法があるようなので、データの特性や解析の目的に応じて、最適な手法を選択して試してみることが大事だと思いました。


この記事が気に入ったらサポートをしてみませんか?