VARs
The following program estimates an unrestricted VAR, creates a model object
out the estimated VAR, and obtains dynamic forecasts from the VAR by solving
the model object.
' estimate VAR and forecast
' replicates example in Lutkepohl (1991) pp.70-73, pp.89-91
' 1/7/2000 h
' last checked 10/27/2000 h
'change path to program path
%path = @runpath
cd "{%path}"
' load workfile
load lut1
' estimate VAR
smpl 1960:1 1978:4
var1.ls 1 2 y1 y2 y3 @ c
' replicates p.72, (3.2.22) & (3.2.24)
' note that the variables are ordered differently
freeze(out1) var1.output
show out1
' make model out of estimated VAR
var1.makemodel(mod1)
' change sample to forecast period
smpl 1979:1 1980:1
' solve model to obtain dynamic forecasts
mod1.solve
' plot actual and forecasts
smpl 1975:1 1980:1
for !i=1 to var1.@neqn
group gtmp y{!i} y{!i}_0
freeze(gra{!i}) gtmp.line
%gname = %gname + "gra" + @str(!i) + " "
next
' merge all graphs into one
freeze(gfcst) {%gname}
gfcst.align(1, 0.1, 0.5)
gfcst.legend position(0.1,0.1)
gfcst.scale(left) +zeroline
show gfcst
This program computes various criteria to select the lag order of a VAR.
The results from EViews do not quite match those reported in Lutkepohl (1991,
Tables 4.4 and 4.5). While Table 4.4 reports the standard LR statistics, EViews
reports the modified statistics as explained in the User's Guide, page ??.
The program computes the unmodified LR statistics that exactly replicate those
reported in Table 4.5 by using the log likelihood values stored in the output
matrix returned from the mname= option in the laglen command.
Note that the stored log likelihood values do not make a degrees of freedom
adjustment to the residual covariance matrix and will not match those reported
in the estimation output. The information criteria reported in Table 4.5 do not
appear to include the constant term in the log likelihood. However, even after
correcting for the constant term, we are not able to replicate the values for AIC,
HQ, and SC in Table 4.5. (There appears to be a typo in Table 4.5. The HQ and SC
values for lag order 0 are unlikely to be the same.)
' VAR lag order selection
' replicates Lutkepohl (1991)
' Table 4.4 (p.127) and Table 4.5 (p.130)
' version 4 beta
' 1/10/2000 h
' last checked 10/27/2000 h
'change path to program path
%path = @runpath
cd "{%path}"
' load workfile
load lut1
' estimate VAR
smpl 1960:1 1978:4
var1.ls 1 2 y1 y2 y3 @ c
' lag length criteria
freeze(tab45) var1.laglen(4,vname=vlag,mname=mlag)
show tab45
!pi = @acos(-1)
!c = var1.@neqn*(1+log(2*!pi))
' unmodified LR test (exactly replicate Table 4.4, p.127)
' 1st column: (unmodified) LR statistic
' 2nd column: p-value
!m = @rows(mlag)-2
matrix(!m,2) tab44
!df = var1.@neqn * var1.@neqn ' degrees of freedom of test
for !r=!m to 1 step -1
tab44(!r,1) = 2*(mlag(!r+1,1) - mlag(!r,1))
tab44(!r,2) = 1 - @cchisq(tab44(!r,1),!df)
next
show tab44
The following program computes residual diagnostics from a VAR. For the residual
correlogram (autocorrelation), EViews only provides the asymptotic standard
error which only depends on the sample size.
' VAR residual tests
' replicates Lutkepohl (1991, pp.148-158)
' version 4 beta
' 1/10/2000 h
' last checked 9/19/2000 h
'change path to program path
%path = @runpath
cd "{%path}"
' load workfile
load lut1
' estimate VAR
smpl 1960:1 1978:4
var1.ls 1 2 y1 y2 y3 @ c
' residual correlograms (Fig 4.2, p.149)
freeze(fig42) var1.correl(12,graph)
show fig42
' portmanteau test (p.152)
freeze(tab_p152) var1.qstats(12,name=qstat)
show tab_p152
' normality test (p.158)
freeze(tab_p158) var1.jbera(factor=chol,name=jbera)
show tab_p158
The sample programs bootfcst1.prg and bootfcst2.prg compute bootstrap
forecast bounds. A VAR in log first differences is estimated and forecast
bounds for log first differences (bootfcst1.prg) and levels (bootfcst2.prg)
are computed. The bootstrap procedure is computationally intensive (time
consuming) but accounts for both coefficient uncertainty and the nonlinear
log transformation without assuming normality.
'bootstrap VAR forecasts
'no transformation
'12/15/2000 h
'load workfile
%data = @runpath + "lut1"
load "{%data}"
'set sample objects
sample smpl_est 1960:1 1978:4 'estimation sample
sample smpl_fcst 1979:1 1980:4 'forecast sample
'estimate VAR
smpl smpl_est
var1.ls 1 2 y1 y2 y3 @ c
'get residuals to bootstrap
var1.makeresid(n=gres) res1 res2 res3
'make model out of estimated VAR
var1.makemodel(mod1)
'solve model to obtain dynamic forecasts
smpl smpl_fcst
mod1.solve
'rename forecasts
smpl smpl_est
for !i=1 to var1.@neqn
rename y{!i}_0 y{!i}f
y{!i}f = na
next
'assign add factors for bootstrap residuals
mod1.addassign(i) @all
'set monte carlo parameters
!reps = 500 'bootstrap replications
!hrz = smpl_fcst.@obs 'forecast horizon
'allocate storage matrix for entire forecast distribution
for !i=1 to var1.@neqn
matrix(!hrz,!reps) mboot{!i}
next
vector vtmp 'temporary working vector
'set random number generator
rndseed(type=mt) 1234567
'bootstrap loop
for !i=1 to !reps
'bootstrap residuals
smpl @all if res1<>na
gres.resample y1_a y2_a y3_a
'generate bootstrap data
mod1.solve
'estimate VAR with bootstrap data
smpl smpl_est
var var2.ls 1 2 y1_0 y2_0 y3_0 @ c
'make model from bootstrap estimates
var2.makemodel(mod2)
'solve to bootstrap forecasts
smpl smpl_fcst
mod2.solve
'store bootstrap forecasts
for !j=1 to var2.@neqn
stom(y{!j}_0_0, vtmp, smpl_fcst)
colplace(mboot{!j}, vtmp, !i)
next
'clean up
delete mod2
next
'find bootstrap percentiles for each horizon
matrix(!hrz,var1.@neqn) mupp 'upper percentile
matrix(!hrz,var1.@neqn) mlow 'lower percentile
rowvector rtmp 'temporary working vector
for !i=1 to !hrz
for !j=1 to var1.@neqn
rtmp = @rowextract(mboot{!j},!i)
mupp(!i,!j) = @quantile(rtmp,0.975)
mlow(!i,!j) = @quantile(rtmp,0.025)
next
next
'plot actual and forecasts
smpl 1975:1 1980:4
for !i=1 to var1.@neqn
'convert bounds into series
series y{!i}_upp
vtmp = @columnextract(mupp,!i)
mtos(vtmp, y{!i}_upp, smpl_fcst)
series y{!i}_low
vtmp = @columnextract(mlow,!i)
mtos(vtmp, y{!i}_low, smpl_fcst)
'plot graph
group gtmp y{!i} y{!i}f y{!i}_upp y{!i}_low
freeze(gra{!i}) gtmp.line
gra{!i}.setelem(1) legend(actual)
gra{!i}.setelem(2) legend(forecast)
gra{!i}.setelem(3) legend(bootstrap bounds)
gra{!i}.setelem(4) legend()
%gname = %gname + "gra" + @str(!i) + " "
next
' merge all graphs into one
freeze(gfcst) {%gname}
gfcst.options size(8,2)
gfcst.align(1, 0.1, 0.5)
gfcst.legend columns(1) -inbox position(0.1,0.1)
'gfcst.scale(left) +zeroline
gfcst.option linepat ' need to set linepat
gfcst.draw( dashline,left,rgb(155,155,155) ) 0.0
gfcst.elem(1) lcolor(blue) lpat(solid)
gfcst.elem(2) lcolor(red) lpat(solid)
gfcst.elem(3) lcolor(red) lpat(dash1)
gfcst.elem(4) lcolor(red) lpat(dash1)
gfcst.addtext(0.1,-0.2) Bootstrap Forecast Bounds
show gfcst