Peersman JAE 2005 |
This is a (near) replication of Peersman(2005), which compares results from VAR's with short- and long-run restrictions vs sign restrictions applied to U.S. and European data. The principal difference is that Peersman uses the parametric analysis from Canova and de Nicolo(2002) for doing sign restrictions, while the examples here use the Monte Carlo methods of Uhlig(2005).
The base model is a four variable VAR with oil price change, output growth, consumer price inflation and interest rates. All variables are in growth rates (100 x log differences) except interest rates. The VAR's are estimated with a constant and linear trend as deterministic variables with 3 lags. Estimates are done over the period 1980Q1 to the end of the data set (2002Q2).
Programs with Short- and Long-Run Restrictions
There are two programs, one for the US data and one for EMU data which are effectively identical except for the data series used.
For the short- and long-run restrictions, the four shocks are to be (in order) an oil price shock, aggregate supply, aggregate demand and monetary shock. The long-run restrictions are that aggregate demand and money have a zero long-run effect on output. The short-run restrictions are that only the oil shock affects oil price and that the money shock has no impact on output. The two "shape" matrices for input to @ShortAndLong are thus:
input lr
. . . .
. . 0 0
. . . .
. . . .
input sr
. 0 0 0
. . . 0
. . . .
. . . .
This satisfies the RRWZ identification criteria for a "B" model as it has 0, 1, 2 and 3 zero restrictions in the columns.
Given the estimated VAR, this estimates the structural VAR with the given restrictions and sets up the labels for later graphs for the shocks and the variables.
@shortandlong(factor=f,lr=lr,sr=sr,masum=inv(%varlagsums)) %sigma
compute shocklabels=||"Oil Price","Supply Shock","Demand Shock","Money Shock"||
compute varlabels=||"Oil Price","Output","Price","Interest Rate"||
It's important in doing and short- and long-run restrictions to make sure that the impacts have the desired signs. (Zero restrictions can be met with a shock of either sign). In this case, we want:
1.Oil shock positive on oil (variable 1)
2.Aggregate demand and aggregate supply both positive on output (variable 2)
3.Monetary shock positive on interest rates (variable 4)
This uses @ImpactSignFlip to make sure those are done and double-checks that the responses have the correct properties:
@impactsignflip f ||+1,+2,+2,+4||
?"Impact Responses" f
?"Long-Run Responses" inv(%varlagsums)*f
This uses @VARIRF to show the point estimates of the impulse response functions for the model. The responses of the three growth variables are accumulated (accum=||1,2,3|| option).
@varirf(model=peersman,steps=nsteps,accum=||1,2,3||,number=0,$
shocks=shocklabels,factor=f,variables=varlabels,$
footer="Impulse responses of the Peersman model of the U.S.")
Those will be the full set of IRF's to the natural scale of the shocks. The paper does responses to specifically a 10% shock to the oil price and to a 50 basis point (that is 0.50 size) shock in the interest rate. To do that, you need a re-scaled version of the first column of F (oil shock) and another which is the fourth column (monetary shock):
dec vect foilshock(%nvar) frateshock(%nvar)
ewise foilshock(i)=10.0*f(i,1)/f(1,1)
ewise frateshock(i)=0.50*f(i,4)/f(4,4)
This does the graphs of the responses to those shocks. These use the INCLUDE option on @VARIRF to limit the graph to showing only certain variables. Note that the VARIABLES option still gives the full set of variables—the labels are pulled out of the proper positions in those.
@varirf(model=peersman,steps=nsteps,accum=||1,2,3||,number=0,$
shocks=||"Oil Price"||,factor=foilshock,variables=varlabels,$
include=||2,3||,$
footer="Responses to a 10 percent rise in oil prices")
*
@varirf(model=peersman,steps=nsteps,accum=||1,2,3||,number=0,$
shocks=||"Interest Rates"||,factor=frateshock,variables=varlabels,$
include=||2,3,1||,$
footer="Responses to a 50 basis points increase in the interest rate")
Next, HISTORY is used to do the historical decomposition over the period 1995Q1 to 2002Q2. The graph does the decomposition of output (variable 2) only.
history(model=peersman,from=1995:1,to=2002:2,accum=||1,2,3||,$
factor=f,base=base,effects=effects)
*
graph(footer="Contribution of shocks to output in U.S.\\Traditional model",$
key=below,klabels=shocklabels) 4
# effects(2,1)
# effects(2,2)
# effects(2,3)
# effects(2,4)
The last part of each program does a Monte Carlo integration to do error bands for the impulse responses to the structural VAR. Note that this is not included in the paper. It's very important when doing this to make sure that the factor is computed using the re-calculated model lag sums. (%VARLAGSUMS used above only applies to the VAR as it is first estimated and the lag sums change when you do a draw for the coefficients). You also have to repeat the @ImpactSignFlip to make sure the impact signs are consistent across draws. This is done with a "call-back" function for @MCVARDoDraws which we call SRLRFactor which returns the appropriate factor matrix for SIGMA given the model:
function SRLRFactor sigma model
type rect SRLRFactor
type symm sigma
type model model
*
@ShortAndLong(lr=lr,sr=sr,masum=inv(%modellagsums(model))) sigma SRLRFactor
@impactsignflip SRLRFactor ||+1,+2,+2,+4||
end
@mcvardodraws(model=peersman,steps=nsteps,accum=||1,2,3||,$
draws=10000,ffunction=SRLRFactor)
@MCGraphIRF(model=peersman,varlabels=varlabels,shocklabels=shocklabels,$
page=all,percent=||.16,.84||,$
footer="VAR with Short- and Long-Run Restrictions")
Programs with Sign Restrictions
There are two programs, one for the US data and one for EMU data which are effectively identical except for the data series used.
The models with sign restrictions similarly identify four (orthogonal) shocks: an oil price shock, aggregate supply, aggregate demand and monetary shock. These are constraining the signs of impacts only (unlike, for instance, Uhlig(2005) which sign-constrains multiple steps in defining its monetary shock). The sign-constraints for the four shocks (in the columns) on the four variables (in the rows) are:
\begin{equation} \begin{array}{*{20}c} {} \hfill & {{\rm{Oil}}} \hfill & {{\rm{AS}}} \hfill & {{\rm{AD}}} \hfill & {{\rm{MP}}} \hfill \\ {{\rm{POil}}} \hfill & \ge \hfill & \bullet \hfill & \ge \hfill & \le \hfill \\ {{\rm{Output}}} \hfill & \le \hfill & \ge \hfill & \ge \hfill & \le \hfill \\ {{\rm{Price}}} \hfill & \ge \hfill & \le \hfill & \ge \hfill & \le \hfill \\ {{\rm{Rate}}} \hfill & \ge \hfill & \le \hfill & \ge \hfill & \ge \hfill \\ \end{array} \end{equation}
This translates into the set of SignDesc arrays for use in @MCSignRestrict as
dec SignDesc OilShockDesc(4)
compute OilShockDesc(1)=||+1,1,1||
compute OilShockDesc(2)=||-2,1,1||
compute OilShockDesc(3)=||+3,1,1||
compute OilShockDesc(4)=||+4,1,1||
dec SignDesc SupplyDesc(3)
compute SupplyDesc(1)=||+2,1,1||
compute SupplyDesc(2)=||-3,1,1||
compute SupplyDesc(3)=||-4,1,1||
dec SignDesc DemandDesc(4)
compute DemandDesc(1)=||+1,1,1||
compute DemandDesc(2)=||+2,1,1||
compute DemandDesc(3)=||+3,1,1||
compute DemandDesc(4)=||+4,1,1||
dec SignDesc MonetaryDesc(4)
compute MonetaryDesc(1)=||-1,1,1||
compute MonetaryDesc(2)=||-2,1,1||
compute MonetaryDesc(3)=||-3,1,1||
compute MonetaryDesc(4)=||+4,1,1||
compute [vect[SignDesc]] SignConstraints=||OilShockDesc,SupplyDesc,DemandDesc,MonetaryDesc||
Note that the differences between the constraints can be fairly small: the oil shock vs the AD shock, for instance, differ only in the sign of the impact on output. You only get a valid orthogonalization if all four complete sets of constraints can be met simultaneously which can be difficult even when you are just doing impact shocks.
As with the short- and long-run restrictions examples, we create more descriptive labels for both the shocks and the variables.
compute nshocks=4,nvar=4
dec vect[strings] shocklabels(nshocks) varlabels(nvar)
compute shocklabels=||"Oil Price","Supply Shock","Demand Shock","Money Shock"||
compute varlabels=||"Oil Price","Output","Price","Interest Rate"||
Again, as with the short- and long-run examples, the author examines shocks to oil price and monetary policy which have specific impacts on the price of oil (up 10%) and the interest rate (up .50). This is more complicated because it needs to be done for each accepted draw. This is accomplished by using a REPLACE call-back function for @MCSignRestrict which replaces the flattened impulse responses with rescaled values that have the desired scalings. Note that this affects only the responses to the first (oil price) and fourth (monetary) shocks.
This uses the %IRFFLATTENX function to extract a response matrix out of the "flattened" matrix that is passed in in the INPUT parameter.
function PegShocks model factor input
type rect PegShocks factor input
type model model
*
local int nshocks i step nvar
local rect impacts response
local real oilshockadjust rateshockadjust
*
compute nvar=%modelsize(model)
compute nshocks=%rows(input)/nvar
*
* Copy the input "flattened" matrix to the output matrix. That way, we
* only have to change the individual elements that need adjusting.
*
compute PegShocks=input
*
* Extract the impacts
*
compute impacts=%irfflattenx(input,1,model)
*
* Peg the own impact on the oil price shock to 10.
* The impact of oil to oil is in position 1,1 (1st shock, 1st variable in
* the model).
*
compute oilshockAdjust=10.0/Impacts(1,1)
*
* And the own impact of the interest rate shock to .50. The impact of
* rate on rate is in position 16 (4th shock, 4th variable), step 1
*
compute rateShockAdjust=0.50/Impacts(4,4)
do step=1,%cols(input)
compute response=%irfflattenx(input,step,model)
do i=1,nvar
compute Response(i,1)*=oilShockAdjust
compute Response(i,4)*=rateShockAdjust
end do i
compute %psubmat(pegshocks,1,step,%vec(response))
end do step
*
end
The analysis in the paper uses only the point estimates for the VAR coefficients and covariance matrix. That can be forced into @MCSignRestrict by using the FIXED option. Note that this still uses a non-zero VARDRAWS option—that allows it to be more easily transformed into a more (now) conventional use of outer draws for the VAR, and also allows interim reports through the progress bar of how the subdraw selection process is going.
@MCSignRestrict(model=peersman,nsteps=nsteps,constraints=SignConstraints,$
accum=||1,2,3||,nkeep=nkeep,fixed,vardraws=vardraws,subdraws=subdraws,replace=PegShocks)
The controls for this are near the top of the program. Note that this anticipates needing a very large number of draws (possible 2 million) to get 1000 keeper draws. That turns out to be a bit pessimistic, but in a different situation, you might find that even that isn't enough.
compute nkeep=1000
compute varDraws=1000
compute subDraws=2000
This does the graphs with the default 16-84% bands. Note that, as was forced in, the top left (oil to oil) and bottom right (rate to monetary shock) start from just a point value with no uncertainly.
@MCGraphIRF(model=peersman,shocklabels=shocklabels,varlabels=varlabels,$
header="Sign Restrictions, US",$
picture="##.##",center=median)
Historical Decomposition with Sign Restrictions
The paper includes graphs of the historical decomposition of output over the period 1995:1 to 2002:2 based upon sign restrictions. It's not entirely clear how that was done, as it shows only a point estimate while the sign restriction procedure would generate a separate value for each accepted factorization. What this calculates is the mean across draws of the contributions of each identified shock. Because in each draw the components (base forecasts plus shock contributions) will sum to the actual data, the same will be true for the mean—that would not be true if we used the median rather than the mean.
This does a new set of sign restriction draws since we don't want the pegged shock sizes that were used previously.
The following is an @MCSignRestrict callback for the EXTRA option which does added calculations for a model based upon an accepted sign-restriction draw. This has to do a run through of the calculation of the historical decomposition given an input model, factor matrix, the flattened set of IRF's for the sign-restricted draw and (for bookkeeping purposes) the current number of accepted draws. (We don't use ACCEPT in this because we are computing only the mean, and can just update a sum, but you would need it if you had to save the full set of values to compute percentiles).
function DoHistory model fsigma flatten accept
type model model
type rect fsigma flatten
type int accept
type int DoHistory
*
local integer nshocks nvar i
local rect impacts remap
local vect beta
local symm sigma
local vect[series] u base baseplus
*
* Do a FORECAST with STATIC and ERRORS to get the residuals over the
* decomposition period. Note that in this application this and the next
* *could* be computed just once since the coefficients of the model
* don't change). However, this doesn't take much time since it is only
* computed for an accepted draw.
*
forecast(model=model,from=hstart,to=hend,static,errors=u)
*
* Compute the base forecast over the decomposition period, accumulating
* the first three dependent variables (all but the interest rate). Note
* that you do *not* use the ACCUM option when you are computing the
* residuals.
*
forecast(model=model,from=hstart,to=hend,results=base,accum=||1,2,3||)
*
* Compute the paths implied by the impact shocks in turn and do the
* FORECAST with those added paths. Subtracting the result from the
* <<base>> series gives the cumulated effects of a particular shock.
*
* This computes only decomposition for output (variable 2), summing across draws.
*
compute nvar=%modelsize(model)
compute impacts=%irfflattenx(flatten,1,model)
compute sigma=fsigma*tr(fsigma)
do i=1,%cols(impacts)
compute beta=%xcol(impacts,i)
compute remap=beta*tr(beta)*inv(sigma)
do t=hstart,hend
compute %pt(upaths,t,remap*%xt(u,t))
end do t
forecast(model=model,from=hstart,to=hend,accum=||1,2,3||,results=baseplus,paths)
# upaths
set history(i) hstart hend = history(i)+(baseplus(2)-base(2))
end do i
end
The historical decomposition requires residuals generated using the VAR model's coefficients. The HISTORY instruction uses the ones saved with the model when it is estimated. HISTORY also assumes that you have a full decomposition of the covariance matrix, which you don't necessarily have in sign-restriction analyses. (This paper does do a full set of shocks). So the first step is to take the current model and calculate the residuals over the decomposition range; that is done using FORECAST with the STATIC and ERRORS options. This is the only use of FORECAST done in this that does not use the appropriate ACCUM option for the model as it is not actually doing forecasts (other than the one-step out which aren't affected by accumulating).
The base forecast is done using FORECAST without the STATIC option. The results of those go into the VECT[SERIES] BASE. The DO I loop runs through the shocks (note that it allows for the number of shocks to be less than the number of variables) where the REMAP matrix maps the original residuals through the structural residual to the corresponding values of the VAR shocks. The FORECAST inside the loop redoes the forecast with the added shocks (PATHS option plus the # upaths supplementary card). The contributions of the shock to output (variable 2) is found by taking the difference between the BASEPLUS(2) and the BASE(2) series. Since we are doing the mean, this sums those differences—outside the loop, that will be scaled by the number of draws to produce the mean.
This does the new set of sign restrictions with the DoHistory call back:
@MCSignRestrict(model=peersman,nsteps=nsteps,constraints=SignConstraints,$
accum=||1,2,3||,nkeep=nkeep,fixed,vardraws=vardraws,subdraws=subdraws,extra=DoHistory)
Scale this by the number of accepted draws to produce the average of the effect of a shock.
do i=1,nvar
set history(i) hstart hend = history(i)/%%accepted
end do i
This graphs the contributions of the four shocks over the decomposed period:
graph(footer="Contribution of shocks to output in U.S.\\Sign Restrictions",$
key=below,klabels=shocklabels) 4
# history(1) hstart hend
# history(2) hstart hend
# history(3) hstart hend
# history(4) hstart hend
Copyright © 2026 Thomas A. Doan