見出し画像

株価のデータ分析!相関係数の可視化と時系列の変化

今回は、yahoo financeのAPIとpythonを使って株価の相関係数の計算方法をまとめてみました。相互相関関数としても表現していますのでぜひご参考にされてみてください。


はじめに

最近は金利やら色んなことで株価の乱高下が続いていますね。みなさんガチホールドできていますか?

以前、資産形成の記事も作成しました。

そんな中、最近、記事を見ているとSaaS/IT系の企業も順調に業績を伸ばしているように見えました。ただ、国内のグロース系はなかなか厳しい株価なのだろうなと思いながら。。

そんな中、以前からpythonで実装しようと思っていたのが、それぞれの株価などの相互相関関数の可視化でした。

trading viewなどでもできるのですが、自分の手元で色々工夫しながらできると良いなと思い、一念発起しました。


計算して得たいもの

今回は、特定の銘柄の株価、および、日経・TOPIXなどの代表的な指数、およびドル円などの為替との相関関係を時系列で表していきたいと思います。

これによって、どれくらいどの値が相関しているのか、を定量的にみてみたいと思います。

特に株価の相関係数は時事刻々変化する(背景となる要因が変化するため)と考えていますので、その変化にも着目したいと思います。

本来、株価の性質上(単位根過程)、微分値などで相関を計算した方がいいのだと思いますが今回は横着をしてシンプルに計算します。


計算のあらすじ

今回は以下のような内容で計算をしています

・株価のチャートおよび移動平均値を可視化する
・元データおよび移動平均値に対する時系列での相関係数を可視化する
・変化率に対する相関および時系列での相関係数の表示


コード

pythonでの実装になります。欠損値はdropしています。
3633はGMOペパボのtickerです。

import pandas_datareader as pdr
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import datetime

# ティッカーシンボルを指定
stock_index_tickers = ['3633.JP', '^NKX', '^TPX']
forex_tickers = ['JPYUSD=X', 'EURUSD=X']

# データ取得期間を指定
start_date = datetime.datetime(2023, 1, 1)
end_date = datetime.datetime(2024, 8, 9)
# end_date = datetime.datetime.now()

# Stooqを使用して株価・指数データを取得
df_stock_index = pd.DataFrame()
for ticker in stock_index_tickers:
    try:
        data = pdr.stooq.StooqDailyReader(ticker, start=start_date, end=end_date).read()
        df_stock_index[ticker] = data['Close']
    except Exception as e:
        print(f"Error fetching data for {ticker}: {e}")

# yfinanceを使用して為替データを取得
df_forex = yf.download(forex_tickers, start=start_date, end=end_date)['Close']

# データフレームを結合
df = pd.concat([df_stock_index, df_forex], axis=1)

# 欠損値がある行を除去
df = df.dropna()

# 20日移動平均を計算
window = 20
for column in df.columns:
    df[f'{column}_MA'] = df[column].rolling(window=window).mean()

# 各データセットの可視化関数
def plot_data(df, tickers, title_prefix):
    for ticker in tickers:
        plt.figure(figsize=(12, 6))
        plt.plot(df.index, df[ticker], label=f'{ticker} Close')
        plt.plot(df.index, df[f'{ticker}_MA'], label=f'{ticker} {window}-day MA')
        plt.title(f'{title_prefix} of {ticker}', fontsize=16)
        plt.xlabel('Date')
        plt.ylabel('Price')
        plt.legend()
        plt.grid(True)
        plt.tight_layout()
        plt.show()

# 株価・指数データの可視化
plot_data(df, stock_index_tickers, 'Closing Prices and Moving Average')

# 為替データの可視化
plot_data(df, forex_tickers, 'Exchange Rate and Moving Average')

# 20日ごとの相関係数を計算する関数
def rolling_correlation(df, col1, col2, window=window):
    return df[col1].rolling(window).corr(df[col2])

# すべてのペアの20日ごとの相関係数を計算(終値のみ)
correlation_data = {}
all_tickers = stock_index_tickers + forex_tickers
for i in range(len(all_tickers)):
    for j in range(i + 1, len(all_tickers)):
        col1, col2 = all_tickers[i], all_tickers[j]
        col_name = f'corr_{col1}_{col2}'
        correlation_data[col_name] = rolling_correlation(df, col1, col2)

# 相関係数のDataFrameを作成
df_correlation = pd.DataFrame(correlation_data)
df_correlation.index = df.index

# 移動平均に対する相関係数を計算
correlation_ma_data = {}
for i in range(len(all_tickers)):
    for j in range(i + 1, len(all_tickers)):
        col1, col2 = f'{all_tickers[i]}_MA', f'{all_tickers[j]}_MA'
        col_name = f'corr_MA_{all_tickers[i]}_{all_tickers[j]}'
        correlation_ma_data[col_name] = rolling_correlation(df, col1, col2)

# 移動平均の相関係数のDataFrameを作成
df_correlation_ma = pd.DataFrame(correlation_ma_data)
df_correlation_ma.index = df.index

# 各ペアの相関係数を別々のグラフで表示(終値と移動平均)
for col in df_correlation.columns:
    plt.figure(figsize=(12, 6))
    plt.plot(df_correlation.index, df_correlation[col], label='Close Price Correlation')
    plt.plot(df_correlation_ma.index, df_correlation_ma[f'corr_MA_{col.split("_")[1]}_{col.split("_")[2]}'], label='Moving Average Correlation')
    plt.title(f'{window}-day Rolling Correlation: {col}', fontsize=16)
    plt.xlabel('Date')
    plt.ylabel('Correlation Coefficient')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.show()

# リターンを計算(終値のみ)
df_returns = df[all_tickers].pct_change().dropna()

# seabornを使用してjoint plotを表示
sns.pairplot(df_returns)
plt.suptitle(f'Joint Plot of Returns for All Assets', y=1.02)
plt.show()

# 相関係数のヒートマップを表示(終値)
plt.figure(figsize=(12, 10))
sns.heatmap(df_returns.corr(), annot=True, cmap='coolwarm', vmin=-1, vmax=1, center=0)
plt.title('Correlation Heatmap of Returns (Close Prices)')
plt.tight_layout()
plt.show()

# 移動平均の相関係数のヒートマップを表示(修正済み)
plt.figure(figsize=(12, 10))
sns.heatmap(df_correlation_ma.T, annot=True, cmap='coolwarm', vmin=-1, vmax=1, center=0)  # データフレームを転置
plt.title('Correlation Heatmap of Moving Averages (Transposed)')
plt.xticks(rotation=45, ha='right')
plt.yticks(rotation=0)
plt.tight_layout()
plt.show()

結果の紹介(一部)

コードを実行するとさまざまな情報が出てきますが、代表的な内容を抜き出しておきます。

チャート

チャートは一般的な形で表示されます
日経平均は最近の下落が目立ちますね
ドル円チャートも一気に下落です

相関係数

日経平均とTOPIXの相関は常に高いです。移動平均値の相互相関を計算しているので少し見やすいと思います。

日経平均とドル円は比較的相関係数は高そうですが、かなり上下しています。

わかりづらいので、時系列の相関を表示してみます。先ほどは別々に表示していましたが、まとめて時系列での相関関係を可視化することにします。
少しゴタゴタしているグラフになりましたが、最近はTOPIX/日経平均とドル円の相関が高くなっていることがわかります。

変化率に対する相関

次に変化率(微分値)に対するヒストグラムの傾向を見ます。

ヒートマップ表示にすると以下のようになります。


まとめ

このように、株価と各種情報の時系列の相関関係の可視化をするコードを準備してみました。さまざまなところで活用できると思いますので使ってみてください。