0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Johansen検定から始めるVECM入門:時系列の長期関係をPythonで分析

Posted at

user:

VECM(ベクトル誤差修正モデル)について、詳しく教えてください。

assistant:

もちろんです。**VECM(Vector Error Correction Model、ベクトル誤差修正モデル)は、複数の時系列変数が共に共通のトレンド(共通の長期的関係)を持つときに、その短期的な変動と長期的な均衡関係を同時に捉えるモデルです。とくに共分散定常ではない(=単位根を持つ)けれども、共に動く系列(共積性:cointegration)**に適しています。


🔁 なぜVECMが必要なのか?

1. 単位根過程(I(1)過程)

多くのマクロ経済時系列(GDP、物価、為替など)は**非定常(単位根を持つ)**であり、通常のVAR(ベクトル自己回帰モデル)では分析に適しません。

2. 共積性(Cointegration)

2つ以上の非定常系列でも、特定の線形結合が定常である場合があります。

  • 例:為替レートと輸出入価格
  • このような関係を「共積関係」と呼び、長期的な均衡関係を表します。

📘 VECMの数式(2変数の例)

VAR(p)モデルを差分形にし、共積関係を取り入れると次のようになります:

$$
\Delta \mathbf{y}t = \Pi \mathbf{y}{t-1} + \sum_{i=1}^{p-1} \Gamma_i \Delta \mathbf{y}_{t-i} + \varepsilon_t
$$

  • $\mathbf{y}_t$:k次元のI(1)系列ベクトル
  • $\Delta \mathbf{y}_t = \mathbf{y}t - \mathbf{y}{t-1}$:1階差分
  • $\Pi$:長期関係(誤差修正項)
  • $\Gamma_i$:短期動学
  • $\varepsilon_t$:ホワイトノイズ

🎯 重要:$\Pi$の役割

  • $\Pi$がランクr(0 < r < k)のとき、r個の共積ベクトルが存在する

  • $\Pi = \alpha \beta^\top$ と分解

    • $\beta$:共積ベクトル(長期均衡関係を定義)
    • $\alpha$:誤差修正項への調整速度(どれだけ早く均衡に戻るか)

🧠 直感的なイメージ

  • 例えば、2国の通貨(円とドル)の為替レートと金利が長期的に連動しているとします。
  • しかし短期的にはバラバラに動く。
  • VECMでは「短期的なズレ(=誤差)を、長期的な関係に戻す力」を数式として表現できます。

🔍 VECMを使う前提とステップ

1. 各変数が**I(1)**であること(ADF検定などで確認)

2. 変数間に共積関係があること(Johansen検定など)

3. モデル推定(VECMとしてVARモデルの形で推定)

4. 結果解釈(係数・誤差修正項・インパルス応答など)


✅ Pythonでの実装(statsmodels.tsa.vector_ar.vecm

from statsmodels.tsa.vector_ar.vecm import coint_johansen, VECM
import pandas as pd

# 1. データ読み込み(複数の時系列を列に持つDataFrame)
df = pd.read_csv('data.csv', index_col=0, parse_dates=True)

# 2. Johansen検定で共積数を確認
jres = coint_johansen(df, det_order=0, k_ar_diff=2)
print(jres.lr1)  # トレース統計量
print(jres.cvt)  # 臨界値

# 3. VECMモデルの推定
vecm_model = VECM(df, k_ar_diff=2, coint_rank=1)
vecm_res = vecm_model.fit()
print(vecm_res.summary())

📝 まとめ

観点 VECMの意味
モデル対象 I(1)系列(非定常)で共積関係がある複数系列
モデル形式 差分式 + 誤差修正項(長期均衡への調整)
特徴 短期的な変動と長期的な関係を同時にモデリング可能
主な分析内容 共積ベクトル・調整係数・因果関係・インパルス応答など

もっと具体的に見たいテーマ(インパルス応答、Granger因果性、共積ベクトルの意味など)があれば、それも丁寧に解説しますね。どこを深掘りしたいですか?

user:

ありがとうございます。上記のコードの動作を見たいので、'data.csv' を読み込む形でも悪くはないのですが、でpた

assistant:

どういたしまして!😊
続きを書こうとしてくださったようですね(「でpた」→「データ」?)——おそらく「data.csv を使ってもいいけど、最初からサンプルデータを使って動作確認したい」みたいな意図かなと思いました。

それなら、サンプルの時系列データを Python内で直接生成して VECM を動かすコード を以下にご紹介します。これで data.csv を別に用意しなくても、コード単体で動作確認できます。


✅ VECM をサンプルデータで実行(Pythonコード)

import numpy as np
import pandas as pd
from statsmodels.tsa.vector_ar.vecm import coint_johansen, VECM
import matplotlib.pyplot as plt

# シード値で再現可能に
np.random.seed(42)

# サンプルの共積時系列データ生成
n_obs = 200
t = np.arange(n_obs)
# 共通のトレンド成分
trend = np.cumsum(np.random.normal(0, 1, n_obs))
# 系列1と2はトレンドに基づく(共積関係あり)
y1 = trend + np.random.normal(0, 1, n_obs)
y2 = 2 * trend + np.random.normal(0, 1, n_obs)
# 系列3はランダムウォークで共積関係なし
y3 = np.cumsum(np.random.normal(0, 1, n_obs))

df = pd.DataFrame({'y1': y1, 'y2': y2, 'y3': y3})

# 1. Johansen検定で共積関係の有無をチェック
jres = coint_johansen(df, det_order=0, k_ar_diff=2)
print("Johansen Trace Statistics:", jres.lr1)
print("Critical Values (95%):", jres.cvt[:, 1])

# 2. 共積ランクを 1 として VECM モデルを推定
vecm_model = VECM(df, k_ar_diff=2, coint_rank=1)
vecm_res = vecm_model.fit()

# 3. 結果表示
print(vecm_res.summary())

# 4. 誤差修正項のプロット
ec_terms = vecm_res.resid
ec_terms.plot(title="Error Correction Terms")
plt.xlabel("Time")
plt.ylabel("Residuals")
plt.show()

📌 実行すると何が起きる?

  • y1y2共通のトレンドに基づく → Johansen検定で共積関係ありと検出
  • y3 は関係のないノイズ系列 → 共積しない(Trace検定の数値が低い)
  • VECMy1, y2, y3 を使って誤差修正モデルを推定
  • .summary()共積ベクトル(長期均衡関係)や調整係数(どの程度その関係に戻るか)などを確認

必要ならこのコードを Streamlit アプリ化したり、Excel から読み取る形に変更することもできます!

次に知りたいことはありますか?
たとえば:

  • VECM のパラメータ解釈
  • インパルス応答分析
  • Granger因果性の検定方法
  • 結果を図解・可視化する方法 など…

なんでも言ってくださいね!

user:

タイポしたにも関わらず、意図を汲み取ってくれてありがとうございます!教えていただいたコードの実行結果は次のようになりました。

Johansen Trace Statistics: [62.95564685 14.3512375   5.23350978]
Critical Values (95%): [29.7961 15.4943  3.8415]
Det. terms outside the coint. relation & lagged endog. parameters for equation y1
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
L1.y1         -0.0294      0.142     -0.207      0.836      -0.308       0.249
L1.y2         -0.0912      0.077     -1.182      0.237      -0.242       0.060
L1.y3         -0.0065      0.106     -0.061      0.951      -0.215       0.202
L2.y1         -0.0003      0.100     -0.003      0.997      -0.196       0.196
L2.y2         -0.0232      0.060     -0.388      0.698      -0.141       0.094
L2.y3         -0.1212      0.106     -1.144      0.253      -0.329       0.087
Det. terms outside the coint. relation & lagged endog. parameters for equation y2
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
L1.y1          0.1511      0.196      0.771      0.441      -0.233       0.536
L1.y2         -0.3185      0.106     -2.992      0.003      -0.527      -0.110
L1.y3         -0.0469      0.147     -0.319      0.750      -0.335       0.241
L2.y1          0.1744      0.138      1.263      0.207      -0.096       0.445
L2.y2         -0.1644      0.083     -1.988      0.047      -0.327      -0.002
L2.y3         -0.3206      0.146     -2.191      0.028      -0.607      -0.034
Det. terms outside the coint. relation & lagged endog. parameters for equation y3
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
L1.y1         -0.1429      0.095     -1.501      0.133      -0.330       0.044
L1.y2          0.0755      0.052      1.460      0.144      -0.026       0.177
L1.y3         -0.0527      0.071     -0.739      0.460      -0.193       0.087
L2.y1         -0.0615      0.067     -0.917      0.359      -0.193       0.070
L2.y2          0.0670      0.040      1.668      0.095      -0.012       0.146
L2.y3          0.0339      0.071      0.477      0.633      -0.105       0.173
                 Loading coefficients (alpha) for equation y1                 
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
ec1           -0.7104      0.170     -4.170      0.000      -1.044      -0.377
                 Loading coefficients (alpha) for equation y2                 
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
ec1            0.4020      0.235      1.709      0.087      -0.059       0.863
                 Loading coefficients (alpha) for equation y3                 
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
ec1            0.1248      0.114      1.093      0.274      -0.099       0.349
          Cointegration relations for loading-coefficients-column 1           
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
beta.1         1.0000          0          0      0.000       1.000       1.000
beta.2        -0.4942      0.005   -102.429      0.000      -0.504      -0.485
beta.3        -0.0107      0.022     -0.481      0.631      -0.054       0.033
==============================================================================
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipython-input-8-3212719816.py in <cell line: 0>()
     34 # 4. 誤差修正項のプロット
     35 ec_terms = vecm_res.resid
---> 36 ec_terms.plot(title="Error Correction Terms")
     37 plt.xlabel("Time")
     38 plt.ylabel("Residuals")

AttributeError: 'numpy.ndarray' object has no attribute 'plot'

assistant:

とっても丁寧に実行結果を見せてくれてありがとう!✨
また、ec_terms.plot(...) でエラーが出たのは、vecm_res.residnumpy.ndarray だからです。
.plot()pandas.DataFrameSeries にしか使えないので、そのままだとエラーになります。


✅ 修正方法

誤差修正項を pandas.DataFrame に変換してから .plot() しましょう!

# 4. 誤差修正項のプロット(修正済み)
ec_terms = pd.DataFrame(vecm_res.resid, columns=df.columns)
ec_terms.plot(title="Error Correction Terms")
plt.xlabel("Time")
plt.ylabel("Residuals")
plt.tight_layout()
plt.show()

💡 もう少し補足すると…

vecm_res.resid とは?

これは、モデルで予測される誤差項(≒「実際との差」)です。ここでは各系列(y1, y2, y3)の短期的なずれの大きさを表しています。

だから plot すると?

「短期的に均衡関係からどれだけ離れてるか(誤差)」が時間とともにどう推移しているかが分かります。つまり、VECM がどのくらいうまく誤差修正できているかを見るヒントになります。


もしさらに深く見たいなら…

たとえば、次のような可視化や分析もできます:

  • 📈 共積ベクトルの図示(y1, y2の長期均衡関係)
  • 🔁 インパルス応答分析(ショックがどう波及するか)
  • 🔍 Granger因果性検定(どの変数が他の変数を予測するか)

もし興味があれば、どれでも一緒にやりましょうね😊
どこを深掘りしてみたい?

user:

ありがとうございます。とりあえず次の結果の意味を解説していただけますか?

Johansen Trace Statistics: [62.95564685 14.3512375   5.23350978]
Critical Values (95%): [29.7961 15.4943  3.8415]

assistant:

もちろんです!💡
この Johansen検定の結果は、**共積関係(長期均衡関係)がいくつあるか(=共積ランク)**を決定するための非常に重要なステップです。


🔍 検定結果の読み方

Johansen Trace Statistics: [62.96, 14.35, 5.23]
Critical Values (95%):       [29.80, 15.49, 3.84]

これは以下のように対応しています:

検定の仮説 Trace統計量 95% 臨界値 判定(有意)
r = 0(共積ランクは0) 62.96 29.80 ✅ 帰無仮説を棄却 → r ≥ 1
r ≤ 1(共積ランクは高々1) 14.35 15.49 ❌ 帰無仮説を棄却できない → r = 1
r ≤ 2(共積ランクは高々2) 5.23 3.84 ✅ 帰無仮説を棄却 → r ≥ 3?(でもこの行は無視してOK)

✅ つまりどういうこと?

  • 最初の行:共積関係が存在しない(r = 0)という仮説を棄却できます → 共積関係がある!
  • 次の行:共積関係は高々1つ(r ≤ 1)という仮説は棄却できない共積関係はちょうど1つ

👉 したがって、共積ランクは r = 1
→ あなたの系列(y1, y2, y3)の中に、**1本の共積関係(長期的均衡を保つ線形関係)**があると判断されます。


📘 背景(ちょっとだけ理論)

Johansen検定は、次のような帰無仮説の系列を順番にテストします:

  1. r = 0(共積関係がない)
  2. r ≤ 1(1個以下しかない)
  3. r ≤ 2(2個以下しかない)
    ...

このとき、初めて帰無仮説を棄却できなくなった時点のrが **「真の共積ランク」**とされます。


💬 まとめ

❗️この検定結果の意味:

あなたのデータ(y1, y2, y3)には 共積関係が1本存在する
つまり、y1, y2, y3のある線形結合(例:y1 − 0.5×y2 など)が定常で、長期的に釣り合っている関係がある、ということです。


これを使って、VECMでは:

  • beta → その長期均衡関係(係数ベクトル)
  • alpha → そのズレをどれだけの速さで修正するか(調整係数)

が推定されるわけです。


よかったら、推定された beta(共積ベクトル)の中身や、alpha の意味も詳しく解説しますよ!興味ありますか?💡

user:

ありがとうございました。今回の内容をブログに残したいので、タイトル案をいくつか提案していただけますか?

assistant:

もちろんです!今回の内容は「VECM(ベクトル誤差修正モデル)の基本とPythonによる実行・解釈」が中心なので、それを踏まえて以下のようなブログタイトル案を提案します:


🎯 理論 + 実践をバランスよく伝えるタイトル

  1. 「共積関係を読み解く:VECMモデルをPythonで実装・可視化してみた」
  2. 「Johansen検定から始めるVECM入門:時系列の長期関係をPythonで分析」
  3. 「ベクトル誤差修正モデル(VECM)をやさしく解説&Pythonでサンプル実行」
  4. 「非定常だけどつながってる?VECMで共積関係を探る時系列モデリング」

🧠 データ分析・時系列解析に寄せたタイトル

  1. 「時系列の長期的なつながりを捉える:PythonでVECMモデルを試す」
  2. 「単位根×共積性=VECM:非定常時系列の分析と可視化」
  3. 「Pythonでできる共積性の検定とモデリング:Johansen → VECM 実践記」

😎 少しキャッチーなトーンも含めて

  1. 「ただのランダムウォークじゃない!Pythonで探る時系列の裏のつながり」
  2. 「y1とy2の共犯関係!? VECMで暴く時系列の隠れた均衡」
  3. 「Pythonで時系列の“縁”を検出する:共積性とVECMを学ぶ」

どれかピンとくるものはありましたか?
気に入ったテイストがあれば、もう少しバリエーションを増やすこともできますよ!

user:

「Johansen検定から始めるVECM入門:時系列の長期関係をPythonで分析」でいきたいと思います。このタイトルに沿って、今回の内容を改めて詳しく説明してください。

assistant:

了解しました!
以下はブログ記事向けに構成した「Johansen検定から始めるVECM入門:時系列の長期関係をPythonで分析」というタイトルに沿った詳しい解説です。


📊 Johansen検定から始めるVECM入門:時系列の長期関係をPythonで分析

はじめに

時系列データを扱うとき、「非定常な変数だけど、長期的には一緒に動く」という現象に出会うことがあります。たとえば為替と物価、株価と金利など。
このような “共に動く関係”=共積関係(Cointegration) を分析するための強力なツールが VECM(ベクトル誤差修正モデル) です。

この記事では、以下の内容を扱います:

  • 共積関係とVECMの基本
  • Johansen検定による共積数の特定
  • Pythonでの実装と結果の解釈
  • 誤差修正項の可視化

🔁 VECMとは? — 共積関係のある非定常データを扱うモデル

単位根と非定常

多くの経済データは非定常(I(1))、つまりランダムウォークのようにトレンドを持ちます。こうしたデータをそのまま扱うと、誤った回帰や解釈をしてしまうリスクがあります。

共積関係(Cointegration)

非定常な時系列でも、一定の線形結合が定常(I(0))になることがある
たとえば、

$$
y_1(t) - 0.5 \cdot y_2(t) \approx \text{定常}
$$

このような関係を 共積関係 と呼びます。


🧠 VECM(Vector Error Correction Model)の構造

VECMは、次のように短期的な差分の動きと、長期的な均衡関係(誤差修正項)を同時に捉えるモデルです:

$$
\Delta y_t = \alpha \beta^\top y_{t-1} + \sum \Gamma_i \Delta y_{t-i} + \varepsilon_t
$$

  • $\Delta y_t$:差分(短期変動)
  • $\beta^\top y_{t-1}$:共積関係(長期均衡項)
  • $\alpha$:均衡からのズレをどれだけ修正するか(調整係数)

🧪 Johansen検定:共積ランクを調べる

Johansen Trace検定は、時系列にいくつの共積関係があるか(共積ランク)を決定する方法です。

今回の検定結果:

Johansen Trace Statistics: [62.96, 14.35, 5.23]
Critical Values (95%):     [29.80, 15.49, 3.84]

解釈:

仮説 Trace統計量 95% 臨界値 判定
r = 0(共積なし) 62.96 29.80 ✅ 棄却(共積あり)
r ≤ 1 14.35 15.49 ❌ 棄却できない
r ≤ 2 5.23 3.84 ✅ 棄却(ただし無視可)

よって、共積ランクは1と判断します。


🛠 Pythonによる実装(完全自作データで)

import numpy as np
import pandas as pd
from statsmodels.tsa.vector_ar.vecm import coint_johansen, VECM
import matplotlib.pyplot as plt

np.random.seed(42)
n_obs = 200
trend = np.cumsum(np.random.normal(0, 1, n_obs))

# 共積関係あり(y1とy2)
y1 = trend + np.random.normal(0, 1, n_obs)
y2 = 2 * trend + np.random.normal(0, 1, n_obs)
# 共積関係なし(y3)
y3 = np.cumsum(np.random.normal(0, 1, n_obs))

df = pd.DataFrame({'y1': y1, 'y2': y2, 'y3': y3})

Johansen検定の実行

jres = coint_johansen(df, det_order=0, k_ar_diff=2)
print(jres.lr1)
print(jres.cvt[:, 1])  # 95%の臨界値

🧩 VECMモデルの推定と結果解釈

vecm_model = VECM(df, k_ar_diff=2, coint_rank=1)
vecm_res = vecm_model.fit()
print(vecm_res.summary())

注目ポイント①:誤差修正項の調整係数(alpha)

                 coef    std err      z      P>|z|
ec1           -0.7104    0.170    -4.17    0.000

これは y1 の変化が、長期均衡からのズレ(=ec1)を70%のスピードで修正していることを意味します。
符号が負 → 均衡から上にズレると下がるように調整される、という動き。

注目ポイント②:共積ベクトル(beta)

beta.1 = 1.0000
beta.2 = -0.4942
beta.3 = -0.0107

これは次のような長期関係を示しています:

$$
y_1 - 0.4942 \cdot y_2 - 0.0107 \cdot y_3 = 定常
$$

→ つまり、y1とy2の間に強い線形関係があることが分かります。


📈 誤差修正項の可視化

ec_terms = pd.DataFrame(vecm_res.resid, columns=df.columns)
ec_terms.plot(title="Error Correction Terms")
plt.xlabel("Time")
plt.ylabel("Residuals")
plt.tight_layout()
plt.show()

このプロットでは、各系列が長期均衡からどのくらい乖離していたかが時間軸で見られます。


おわりに

VECMは、短期変動と長期均衡の両方を同時に捉える強力なモデリング手法です。
Johansen検定を通じて共積関係を特定し、その後VECMで調整の力学を把握することで、ただの「非定常なノイズ」に見える時系列の中に、実は持続的な均衡関係があることを発見できます。


🔗 補足・関連記事リンク(例)


必要に応じて、次は インパルス応答分析因果性検定も加えるとさらに面白くなります!

記事化する際、マークダウン形式・HTML形式などでの出力もできますので、ご希望あればお知らせくださいね。

user:

ありがとうございます!お疲れ様でした!

assistant:

こちらこそ、ありがとうございました!お疲れさまでした ☕😄
またいつでも気軽にご相談ください。よいブログ執筆を!📝✨

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?