2020. 12. 27. 20:06ㆍ계량경제학
이전 포스팅(direction-f.tistory.com/68)에 이어서, 시계열 모형을 결정하기 위한 Process에 대해서 정리해보도록 하겠습니다.
이전 포스팅에서 원본 시계열 데이터의 비정상성을 차분을 통해서 정상성을 가진 시계열 데이터로 변환했으며, ACF&PACF 그래프를 활용하여, 대략적으로 모형의 차수를 결정해보았습니다.
이번 포스팅에서는 모형을 추정하고, 진단을 통해서 우리가 가지고 있는 데이터의 타당한 모형을 구축해보겠습니다.
[Estimation/Diagnosis]
먼저 일차적으로 차분한 데이터를 활용하여 ARMA(1,1)과 ARMA(5,5)를 Fitting 해보겠습니다. LLR Test 결과를 보면 ARMA(5,5)일 때 Likelihood가 더 높음을 알 수 있습니다.
model_ret_ar_1_ma_1 = ARMA(df["diff_Close"][1:], order=(1,1))
results_ret_ar_1_ma_1 = model_ret_ar_1_ma_1.fit(maxiter=100)
results_ret_ar_1_ma_1.summary()
'''
====================================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------------
const 0.4064 0.150 2.707 0.007 0.112 0.701
ar.L1.diff_Close 0.7282 0.086 8.445 0.000 0.559 0.897
ma.L1.diff_Close -0.7722 0.080 -9.657 0.000 -0.929 -0.615
'''
## Higher lag
model_ret_ar_5_ma_5 = ARMA(df["diff_Close"][1:], order=(5,5))
results_ret_ar_5_ma_5 = model_ret_ar_5_ma_5.fit(maxiter=100)
results_ret_ar_5_ma_5.summary()
'''
====================================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------------
const 0.4075 0.149 2.738 0.006 0.116 0.699
ar.L1.diff_Close -0.5400 0.097 -5.572 0.000 -0.730 -0.350
ar.L2.diff_Close -0.1138 0.121 -0.941 0.347 -0.351 0.123
ar.L3.diff_Close -0.2997 0.113 -2.664 0.008 -0.520 -0.079
ar.L4.diff_Close -0.0207 0.125 -0.166 0.869 -0.266 0.224
ar.L5.diff_Close 0.6850 0.076 8.972 0.000 0.535 0.835
ma.L1.diff_Close 0.4909 0.093 5.267 0.000 0.308 0.674
ma.L2.diff_Close 0.0547 0.111 0.492 0.623 -0.163 0.273
ma.L3.diff_Close 0.2753 0.106 2.589 0.010 0.067 0.484
ma.L4.diff_Close -0.0156 0.114 -0.136 0.891 -0.240 0.209
ma.L5.diff_Close -0.7324 0.070 -10.497 0.000 -0.869 -0.596
'''
## LLR Test
LLR_test(results_ret_ar_1_ma_1 ,results_ret_ar_5_ma_5, DF=8) ## 0.003
우리가 대략적으로 우리가 활용할 ARMA의 차수 p,q를 선택하긴 했지만 우리 데이터에 맞는 모델을 찾는 것은 쉽지 많은 일입니다. 따라서 일반적으로 여러 차수들의 조합을 하나씩 해보면서 Likelihood나 AIC를 활용하여 차수를 결정합니다.
##Finding Best Model
import itertools
p = range(0,7)
q = range(0,6)
pq = list(itertools.product(p,q))
pq
'''
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5),
(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
(3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
(4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5),
(5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5),
(6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5)]
'''
dict_model ={}
for i in pq:
try:
model = ARMA(df["diff_Close"][1:], order=(i))
print(i)
model_fit = model.fit( maxiter = 50)
# print("\n ARMA:", i, "\tLL = ", model_fit.llf, "\tAIC = ", model_fit.aic)
dict_model[i]=[model_fit.llf, model_fit.aic]
except:
print("error lag:",i)
information=pd.DataFrame.from_dict(dict_model, orient ="index", columns =["llf", "AIC"])
information
'''
llf AIC
(0, 0) -27880.760013 55765.520025
(0, 1) -27874.378058 55754.756116
(0, 2) -27868.459873 55744.919747
(0, 3) -27868.455678 55746.911357
(0, 4) -27867.999625 55747.999250
(0, 5) -27863.033780 55740.067560
(1, 0) -27874.916724 55755.833448
(1, 1) -27866.783239 55741.566478
(1, 2) -27866.779053 55743.558106
(2, 0) -27868.602791 55745.205582
(2, 1) -27868.600941 55747.201881
(2, 2) -27866.477850 55744.955701
(3, 0) -27868.601724 55747.203449
(3, 1) -27865.550586 55743.101171
(3, 2) -27865.176116 55744.352231
(4, 0) -27868.369223 55748.738446
(4, 1) -27864.280319 55742.560638
(4, 2) -27862.774859 55741.549719
(4, 3) -27860.780319 55739.560638
(4, 4) -27860.981231 55741.962461
(5, 0) -27863.682973 55741.365947
(5, 1) -27861.723647 55739.447294
(5, 2) -27861.648074 55741.296148
(5, 3) -27861.500173 55743.000345
(5, 4) -27861.439065 55744.878130
(5, 5) -27855.184151 55734.368302
(6, 0) -27861.707017 55739.414034
(6, 1) -27861.594288 55741.188577
(6, 2) -27861.587400 55743.174800
(6, 3) -27859.896809 55741.793619
(6, 4) -27859.300464 55742.600929
(6, 5) -27860.317466 55746.634932
'''
information.loc[information["llf"] == information["llf"].max()]
'''
llf AIC
(5, 5) -27855.184151 55734.368302
'''
information.loc[information["AIC"] == information["AIC"].min()]
'''
llf AIC
(5, 5) -27855.184151 55734.368302
'''
해당 결과를 보면, (p,q)가 (5,5)일때 가장 Likelihood가 높고, AIC가 낮음을 확인할 수 있습니다. (6,5)랑 (5,5)를 가지고 LLR test를 수행해보겠습니다.
model_ret_ar_6_ma_5 = ARMA(df["diff_Close"][1:], order=(6,5))
results_ret_ar_6_ma_5 = model_ret_ar_6_ma_5.fit(maxiter= 100)
results_ret_ar_6_ma_5.summary()
LLR_test(results_ret_ar_5_ma_5 ,results_ret_ar_6_ma_5, DF=1) ##1.0
이제 ARMA(5,5) 모형의 잔차를 분석해보도록 하겠습니다. 잔차는 기본적으로 Correlation을 가지면 안되기 때문에 ACF에서 유의한 autocorrelation이 나오면 안됩니다.
df['res_ar_5_ma_5'] = results_ret_ar_5_ma_5.resid
sgt.plot_acf(df['res_ar_5_ma_5'] [1:], zero = False, lags = 20)
plt.title("ACF Of Residuals for ARMA(5,5)", size=20)
plt.show()
다만 위의 사진을 보면 Lag 10에서 유의성을 나타내는데, 이는 모형에서 다루어야할 모든 시차를 포함하지 않음을 나타내는 것일 수 있습니다.
따라서 추가적으로 Ljung-Box test를 활용하여, 잔차들이 White Noise인지를 확인해 보겠습니다. Ljung-Box test의 특이한 점은 귀무가설이 잔차들이 White Noise란 것이며, P-value가 0.05미만이여서 귀무가설이 기각되었을 때 채택되는 대립가설이 잔차들이 White Noise가 아니다라는 것을 나타낸다는 것입니다.
Ljung Box Test에서 활용하는 Q statistic 는 아래와 같이 정의됩니다. Q Statistc은 s 자유도를 가진 $\chi^2$를 따르게 되어 카이제곱분포를 활용하여 통계적 검증울 수행합니다.
이 때 T는 관측값의 수(the number of observation)이며, s는 시차의 수(the total number of lags), $r_k$는 시차 k에서의 autocorrelation을 나타냅니다.
Python을 활용하여 Ljung-Box test를 수행해보겠습니다.
import statsmodels.api as sm
sm.stats.acorr_ljungbox(results_ret_ar_5_ma_5.resid, lags=[20], return_df=True)
'''
lb_stat lb_pvalue
20 15.602546 0.740955
'''
위의 결과를 보면 p-value가 0.7로 귀무가설을 기각하지 못하여 잔차자 White Noise를 따름을 나타냅니다.
'계량경제학' 카테고리의 다른 글
시계열(Time series) > Forecasting (1) | 2021.01.02 |
---|---|
시계열(Time series) > ARIMAX, SARIMA, SARIMAX (2) | 2021.01.01 |
시계열(Time series) > Diagnosing Models(ARMA, ARIMA)(1/2) (0) | 2020.12.27 |
시계열(Time series) > Moving average model(이동평균모형) (2) | 2020.12.23 |
시계열(Time series) > Autoregressive model(자기회귀모형) (1) | 2020.12.21 |