다운로드
작성자: admin 작성일시: 2016-05-27 20:55:50 조회수: 1528 다운로드: 187
카테고리: 시계열 분석 태그목록:

공적분 모형

두 비정상 시계열을 선형조합(linear combination)하여 생성한 시계열의 integration 차수가 낮아지거나 정상상태가 되는 경우에 그 두 비정상 시계열이 공적분(cointegrate) 상태라고 한다. 이 때 이러한 선형 조합을 만드는 값을 공적분 벡터(cointegration vector)라고 한다.

$$ x_1 \sim I(d_1) $$$$ x_2 \sim I(d_2) $$

인 경우

공적분 벡터 $\alpha = [\alpha_1, \alpha_2]$에 대해 $$ \alpha_1 x_1 + \alpha_2 x_2 \sim I(b) $$

이고 $$ b < d_1, \;\;\; b < d_2 $$

공적분 시계열은 서로 상관관계를 가지지 않음에도 불구하고 장기적으로 같은 방향으로 움직이는 특성을 가진다. 마치 술취한 사람이 개를 끈에 묶어 다니는 경우에 사람과 개는 각자 아무런 상관관계가 없이 움직이지만 서로 너무 멀어지지는 않는 것과 유사하다. 공적분은 페어 트레이딩 (pair trading), 통계적 차익거래 (statistical arbitrage) 등의 매매전략에 응용 가능하다.

공적분의 예

다음과 같은 두 시계열은 모두 1차 Integrated 시계열 즉, 랜덤 워크 시계열이다.

$$ x_{1,t} = x_{1,t-1} + e_{1,t} $$
  
$$ x_{2,t} = 0.6 x_{1,t} + e_{2,t} $$
  

하지만 식에서 볼 수 있듯이 $y = 0.6 x_1 - x_2$는 정상 시계열이 된다.

In:
np.random.seed(1)
x1 = np.random.randn(500).cumsum()
x2 = 0.6 * x1 + np.random.randn(500)
plt.plot(x1, 'g')
plt.plot(x2, 'b')
plt.show()
In:
y = 0.6 * x1 - x2
plt.plot(y)
plt.show()

Engle-Granger’s Representation Theorem

두 시계열 $x_t \sim I(1)$, $y_t \sim I(1)$이 공적분인 경우, $y_t$를 종속 변수로, $x_t$를 독립 변수로 회귀 분석을 하여 만들어지는 잔차항 $z_t$에 대해 다음과 같은 식이 만족한다. (그 역도 성립) 이 식을 ECM(Error-Correction Model) 형식이라고 한다.

$$ \Delta y_t = \gamma_1 z_{t-1} + \sum_{i=1}^K \psi_{1,i} \Delta x_{t-i} + \sum_{i=1}^L \psi_{2,i} \Delta y_{t-i} + e_{1,t} $$

이 식에서 $\Delta x_t$, $\Delta y_t$는 항상 정상 시계열이고 이 식이 성립하려면 $z_t$과 $e_t$가 정상 시계열이어야 한다. 즉, 다음 두 가지를 확인하면 두 시계열이 공적분인지 알 수 있다.

  1. $x_t$로 $y_t$를 회귀 분석한 결과로 만들어지는 잔차 $z_t$가 정상 시계열인지를 확인
  2. 회귀 분석으로 ECM 형식의 잔차 $e_t$가 정상 시계열인지를 확인

정상 시계열인지를 정량적으로 확인하려면 Augmented Dickey-Fuller 검정을 사용하여 정상 상태를 확인하면 된다.

In:
resid1 = sm.OLS(x2, x1).fit().resid
print(sm.tsa.adfuller(resid1)[1])
0.0

ECM 모형의 정상 상태 확인은 statsmodels.tsa 서브패키지의 coint 명령을 사용하면된다.

coint 명령은 ECM 형식의 잔차에 대해 ADF 검정을 실시한다. 정상상태가 아닌 경우가 귀무가설이고 검정 통계량, p-value, critical value를 반환한다.

In:
sm.tsa.coint(x1, x2)
Out:
(-22.65828042744149, 0.0, array([-3.44349638, -2.86733786, -2.56985804]))

페어 트레이딩에의 응용

In:
import pandas.io.data as web
import datetime
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2013, 1, 27)
df1 = web.DataReader("005930.KS", 'yahoo', start, end)
df2 = web.DataReader("005935.KS", 'yahoo', start, end)
In:
df = pd.concat([df1.Close, df2.Close], axis=1).dropna()
df.columns = ["SecComm", "SecPref"]
df.plot()
plt.show()
In:
plt.plot(df.SecComm, df.SecPref, alpha=0.7)
plt.scatter(df.SecComm.values[-1:], df.SecPref.values[-1:], c="r", s=300)
plt.show()
In:
Y = df.SecComm
X = df.SecPref
X = sm.add_constant(X)
res = sm.OLS(Y, X).fit()
print(res.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                SecComm   R-squared:                       0.949
Model:                            OLS   Adj. R-squared:                  0.949
Method:                 Least Squares   F-statistic:                 1.421e+04
Date:                Fri, 27 May 2016   Prob (F-statistic):               0.00
Time:                        11:47:33   Log-Likelihood:                -9378.9
No. Observations:                 765   AIC:                         1.876e+04
Df Residuals:                     763   BIC:                         1.877e+04
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const      -3.748e+05   1.17e+04    -32.130      0.000   -3.98e+05   -3.52e+05
SecPref        2.1523      0.018    119.203      0.000       2.117       2.188
==============================================================================
Omnibus:                       20.892   Durbin-Watson:                   0.096
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               17.706
Skew:                          -0.301   Prob(JB):                     0.000143
Kurtosis:                       2.561   Cond. No.                     4.08e+06
==============================================================================

Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 4.08e+06. This might indicate that there are
strong multicollinearity or other numerical problems.
In:
sns.regplot(x="SecPref", y="SecComm", data=df)
plt.show()
In:
plt.plot(df.SecComm - 2.1523 * df.SecPref)
plt.show()
In:
sm.tsa.adfuller(res.resid)
Out:
(-4.4179236958217967,
 0.0002758868174581239,
 0,
 764,
 {'1%': -3.4389382294377469,
  '10%': -2.5687884250020558,
  '5%': -2.8653304587462944},
 16492.315423899745)
In:
sm.tsa.coint(df.SecComm, df.SecPref)
Out:
(-4.4179236958218944,
 0.0016653388999783348,
 array([-3.43892696, -2.86532549, -2.56878578]))

질문/덧글

감사합니다 rlaw*** 2018년 9월 8일 2:58 오후

안녕하십니까,

import pandas.io.data as web

import datetime

start = datetime.datetime(2010, 1, 1)

end = datetime.datetime(2013, 1, 27)

df1 = web.DataReader("005930.KS", 'yahoo', start, end)

df2 = web.DataReader("005935.KS", 'yahoo', start, end)

Yahoo Data를 사용하기 위해서는 위의 패키지 pandas.io대신에 pandas_datareader 및 fix_yahoo_finance 사용이 필요해 보입니다.


ImportError: The pandas.io.data module is moved to a separate package (pandas-datareader). After installing the pandas-datareader package (https://github.com/pydata/pandas-datareader), you can change the import ``from pandas.io import data, wb`` to ``from pandas_datareader import data, wb``.

import pandas_datareader.data as web

import fix_yahoo_finance as yf

import datetime

start = datetime.datetime(2010, 1, 1)

end = datetime.datetime(2013, 1, 27)

yf.pdr_override()

df1 = web.get_data_yahoo('005930.KS', start=start, end=end)

df2 = web.get_data_yahoo('005935.KS', start=start, end=end)

이후의, 코드는 동일하게 실행되었습니다.