Homework #6
Homework #6
# load package
library(tsm)
library(vars)
source("plot_varcheck.R")
● GDP and unemployment data are loaded from a CSV file and converted into time
series objects, starting from the first quarter of 1948:
# load data and create time series object ----
dat_sa <- read.csv("Datasets/blanchQua.csv")
The unemployment data exhibits strong persistence, indicating the potential presence of a
unit root. To investigate this, we perform a Dickey-Fuller test, which allows us to assess
whether we can reject the null hypothesis of a unit root in the data:
# check unemployment for UR
adf.une <- ur.df(une, type = "trend", selectlags = "AIC")
summary(adf.une)
###############################################
# Augmented Dickey-Fuller Test Unit Root Test #
###############################################
Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
Residuals:
Min 1Q Median 3Q Max
-0.70448 -0.21077 -0.04731 0.19844 1.03067
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.0059997 0.0536401 0.112 0.911
z.lag.1 -0.0972035 0.0204701 -4.749 4.67e-06 ***
tt -0.0001167 0.0005838 -0.200 0.842
z.diff.lag 0.6846610 0.0595395 11.499 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.3311 on 153 degrees of freedom
Multiple R-squared: 0.4776, Adjusted R-squared: 0.4674
F-statistic: 46.63 on 3 and 153 DF, p-value: < 2.2e-16
Based on the ADF test results, we can conclude that the time series data does not have a
unit root and is stationary. This conclusion is supported by both the test statistic (which is
more negative than the critical values) and the very low p-value.
After that, Information criteria (AIC, HQ, SC, FPE) are computed to select the
appropriate number of lags for the VAR model:
info.bv <- VARselect(dat.bv, lag.max = 12, type = "const")
info.bv$selectio
We can see that the criteria above all suggest using 2 lags for the model. We, therefore,
set 𝑝 = 2 to estimate the model:
# group data and choose lag length
bv.est <- VAR(dat.bv, p = 2 ,type = "const", season = NULL, exog
= NULL)
summary(bv.est)
The results indicate that the system is stable since all the roots of the characteristic
polynomial are less than 1. Moreover, the lagged values of the unemployment rate seem
to be significant predictors for the current GDP. The analysis also reveals that the past
values of the unemployment rate are significant determinants of the current employment
rate, highlighting the persistence and interdependence of labor market conditions over
time.
Since p-value is greater than 5%, we can conclude that there is an absence of serial
correlation. We, then, conduct residuals diagnostic checks for both GDP and
Unemployment rate data:
my_varcheck_plot(bv.serial, names = "gdp")
my_varcheck_plot(bv.serial, names = "une")
After inspecting the visualizations of GDP and Unemployment rate residuals, it is quite
clear that there is no serial correlation left in the residuals, their variance are constant, and
they follow a normal distribution. This indicates that there are no clear patterns and the
residuals are a close resemblance of white noise. The model, therefore, seems to have
adequately captured the data’s structure.
To test for heteroscedasticity in the residuals we can perform a multivariate ARCH
Lagrange-Multiplier test:
# testing heteroscedasticity
bv.arch <- arch.test(bv.est, lags.multi = 12, multivariate.only
= TRUE)
bv.arch
ARCH (multivariate)
$JB
JB-Test (multivariate)
$Skewness
$Kurtosis
Once again, all the p-values are greater than 5%. This suggests that the residuals are
fairly normally distributed.
Lastly, to test for the structural break in the residuals we can apply a CUSUM test:
# testing for structural stability
bv.cusum <- stability(bv.est, type = "OLS-CUSUM")
plot(bv.cusum)
Because the CUSUM lines stay within bounds of the critical lines, the coefficients of the
model are stable over the period of the sample. There is no statistical evidence of
structural breaks within the given confidence level.
$Granger
$Instant
Based on the p-value obtained from the result above, we can reject the null hypothesis of
no Granger causality for GDP.
bv.cause.une <- causality(bv.est, cause = "une")
bv.cause.une
$Granger
$Instant
It is clear that while an unemployment shock initially has a significant negative effect on
GDP, the effect is temporary and GDP is expected to recover over time back to its
pre-shock levels.
To consider the response of unemployment to output shock we do as follows:
irf.une <- irf(bv.est, impulse = "gdp", response = "une",n.ahead
= 40, boot = TRUE)
plot(irf.une, ylab = "unemployment", main = "Shock from output")
The same thing can be said for Unemployment rate, a positive shock in GDP would
typically lead to a negative effect on unemployment, and this also tapers off through time.
Similarly, we can look at the effect of an unemployment shock on unemployment:
irf.une_un <- irf(bv.est, impulse = "une", response =
"une",n.ahead = 40, boot = TRUE)
plot(irf.une_un, ylab = "unemployment", main = "Shock from
unemployment")
To generate the forecast error variance decompositions we make use of the fevd
command, where we set the number of steps ahead to ten:
# generate variance decompositions
bv.vardec <- fevd(bv.est, n.ahead = 10)
plot(bv.vardec)
● The variance decomposition for GDP shows that the majority of the forecast error
variance in GDP can be attributed to its own shocks. This indicates that GDP is
largely explained by its own innovations over the horizon of 10 periods.
● In the case of unemployment, the plot indicates that its own shocks and GDP
shocks both account for a substantial portion of the forecast error variance. This
suggests unemployment is influenced by both shocks.
VI. Forecasting
To generate forecasts, we can utilize the predict() command, which in this case will
produce forecasts for the next 8 time periods. Additionally, we aim to obtain 95%
confidence intervals for the forecasted values, providing a measure of the uncertainty
around the point forecasts:
# Forecasting with the VAR model
predictions <- predict(bv.est, n.ahead = 8, ci = 0.95)
plot(predictions, names = "gdp")