공적분(Cointegration)

2025. 4. 30. 06:25계량경제학

반응형

Cointegration은 경제학 및 금융 분야에서 시계열 데이터를 분석하는 데 있어 매우 중요한 개념입니다. 이는 개별적으로 불안정한 움직임을 보이는 두 개 이상의 시계열 변수가 장기적으로 안정적인 균형 관계를 유지하는 현상을 의미합니다.

좀 더 정리해보면 두 개 이상의 비정상 시계열이 장기적으로는 안정적인 관계를 가지는 것을 나타냅니다. 즉 각각의 시계열은 단위근을 가져 비정상 시계열이나 이들의 선형결합은 stationary인 특성을 보입니다.

두개의 비정상시계열 $X_t$, $Y_t$가 있다고 할 때, 아래와 같은 선형결합의 오차항이 Stationary가 되면 이는 공적분 관계가 있다고 말할 수 있습니다.

좀 더 직관적으로 설명하면, 유명한 예시가 있습니다.

술 취한 사람과 강아지인데, 술 취한 사람은 비틀거리며 예측 불가능하게 움직이고 그 옆을 따라가는 강아지도 역시 예측 불가능하게 이리저리 움직입니다. 다만 강아지는 주인을 따라가기 때문에 주인과의 거리가 너무 멀어지지 않도록 계속 조정합니다. 이처럼 개별적으로는 무작위 움직이지만 장기적으로는 서로 영향을 미치면 일정한 차이를 나타내는 이러한 예시가 공적분의 개념을 좀 더 직관적으로 보여줍니다.

실제 예시를 이용하여 Cointegration을 검증해보겠습니다. Cointegration을 검증해보기 위해서는 두계의 시계열 변수가 비정상성을 나타내야 합니다. 이를 검증하기 위해 ADF 테스를 수행합니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller, coint
from statsmodels.tsa.vector_ar.vecm import coint_johansen


## 데이터 준비

np.random.seed(42)
n = 1000

# 두 개의 랜덤워크 시계열 생성
x = np.cumsum(np.random.randn(n))
y = 2 * x + np.random.randn(n) * 0.1


## ADF test 준비
def adf_test(series):
    result = adfuller(series)
    print('ADF Statistic: %f' % result[0])
    print('p-value: %f' % result[1])
          
adf_test(x)
adf_test(y)

"""
ADF Statistic: -0.965952
p-value: 0.765479
ADF Statistic: -0.974789
p-value: 0.762348
"""

두가지 시계열 모두 비정상성을 나타냄을 확인했습니다.

그 다음에 공적분 관계가 있는지를 검정합니다. 공적분 관계를 검정하는데는 크게 두가지 방법이 있습니다. Engle-Granger 방법과 Johansen 검정입니다. Johansen 검정은 동시에 여러 변수의 공적분 관계를 파악할 수 있습니다. 간단하게 직관적으로 검정 방법에 대해서 정리해보겠습니다.

Engle-Granger 방법은 일반적인 OLS으로 선형모형을 Fit한다음 오차항이 정상성을 나타내는지를 파악하는 방식으로 공적분 관계를 검정합니다. 해당 방버은 두 개의 시계열간의 공적분 관계를 검정하는데 활용합니다.

Johansen 검정은 두 개 이상의 다변량 시계열에도 적용가능합니다. 이 방법은 VAR모형을 기반으로 하며, Trace와 Maximun Eigenvalue를 이용합니다. 간단하게 말하면 Trace value는 변수들의 관계가 우연이 아닌지, Maximum Eigenvalue는 X와 Y의 차이가 우연이 아닌지를 검증합니다.(좀더 상세한 설명은 https://medium.com/@cemalozturk/unveiling-cointegration-johansen-test-explained-with-python-examples-db8385219f1f 참조)

3개의 변수가 있다고 했을 때 요한슨 검정

1. Trace 검정:
   r=0: H0: 공적분 관계 없음
   r=1: H0: 최대 1개의 공적분 관계
   r=2: H0: 최대 2개의 공적분 관계

2. Max Eigenvalue 검정:
   r=0: H0: 0개 vs H1: 1개
   r=1: H0: 1개 vs H1: 2개
   r=2: H0: 2개 vs H1: 3개

실제 검정을 해보겠습니다.

# Engle-Granger Cointegration 검정
result_coint = coint(y, x)
print('\nCointegration Test Statistic:', result_coint)
print('Cointegration p-value:', result_coint[1])

"""
Cointegration p-value: 0.0
"""

# Johansen 검정
data = np.column_stack([x, y])
result = coint_johansen(data, det_order=0, k_ar_diff=1)
print("Trace Statistic:", result.lr1)
print("Critical Values (90%, 95%, 99%):", result.cvt)
print(result.evec)


trace_stat = result.lr1
critical_values = result.cvt
n_coint = 0
 
for i in range(len(trace_stat)):
    if trace_stat[i] > critical_values[i, 1]:  # 95% 유의수준
        n_coint += 1
    
print(f"\n추정된 공적분 관계의 개수: {n_coint}")

"""
추정된 공적분 관계의 개수: 1
"""


max_eigen_stat = result.lr2
n_coint_max = 0
 
for i in range(len(max_eigen_stat)):
    if max_eigen_stat[i] > critical_values[i, 1]:  # 95% 유의수준
        n_coint_max += 1
 
print(f"\nMaximum Eigenvalue 통계량 기반 추정된 공적분 관계의 개수: {n_coint_max}")

"""
Maximum Eigenvalue 통계량 기반 추정된 공적분 관계의 개수: 1
"""

Engle-Granger 방법, Johansen 검정 모두 X와 Y사이에 공적분 관계가 있음을 나타냈습니다.

반응형