TL wrote:Dear Tom,
I use code for two shocks from the forum. In addition to the impulse responses, I would like to see how much of the variation is accounted for by the first shock and by the second shock (variance decomposition).
I am not quite sure whether fraction explained (variance decomposition) is correct. Could you please give me some suggestions and feedbacks whether my code is correct?
Thank you very much for your help and kindness.
Tim
That won't work without changing the way the impulse responses are computed. In the original Uhlig code, the impulse response and squares are computed by:
Code: Select all
impulse(noprint,model=varmodel,decomp=swish,results=impulses,steps=nstep)
gset irfsquared 1 1 = %xt(impulses,t).^2
gset irfsquared 2 nstep = irfsquared{1}+%xt(impulses,t).^2
The shocks are computed using a factorization of the covariance matrix (decomp=swish). Because the shocks are orthogonal (across time by assumption, across variables by construction), the sums of squared impulse responses (in IRFSQUARED) provide all the information needed for computing the decomposition of variance. To get the variance produced by impulse vector swish * a (where ||a||=1) you just need the sum over j of irfsquared(i,j)*a(j)^2, which is what (irfsquared(i)*(a.^2)) is computing in:
Code: Select all
ewise goodfevd(accept)(i,j)=ik=(irfsquared(i)*(a.^2))./(irfsquared(i)*ones),ik(j)
The irfsquared(i)*ones is the vector of total variances (sums across rows), so the ./ gives the fractions.
The code we wrote for doing multiple sign-restricted shocks uses:
Code: Select all
impulse(noprint,model=varmodel,decomp=%identity(nvar),results=impulses,steps=nstep)
Because the shocks aren't orthogonal contemporaneously:
Code: Select all
gset irfsquared 1 1 = %xt(impulses,t).^2
gset irfsquared 2 nstep = irfsquared{1}+%xt(impulses,t).^2
[/code]
should have a big red X through it - the numbers produced are of almost no value; there are a whole bunch of non-zero covariances which this doesn't compute.
The solution to this is to return to the original base set of impulse responses, then back out the weights based upon those. That's really easy for the first one, since it just restores the original code:
Code: Select all
compute v1=%ransphere(6)
compute i1=p*v1
do k=1,KMAX+1
compute ik=%xt(impulses,k)*v1
if ik(1)>0.or.ik(2)>0.or.ik(3)<0.or.ik(6)>0
branch 105
end do k
The second (and any others) just requires pre-multiplying the non-orthogonal shock by inv(p).
Code: Select all
@forcedfactor(force=column) sigmad i1 f
compute v2=%ransphere(5)
compute i2=%xsubmat(f,1,6,2,6)*v2
compute v2=inv(p)*i2
*****************************************************
* Second Set of Restrictions - Demand Shock
*****************************************************
do k=1,KMAX+1
compute ik=%xt(impulses,k)*v2
if ik(1)<0.or.ik(2)<0.or.ik(3)<0.or.ik(6)<0
branch 105
end do k
v1 and v2 are the two weight vectors on the "SWISH" factored draws. The FEVD's are computed with:
Code: Select all
ewise goodfevd(accept)(i,j)=(ik=(irfsquared(i)*(v1.^2))./(irfsquared(i)*ones)),ik(j)
ewise goodfevda(accept)(i,j)=(ik=(irfsquared(i)*(v2.^2))./(irfsquared(i)*ones)),ik(j)
Code: Select all
OPEN DATA uhligdata.xls
CALENDAR 1965 1 12
compute missc=1.0e+32
data(format=xlS,org=columns) 1965:1 2003:12 gdpc1 gdpdef cprindex totresns bognonbr fedfunds
set gdpc1 = log(gdpc1)*100.0
set gdpdef = log(gdpdef)*100.0
set cprindex = log(cprindex)*100.0
set totresns = log(totresns)*100.0
set bognonbr = log(bognonbr)*100.0
*
system(model=varmodel)
variables gdpc1 gdpdef cprindex fedfunds bognonbr totresns
lags 1 to 12
end(system)
estimate(noprint,resid=resids)
dec vect[strings] vl(6)
compute vl=||'real GDP','GDP price defl','Comm. Price Ind.',$
'Fed Funds Rate','Nonborr. Reserv.','Total Reserves'||
compute n1=1000
compute n2=1000
compute nvar=6
compute nstep=60
compute KMAX=5
* This is the standard setup for MC integration of an OLS VAR
*
dec symm s(6,6)
dec vect v1(6) ;* For the unit vector on the 1st draw
dec vect v2(5) ;* For the unit vector on the 2nd draw
dec vect v(6) ;* Working impulse vector
compute sxx =%decomp(%xx)
compute svt =%decomp(inv(%nobs*%sigma))
compute betaols=%modelgetcoeffs(varmodel)
compute ncoef =%rows(sxx)
compute wishdof=%nobs-ncoef
dec rect ranc(ncoef,nvar)
*
* Most draws are going to get rejected. We allow for up to 1000
* good ones. The variable accept will count the number of accepted
* draws. GOODRESP will be a RECT(nsteps,nvar) at each accepted
* draw.
*
declare vect[rect] goodresp(1000) goodfevd(1000)
declare vect[rect] goodrespa(1000) goodfevda(1000)
declare vector ik a(nvar) ones(nvar)
declare series[rect] irfsquared
compute ones=%const(1.0)
source forcedfactor.src
*
compute accept=0
infobox(action=define,progress,lower=1,upper=n1) 'Monte Carlo Integration'
do draws=1,n1
*
* Make a draw from the posterior for the VAR and compute its impulse
* responses.
*
compute sigmad =%ranwisharti(svt,wishdof)
compute p =%decomp(sigmad)
compute ranc =%ran(1.0)
compute betau =sxx*ranc*tr(p)
compute betadraw=betaols+betau
compute %modelsetcoeffs(varmodel,betadraw)
*
* This is changed to unit shocks rather than orthogonalized shocks.
*
impulse(noprint,model=varmodel,decomp=p,results=impulses,steps=nstep)
gset irfsquared 1 1 = %xt(impulses,t).^2
gset irfsquared 2 nstep = irfsquared{1}+%xt(impulses,t).^2
*
* Do the subdraws over the unit sphere. These give the weights on the
* orthogonal components.
*
do subdraws=1,n2
************************************************
* First Set of Restrictions - Unique Impulse Vector
************************************************
compute v1=%ransphere(6)
compute i1=p*v1
do k=1,KMAX+1
compute ik=%xt(impulses,k)*v1
if ik(1)>0.or.ik(2)>0.or.ik(3)<0.or.ik(6)>0
branch 105
end do k
*
* Meets the first restriction
* Draw from the orthogonal complement of i1 (last five columns of the
* factor "f").
*
@forcedfactor(force=column) sigmad i1 f
compute v2=%ransphere(5)
compute i2=%xsubmat(f,1,6,2,6)*v2
compute v2=inv(p)*i2
*****************************************************
* Second Set of Restrictions - Demand Shock
*****************************************************
do k=1,KMAX+1
compute ik=%xt(impulses,k)*v2
if ik(1)<0.or.ik(2)<0.or.ik(3)<0.or.ik(6)<0
branch 105
end do k
*
* Meets both restrictions
*
compute accept=accept+1
dim goodrespa(accept)(nstep,nvar) goodfevda(accept)(nstep,nvar)
dim goodresp(accept)(nstep,nvar) goodfevd(accept)(nstep,nvar)
ewise goodresp(accept)(i,j)=(ik=%xt(impulses,i)*v1),ik(j)
ewise goodfevd(accept)(i,j)=(ik=(irfsquared(i)*(v1.^2))./(irfsquared(i)*ones)),ik(j)
ewise goodrespa(accept)(i,j)=(ik=%xt(impulses,i)*v2),ik(j)
ewise goodfevda(accept)(i,j)=(ik=(irfsquared(i)*(v2.^2))./(irfsquared(i)*ones)),ik(j)
if accept>=1000
break
:105
end do subdraws
if accept>=1000
break
infobox(current=draws)
end do draws
infobox(action=remove)
*
* Post-processing. Graph the mean of the responses along with the 16% and 84%-iles
*
clear upper lower resp
*
spgraph(vfields=3,hfields=2,hlabel='Impulse Responses with Pure-Sign Approach',subhea='Subhea')
do i=1,nvar
compute minlower=maxupper=0.0
smpl 1 accept
do k=1,nstep
set work = goodresp(t)(k,i)
compute frac=%fractiles(work,||.16,.84||)
compute lower(k)=frac(1)
compute upper(k)=frac(2)
compute resp(k)=%avg(work)
end do k
*
smpl 1 nstep
graph(pattern,ticks,number=0,picture='##.##',header='Impulse Responses for '+vl(i)) 3
# resp
# upper / 2
# lower / 2
end do i
*
spgraph(done)
smpl
*
clear upper lower resp
*
spgraph(vfields=3,hfields=2,hlabel='SECOND Impulse Responses with Pure-Sign Approach',subhea='Subhea')
do i=1,nvar
compute minlower=maxupper=0.0
smpl 1 accept
do k=1,nstep
set work = goodrespa(t)(k,i)
compute frac=%fractiles(work,||.16,.84||)
compute lower(k)=frac(1)
compute upper(k)=frac(2)
compute resp(k)=%avg(work)
end do k
*
smpl 1 nstep
graph(pattern,ticks,number=0,picture='##.##',header='Impulse Responses for '+vl(i)) 3
# resp
# upper / 2
# lower / 2
end do i
*
spgraph(done)
smpl
*
clear upper lower resp
*
spgraph(vfields=3,hfields=2,hlabel='Fraction of Variance Explained with Pure-Sign Approach',subhea='Subhea')
do i=1,nvar
compute minlower=maxupper=0.0
smpl 1 accept
do k=1,nstep
set work = goodfevd(t)(k,i)
compute frac=%fractiles(work,||.16,.50,.84||)
compute lower(k)=frac(1)
compute upper(k)=frac(3)
compute resp(k)=frac(2)
end do k
*
smpl 1 nstep
graph(pattern,ticks,number=0,min=0.0,picture="##.##",header="Fraction Explained for "+vl(i)) 3
# resp
# upper / 2
# lower / 2
end do i
*
spgraph(done)
smpl
*
clear upper lower resp
*
spgraph(vfields=3,hfields=2,hlabel='SECOND Fraction of Variance Explained with Pure-Sign Approach',subhea='Subhea')
do i=1,nvar
compute minlower=maxupper=0.0
smpl 1 accept
do k=1,nstep
set work = goodfevda(t)(k,i)
compute frac=%fractiles(work,||.16,.50,.84||)
compute lower(k)=frac(1)
compute upper(k)=frac(3)
compute resp(k)=frac(2)
end do k
*
smpl 1 nstep
graph(pattern,ticks,number=0,min=0.0,picture="##.##",header="Fraction Explained for "+vl(i)) 3
# resp
# upper / 2
# lower / 2
end do i
*
spgraph(done)
smpl