시계열(Time series) > Diagnosing Models(ARMA, ARIMA)(2/2)

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를 따름을 나타냅니다.

반응형