Granger Causality(그레인저 인과관계)

2025. 4. 28. 12:40계량경제학

반응형

Granger Causality는 예측력에 기반한 인과 관계를 추론하는 모델입니다. 즉 진정한 인과관계를 나타내지는 않고 예측력을 기반으로 정의된 개념입니다. 술을 마시면 취한다와 같은 진정한 인과관계가 아니라, 어떤 시기에는 X 종목 주가가 오르면 Y종목 주가가 오르더라 하는것과 같이 완벽하게 증명되지는 않았지만 실증을 통해서 추론해볼 수 있는 인과관계를 살펴본다고 이해하시면 좋을 것 같습니다.

즉, X가 Y를 일으킨다라는 직접적으로 검증된 인과관계가 아닌 X가 Y를 예측하는데 도움이 되더라 하는 것을 살펴보는데 활용할 수 있는 모형이 Gragner Causality입니다. 또한 Granger Causality는 일반적으로 시계열 데이터에 많이 적용되며, 시간적 선후관계를 기반한 인과관계 분석이 핵심입니다.

그렇다면 Granger 인과관계가 있다는 것은 어떻게 알 수 있을까요? X 종목 주가와 Y종목 주가가 있다고 해보겠습니다. 만약 X 종목주가가 Y 종목 주가를 예측하는 힘을 갖고 있다면 Gragner 인과관계가 있다라고 (즉 X종목 주가가 Y종목 주가를 예측하는데 도움이 된다)라고 말할 수 있습니다.

제한된 모델(Restricted Model), 자기자신의 시계열 Y만 가진 모형

비제한된 모델 (Unrestricted Model) 자기자신의 시계열 Y뿐만 아니라 시계열 X의 과거값까지 포함한 모형

 

이 두 모형의 비교를 통해서 X가 실제 Y를 예측하는데 예측력을 가지는지 살펴봅니다. 이 예측력은 F-statstic을 활용하며 이 F통계값이 클수록 X의 예측력이 존재한다고 판단합니다.

 

Python으로 Granger 인과관계를 분석해보겠습니다.

삼성전자와 하이닉스주가를 가지고와서 두 주가간에 인과관계가 있는지 살펴보겠습니다.(24/3~25/3) 그래프를 보면 사실 그렇게 크게 인과관계가 보이진 않아보이긴 합니다.

## 데이터 로드 및 그래프 그리기

import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import grangercausalitytests
from statsmodels.tsa.api import VAR
from statsmodels.tsa.stattools import adfuller
import FinanceDataReader as fdr
import matplotlib.pyplot as plt

samsung = fdr.DataReader('005930','2024-03-01', '2025-03-31')
hynix = fdr.DataReader('000660','2024-03-01', '2025-03-31')

plt.figure(figsize=(12, 6))

plt.plot(samsung.index, samsung["Close"], label='Samsung', linewidth=2)
plt.plot(hynix.index, hynix["Close"], label='Hynix', linewidth=2)


plt.title('Samsung vs Hynix Stock Price', fontsize=14, pad=15)
plt.xlabel('Date', fontsize=12)
plt.ylabel('Price (KRW)', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, alpha=0.3)

plt.show()

Granger 인과관계를 분석하는데 있어, 시계열데이터의 정상성 검정을 수행하고 정상 시계열로의 변환이 필요합니다. 따라서 ADF test와 비정상성 발견시 차분을 통해 정상시계열로 변환하겠습니다.

ss =samsung["Close"].values
hn =hynix["Close"].values


result = adfuller(ss)
print(f'ADF Statistic: {result[0]:.4f}')
print(f'p-value: {result[1]:.4f}')

## ADF Statistic: -0.8846
## p-value: 0.7930


result = adfuller(hn)
print(f'ADF Statistic: {result[0]:.4f}')
print(f'p-value: {result[1]:.4f}')

## ADF Statistic: -2.5263
## p-value: 0.1092

## -> 모두 비정상성 시계열

## 차분
ss =samsung["Close"].diff().dropna().values
hn =hynix["Close"].diff().dropna().values

result = adfuller(ss)
print(f'ADF Statistic: {result[0]:.4f}')
print(f'p-value: {result[1]:.4f}')

## ADF Statistic: -14.6769
## p-value: 0.0000

result = adfuller(hn)
print(f'ADF Statistic: {result[0]:.4f}')
print(f'p-value: {result[1]:.4f}')

## ADF Statistic: -15.9058
## p-value: 0.0000

변환한 데이터에 대해서 granger causality 테스트를 수행해보겠습니다. 하이닉스 주가(Y)에 삼성전자 주가(X)가 그레인저 인과를 가지는지를 살펴보겠습니다. 결과적으로 모든시차에서 큰 p-value를 가짐으로써 Gragner Casuality는 없다, 즉 하이닉스 주가(Y)와 삼성전자 주가(X)의 그레인저 인과관계는 없다는 결과를 얻었습니다. 이는 위에서 저희가 그래프를 보고 판단한것처럼 주가의 이동방향이 전혀 일치하지 않아 인과관계가 없다고 나온것이 더 적절한것으로 보입니다.

data = pd.DataFrame({'X': ss, 'Y': hn})

# 그랜저 인과관계 검정
result = grangercausalitytests(data[['Y', 'X']], maxlag=5)

# 결과 출력
for lag, values in result.items():
    print(f"Lag {lag}:")
    print(f"  F-statistic: {values[0]['ssr_ftest'][0]}")
    print(f"  p-value: {values[0]['ssr_ftest'][1]}")
    
    
    """
    
    Lag 1:
  F-statistic: 1.1650199017513658
  p-value: 0.2814427681342322
Lag 2:
  F-statistic: 0.94185473836009
  p-value: 0.3912667369858226
Lag 3:
  F-statistic: 0.6696668827666719
  p-value: 0.5713770296998858
Lag 4:
  F-statistic: 0.98216179582994
  p-value: 0.41784459934626383
Lag 5:
  F-statistic: 0.8577931983839979
  p-value: 0.5101590090786791
  
  
  
  """

그렇다면 강제적으로 인과를 만들어서 한번 분석해보겠습니다. 

# 예시 데이터 생성
np.random.seed(42)
n = 100
X = np.random.normal(0, 1, n)
Y = np.zeros(n)

# Y가 X의 과거값에 의존하도록 설정
for t in range(2, n):
    Y[t] = 0.5 * Y[t-1] + 0.3 * X[t-1] + np.random.normal(0, 0.1)

# 그래프 스타일 설정
plt.figure(figsize=(12, 6))

# 플롯
plt.plot(X, label='X', linewidth=2)
plt.plot(Y, label='Y', linewidth=2)


# 그래프 꾸미기
plt.title('X vs Y', fontsize=14, pad=15)
plt.legend(fontsize=10)
plt.grid(True, alpha=0.3)

plt.show()

 그래프에서 보는것처럼 연관성이 있음을 확인할 수 있습니다.  그 다음 그레인저 인과 검정을 해보겠습니다.

 


data2 = pd.DataFrame({'X': X, 'Y': Y})

result = grangercausalitytests(data2[['Y', 'X']], maxlag=5)

# 결과 출력
for lag, values in result.items():
    print(f"Lag {lag}:")
    print(f"  F-statistic: {values[0]['ssr_ftest'][0]}")
    print(f"  p-value: {values[0]['ssr_ftest'][1]}")
    
    
    """
    Lag 1:
  F-statistic: 727.2872048527712
  p-value: 1.3758363455524521e-46
Lag 2:
  F-statistic: 364.279676900578
  p-value: 1.0086632132109107e-44
Lag 3:
  F-statistic: 243.2949661377557
  p-value: 4.786505167395823e-43
Lag 4:
  F-statistic: 177.5563044370544
  p-value: 5.61929332777676e-41
Lag 5:
  F-statistic: 132.54844892955944
  p-value: 2.518048917574036e-38
  """

전시차에서 유의하게 나와서 X가 Y에 그레인저 인과가 있다고 볼 수 있습니다.

granger causality 테스트를 하는 다른방식으로는 VAR모형을 이용하는 것이고, 이때는 시차까지 자동으로 선정할 수 있어 조금더 편리하게 테스트를 해볼 수 있습니다. granger causality 테스트를 수행할때 시차도 영향력을 가질 수 있어 이와 같이 기준을 가지고 시차 선정후 분석을 하면 좋습니다. 여기서는 AIC 기준으로 시차를 선택하고 그랜저 인과관계를 검정해보겠습니다.

# VAR 모델 적용
model = VAR(data2)
results = model.fit(maxlags=5, ic='aic')
print(results.summary())

"""
Results for equation Y
========================================================================
           coefficient       std. error           t-stat            prob
------------------------------------------------------------------------
const        -0.002389         0.009807           -0.244           0.808
L1.X          0.284448         0.010548           26.968           0.000
L1.Y          0.453945         0.031413           14.451           0.000
========================================================================
"""

# 그랜저 인과관계 검정
granger_results = results.test_causality('Y', 'X', kind='f')
print(granger_results.summary())


"""
Granger causality F-test. H_0: X does not Granger-cause Y. Conclusion: reject H_0 at 5% significance level.
========================================================
Test statistic Critical value p-value         df        
--------------------------------------------------------
         727.3          3.890   0.000 (1, np.int64(192))
--------------------------------------------------------

"""

AIC 기준 시차는 1차로 결정되었으며, 그랜저 인과관계를 가짐으로 나왔습니다.

반응형

'계량경제학' 카테고리의 다른 글

오차수정모형(Error Correction Model, ECM)  (0) 2025.05.02
공적분(Cointegration)  (2) 2025.04.30
VAR(Vector Autoregressive Models)  (1) 2024.06.17
시계열(Time series) > Break  (0) 2021.01.05
시계열(Time series) > Forecasting  (1) 2021.01.02