Pythonで分析:ビットコインと関連銘柄の相関関係を可視化する
ビットコイン(BTC)の価格動向は、マイクロストラテジー(MSTR)や暗号資産マイニング企業などの関連銘柄に大きな影響を与えます。今回はPythonを用いて、BTCとこれら関連銘柄の相関を分析し、「直近の動きが過去の傾向からどう変化しているか」を可視化する方法を解説します。
1. 分析の目的
ビットコイン価格と関連銘柄(今回はBTC, MSTR, CLSK, CAN, CEPI)のデータを取得し、以下の2点を確認します。
- 両者の相関係数はどれくらいか
- 回帰分析を用いて、BTCの動きに対して銘柄がどれだけ反応しているか
- 直近15日間の動きが、過去の傾向(回帰直線)から乖離していないか
2. 使用したライブラリ
金融データの取得には yfinance、データの加工には pandas、可視化には matplotlib と numpy を使用しました。
3. 実装のポイント
① データの統合
複数の銘柄データを取得し、date をキーにして inner merge(内部結合)することで、すべての銘柄の価格が存在する日付のみを抽出しています。
result = pd.merge(btc_data, mstr_data, on='date', how='inner')
result_xyz = pd.merge(result, cepi_data, on='date', how='inner')
② 散布図と回帰直線の描画
np.polyfit を使って1次近似($y = ax + b$)を行い、回帰直線と決定係数($R^2$)を算出しています。これにより、BTCの価格変動が銘柄価格をどれだけ説明できているかを定量化します。
③ 直近データのハイライト(今回の工夫点)
ここがこの分析のユニークな点です。過去のデータ(15日前まで)を青色、直近15日間のデータを赤色で表示し分けることで、最新のトレンドが過去の相関から外れていないかを一目で把握できるようにしました。
# 過去のデータを青い丸でプロット
ax.plot(x[:-15], y[:-15], "o", label=stock1 + " " + stock2)
# 直近15日分を赤い丸でプロット(強調)
ax.scatter(x[-15:], y[-15:], marker='o', color='red')
4. 分析結果の例:CEPI vs BTC
- 相関係数(Corr): 1に近いほど、BTCと同じ方向に動いていることを示します。
- 回帰直線(y = ax + b): 傾き($a$)が大きければ、BTCの変動に対してより敏感に反応(ボラティリティが高い)することを意味します。
- 直近の赤色プロット: もし赤色の点が回帰直線から大きく上に外れていれば、その銘柄はBTCに対して一時的に「買われすぎ」、下に外れていれば「売られすぎ」という判断材料になります。
執筆時点の結果:BTCとの相関
執筆時点の結果:銘柄間の散布図
5. まとめ
今回のコードを使用することで、単なる価格の推移だけでなく、「ビットコインとの連動性が現在維持されているか、あるいは崩れ始めているか」を視覚的に捉えることができます。
特に直近のデータを色分けする手法は、急激な市場の変化を察知するのに非常に有効です。
補足:分析をカスタマイズするには
- 期間を変更する: start_ と end_ の日付を調整して、バブル期や暴落期の相関を比較してみてください。
- 対象銘柄を増やす: name_st に他のマイニング銘柄(MARA, RIOTなど)を追加して比較するのも面白いでしょう。
コード
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
# 例:2016年4月1日から2026年04月18日までを取得する場合
start_="2016-04-01"
end_="2026-04-18"
#データ描画関数
def get_data(name_st,start_,end_):
# name_st:ティッカーシンボル
tk = yf.Ticker(name_st)
tk_data = pd.DataFrame()
# 価格情報を取得
tk_data = tk.history(start=start_, end=end_, interval="1d", auto_adjust=False)
tk_data["date"] = pd.to_datetime(tk_data.index).date
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(tk_data["date"], tk_data["Close"], "o")
ax.set_title(name_st)
ax.set_xlabel('year')
ax.set_ylabel(name_st)
# 横軸の目盛りラベルを45度傾ける
ax.tick_params(axis='x', labelrotation=45)
ax.grid(True)
return tk_data
name_st = "BTC-USD"
btc_data = get_data(name_st,start_, end_)
# 例:2025年10月1日から2026年04月24日までを取得する場合
start_="2025-10-01"
end_="2026-04-24"
#以下それぞれnotebook上のひとつづつ表示
name_st = "BTC-USD"
btc_data = get_data(name_st,start_, end_)
name_st = "MSTR"
mstr_data = get_data(name_st,start_, end_)
name_st = "CLSK"
clsk_data = get_data(name_st,start_, end_)
name_st = "CAN"
can_data = get_data(name_st,start_, end_)
name_st = "CEPI"
cepi_data = get_data(name_st,start_, end_)
#データ統合
result = pd.merge(btc_data, mstr_data, on='date', how='inner')
result_xyz = pd.merge(result, cepi_data, on='date', how='inner')
def plot_corr(name1,name2,stock1,stock2):
x = result_xyz[name1]
y = result_xyz[name2]
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
corr = x.corr(y)
corr_ = "{:.3f}".format(corr)
ax.plot(x[:-15], y[:-15],"o", label =stock1+" "+stock2)
ax.scatter(x[-15:], y[-15:], marker='o', color='red')
ax.set_title(stock1 +' vs '+stock2+ str(corr_))
ax.set_xlabel(stock2)
ax.set_ylabel(stock1)
# 2. 最小二乗法で傾き(a)と切片(b)を計算
# np.polyfit(x, y, 次数) を使い、1次式として近似します
a, b = np.polyfit(x, y, 1)
# 3. 近似式の作成
y_pred = a * x + b
# 残差平方和 (RSS)
rss = np.sum((y - y_pred) ** 2)
# 全平方和 (TSS)
tss = np.sum((y - np.mean(y)) ** 2)
# R^2
r2 = 1 - (rss / tss)
ax.plot(x, y_pred, color='red', label=f'Line: y={a:.5f}x+{b:.2f}' +"\n " + " R^2= " + f"{r2:.3f}") # 回帰直線
ax.legend()
ax.grid(True)
#関数を呼び出してプロット
name1 = "Close_x"
name2 = "Close"
stock1 = "cepi"
stock2 = "BTC"
plot_corr(name1,name2,stock1,stock2)
#以下同様
。。。





