Error Correction Model is employed to examine whether a cointegration is exist between households consumption and GDP of Indonesia. If it’s exist, we can estimate the speed of adjustment of GDP to Households Consumption when there is a shock.

Installing Libraries

Before started, we need to install some libraries.

library(readxl)
library(aTSA)
library(car)
library(lmtest)
library(ARDL)

Importing the Data

The observation ranges from 1960 to 2021. Households consumption and GDP have to be transformed to natural logarithm.

df <- read_excel("D:/R projects/ECM/indonesia.xlsx")
df <- df[, c(-1:-3)]
df <- ts(df, start = c(1960), frequency = 1)

head(df)
##        lncons    lngdp
## [1,] 24.06894 24.68935
## [2,] 24.14438 24.74517
## [3,] 24.21174 24.76342
## [4,] 24.17141 24.74080
## [5,] 24.17920 24.77549
## [6,] 24.20279 24.78625
tail(df)
##         lncons    lngdp
## [57,] 26.97615 27.53030
## [58,] 27.02477 27.57975
## [59,] 27.07486 27.63020
## [60,] 27.12518 27.67917
## [61,] 27.09815 27.65831
## [62,] 27.11800 27.69455

Plotting the Data

As we can see, both of them move in the same direction.

plot(df, main = "Indonesia Households Consumption and GDP")

Stationary Test

lncons <- df[, "lncons"]
lngdp <- df[, "lngdp"]

adf.test(lncons)
## Augmented Dickey-Fuller Test 
## alternative: stationary 
##  
## Type 1: no drift no trend 
##      lag   ADF p.value
## [1,]   0 10.24    0.99
## [2,]   1  4.34    0.99
## [3,]   2  3.13    0.99
## [4,]   3  3.23    0.99
## Type 2: with drift no trend 
##      lag    ADF p.value
## [1,]   0 -1.049   0.677
## [2,]   1 -0.772   0.774
## [3,]   2 -0.719   0.792
## [4,]   3 -1.393   0.556
## Type 3: with drift and trend 
##      lag    ADF p.value
## [1,]   0 -0.747   0.961
## [2,]   1 -1.392   0.819
## [3,]   2 -1.639   0.717
## [4,]   3 -1.295   0.859
## ---- 
## Note: in fact, p.value = 0.01 means p.value <= 0.01
adf.test(lngdp)
## Augmented Dickey-Fuller Test 
## alternative: stationary 
##  
## Type 1: no drift no trend 
##      lag   ADF p.value
## [1,]   0 11.20    0.99
## [2,]   1  4.40    0.99
## [3,]   2  3.76    0.99
## [4,]   3  3.33    0.99
## Type 2: with drift no trend 
##      lag    ADF p.value
## [1,]   0 -0.715   0.794
## [2,]   1 -0.594   0.836
## [3,]   2 -0.817   0.758
## [4,]   3 -1.327   0.579
## Type 3: with drift and trend 
##      lag   ADF p.value
## [1,]   0 -1.08   0.918
## [2,]   1 -1.77   0.664
## [3,]   2 -1.68   0.698
## [4,]   3 -1.79   0.655
## ---- 
## Note: in fact, p.value = 0.01 means p.value <= 0.01

Regression Model

Stationary test tell us that Household consumption and GDP are I(1); that is, they contain a unit root. Now, we regress Household consumption on GDP.

regression <- lm(lncons ~ lngdp)
summary(regression)
## 
## Call:
## lm(formula = lncons ~ lngdp)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.10970 -0.03382 -0.01281  0.03752  0.12963 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -1.355305   0.199440  -6.796 5.58e-09 ***
## lngdp        1.030177   0.007596 135.616  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.05598 on 60 degrees of freedom
## Multiple R-squared:  0.9967, Adjusted R-squared:  0.9967 
## F-statistic: 1.839e+04 on 1 and 60 DF,  p-value: < 2.2e-16

Next, we extract the residuals and subject to unit root test. The result confirm that it is stationary. In other word, cointegration is exist.

ect <- regression$residuals
adf.test(ect)
## Augmented Dickey-Fuller Test 
## alternative: stationary 
##  
## Type 1: no drift no trend 
##      lag   ADF p.value
## [1,]   0 -1.98  0.0475
## [2,]   1 -2.33  0.0216
## [3,]   2 -3.15  0.0100
## [4,]   3 -3.12  0.0100
## Type 2: with drift no trend 
##      lag   ADF p.value
## [1,]   0 -1.96  0.3436
## [2,]   1 -2.31  0.2119
## [3,]   2 -3.11  0.0339
## [4,]   3 -3.09  0.0361
## Type 3: with drift and trend 
##      lag   ADF p.value
## [1,]   0 -1.93   0.597
## [2,]   1 -2.27   0.457
## [3,]   2 -3.10   0.129
## [4,]   3 -3.06   0.143
## ---- 
## Note: in fact, p.value = 0.01 means p.value <= 0.01

Manipulating the Data

To run ECM, we need to manipulate variables into lag form.

ect <- ts(ect, start = c(1960), frequency = 1)
l1_ect <- ts(ect, start = c(1961), end = c(2021), frequency = 1)

l1_lncons <- lag(lncons, -1)
l1_lngdp <- lag(lngdp, -1)

l1_lncons <- ts(l1_lncons, start = c(1961), end = c(2021), frequency = 1)
l1_lngdp <- ts(l1_lngdp, start = c(1961), end = c(2021), frequency = 1)

new_df <- ts.union(lncons, lngdp, ect, l1_ect, l1_lncons, l1_lngdp)

Error Correction Model

The first model is based on Engle-Granger (1987). The second is an alternative and give us short run effects of GDP reflected in Households consumption.

ecm1 <- lm(diff(lncons) ~ diff(lngdp) + l1_ect)
summary(ecm1)
## 
## Call:
## lm(formula = diff(lncons) ~ diff(lngdp) + l1_ect)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.052744 -0.014231 -0.004803  0.012665  0.083291 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.017117   0.006098   2.807  0.00680 ** 
## diff(lngdp)  0.670707   0.103002   6.512 1.93e-08 ***
## l1_ect      -0.187858   0.063188  -2.973  0.00429 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.02622 on 58 degrees of freedom
## Multiple R-squared:  0.5314, Adjusted R-squared:  0.5152 
## F-statistic: 32.88 on 2 and 58 DF,  p-value: 2.845e-10
ecm2 <- lm(diff(lncons) ~ diff(lngdp) + l1_lncons + l1_lngdp)
summary(ecm2)
## 
## Call:
## lm(formula = diff(lncons) ~ diff(lngdp) + l1_lncons + l1_lngdp)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.054531 -0.013878 -0.002905  0.013832  0.082602 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -0.18694    0.12893  -1.450  0.15254    
## diff(lngdp)  0.66589    0.10406   6.399 3.17e-08 ***
## l1_lncons   -0.18775    0.06359  -2.953  0.00457 ** 
## l1_lngdp     0.19150    0.06562   2.918  0.00503 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.02639 on 57 degrees of freedom
## Multiple R-squared:  0.5336, Adjusted R-squared:  0.509 
## F-statistic: 21.74 on 3 and 57 DF,  p-value: 1.642e-09

Autocorrelation and Heteroscedasticity Tests

The model is free from Autocorrelation and Heteroscedasticity problems.

ncvTest(ecm2)
## Non-constant Variance Score Test 
## Variance formula: ~ fitted.values 
## Chisquare = 0.785511, Df = 1, p = 0.37546
bgtest(ecm2)
## 
##  Breusch-Godfrey test for serial correlation of order up to 1
## 
## data:  ecm2
## LM test = 2.5848, df = 1, p-value = 0.1079

Short Run and Long Run Equilibrium

The coefficient of ect in the first model shows us that 0.19 of the discrepancy in the two variables in the previous year is eliminated this year. Besides, short run changes in the GDP are fast enough reflected in the Households consumption, as the slope coefficient between the two is 0.67. While, in the long run the slope coefficient is 1.00.

c1 <- ecm2$coefficients[2]
c2 <- ecm2$coefficients[4]
c3 <- ecm1$coefficients[3]

cons_sr_eq <- c1
cons_sr_eq
## diff(lngdp) 
##   0.6658949
cons_lr_eq <- c2/-c3
cons_lr_eq
## l1_lngdp 
##  1.01941