VARs

Estimate and forecast VAR

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

VAR lag order selection

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

VAR residual diagnostics

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

Bootstrap forecast bounds

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