RATS 10.1
RATS 10.1

Paper Replications /

Hafner Herwartz JIMF 2006

Home Page

← Previous Next →

This is a replication file for the analysis in Hafner and Herwartz(2006) (HH for short). The data set is a reproduction, so the results are similar but don't quite match.


This paper defines the concept of a Volatility Impulse Reponse Function or VIRF, which is the response of the variance/covariance matrix to some form of shock. Note that this has very different behavior from a standard Impulse Response Function in a VAR or VECM, which shows the response to the process mean (not variance) to a shock. In standard IRF calculations, the mean of a residual is zero, so anything non-zero is a "shock". In a VIRF for a GARCH model, the residuals have an covariance matrix which is non-zero—not only non-zero, but time-varying. If the variance of component 1 is 4.0, then a residual of 1.0 is not a "shock", but exactly the opposite—it's of a size smaller than expected. Also, unlike standard IRF's, the VIRF's aren't linear in the shock size (doubling the size of a shock doesn't double the response of the variance), so there is no real point to any sort of standardized calculation. Because of this, HH look at historical episodes—it gives you the baseline covariance matrix from the GARCH model and an observable shock that exceeds that.

 

Note that the VIRF as defined by HH only exists for certain types of models—those that are special cases of the "VECH" model, and only with no asymmetry. This includes BEKK and DVECH, but excludes (for instance) CC and DCC. The excluded models have variances which are more dependent upon initial conditions than is allowed by the VIRF calculation.

 

This paper and VIRF's in general are covered in greater detail as part of the ARCH, GARCH and Volatility Models e-course.

 

This describes the program named garchmodels_v10.rpf, which uses some features added with version 10 for better handling daily data with irregular dates (due to holidays). The garchmodels.rpf program (which will work with version 9 and earlier) does the same calculations, but the handling of calendar dates is much clumsier.

 

The dates on the file are coded into a series called date, which has the date as a six digit number in the form yymmdd. This reads the data, using the %JULIANFROMCODED function to remap the date to its "Julian" value, and sets the CALENDAR based upon that.
 

open data xrates.xls

data(format=xls,org=columns) 1 3720 usxjpn usxfra usxsui usxnld usxuk $

 usxbel usxger usxswe usxcan usxita date


set jdate = %julianfromcoded(date,"yymmdd")

cal(julian=jdate)

 

This converts the raw exchange rates in the data set to returns (for Germany (DEMRET) and the UK pound (GBPRET) vs the US dollar). This is the transformation used in the paper, but in practice we would recommend multiplying these by 100 to give the data and the variances a more reasonable scale. (In the paper, they have to multiply variances by \(10^4\) to get a reasonable scale on graphs, which is what scaling the data by 100 accomplishes directly).

 

set demret = log(usxger/usxger{1})

set gbpret = log(usxuk/usxuk{1})

 

This next fits univariate GARCH models to the two series with univariate AR(1) models for the mean and does some diagnostics on the standardized residuals: a test for residual ARCH, a Jarque-Bera test for Gaussianity, and Q tests for serial correlation. REPORT is used to insert the diagnostics into a single combined table which could be put into a paper.
 

garch(regressors,robust,hseries=h) / demret

# constant demret{1}

set stdu = %resids/sqrt(h)

 

report(action=define,title="Table 1: Diagnostic Tests for Univariate Processes")

report(atrow=1,atcol=1,align=center) "ARCH-LM(1)" "JB" "Q(10)" "Q(20)"

report(atrow=2,atcol=1,span) "DEM/USD"

@archtest(noprint,lags=1) stdu

report(atrow=3,atcol=1) %cdstat

report(atrow=4,atcol=1,special=parens) %signif

stats(noprint) stdu

report(atrow=3,atcol=2) %jbstat

report(atrow=4,atcol=2,special=parens) %jbsignif

corr(noprint,number=10,qstats,dfc=1) stdu

report(atrow=3,atcol=3) %qstat

report(atrow=4,atcol=3,special=parens) %qsignif

corr(noprint,number=20,qstats,dfc=1) stdu

report(atrow=3,atcol=4) %qstat

report(atrow=4,atcol=4,special=parens) %qsignif

 

garch(regressors,robust,hseries=h) / gbpret

# constant gbpret{1}

 

set stdu = %resids/sqrt(h)

report(atrow=5,atcol=1,span) "GBP/USD"

@archtest(noprint,lags=1) stdu

report(atrow=6,atcol=1) %cdstat

report(atrow=7,atcol=1,special=parens) %signif

stats(noprint) stdu

report(atrow=6,atcol=2) %jbstat

report(atrow=7,atcol=2,special=parens) %jbsignif

corr(noprint,number=10,qstats,dfc=1) stdu

report(atrow=6,atcol=3) %qstat

report(atrow=7,atcol=3,special=parens) %qsignif

corr(noprint,number=20,qstats,dfc=1) stdu

report(atrow=6,atcol=4) %qstat

report(atrow=7,atcol=4,special=parens) %qsignif

report(action=format,atrow=2,picture="*.###",align=decimal)

report(action=show)

 

The GARCH estimates are fairly typical of daily returns series—for both series, the GARCH persistence (sum of A and B) is just below 1, with most of it coming from the "GARCH" coefficient (B). The AR(1) coefficients in the mean are small, but probably not negligible for the GBPRET estimates. The diagnostics are not unreasonable—the residual ARCH test passes easily; the Q test fails slightly at the .05 level for the German data, but that's not a major problem with such a large data set (over 3000 observations). The JB test for Gaussianity very strongly rejects, but the GARCH model doesn't require normally distributed residuals, so that isn't surprising.

 

Note that if the intent is to estimate a multivariate GARCH model (as it is here), the univariate models and diagnostics don't help that much—while the AR(1) univariate models seem to be adequate for a univariate model, that doesn't tell you that they are adequate for a bivariate model, since there is no test for cross-series effects. A VAR(1) model is probably a more reasonable choice for the mean if there appears to be some serial correlation in the returns.
 

That being said, the paper uses a model with separate univariate AR(1) models rather than a full VAR(1) for the bivariate mean model. That's set up and estimated with:

 

equation demeqn demret

# constant demret{1}

equation gbpeqn gbpret

# constant gbpret{1}

group uniar1 demeqn gbpeqn

garch(model=uniar1,mv=bekk,rvectors=rv,hmatrices=hh,$

   stdresids=stdmvu,factorby=eigen)
 

The GARCH estimates include jointly standardized residuals using an eigen factorization of the covariance matrices. The (non-standardized) residuals are saved using the RVECTORS option as they will be needed for computing the shocks at the historical episodes.

 

The coefficient estimates for a BEKK model are usually difficult to interpret. HH convert the BEKK estimates to their equivalent VECH form, which tells you more about the dynamics of the variance/covariance matrices, and compute the eigenvalues of the recursion. @MVGARCHtoVECH is a procedure which takes the GARCH output (for certain types of models) and produces the A and B matrices in the implied VECH form.

 

@MVGARCHtoVECH(mv=bekk)

eigen(cvalues=cv) %%vech_a+%%vech_b

disp "Eigenvalues from BEKK-Gaussian" cv
 

The largest eigenvalue is 0.98557, that is, just inside the unit circle, so the variance recursion will be fairly persistent, but isn't explosive.


 

HH then do a multivariate Jarque-Bera test for Gaussianity in the (jointly standardized) residuals—in RATS, this is done with the @MVJB procedure:

 

@mvjb(sigma=%identity(%nvar))

# stdmvu

 

which, not surprisingly given the univariate results, overwhelmingly rejects. The estimation of the BEKK model is re-done using t distributed errors, and that is what is used for the remainder of the paper. (Note that the repeat of the multivariate J-B test is not expected to give an acceptance—in fact, you would expect to see an even stronger rejection, as the use of t errors rather than Gaussian errors doesn't penalize outliers as strongly).

 

garch(model=uniar1,mv=bekk,rvectors=rv,hmatrices=hh,distrib=t,$

   stdresids=stdmvu,factorby=eigen)

@MVGARCHtoVECH(mv=bekk)

eigen(cvalues=cv) %%vech_a+%%vech_b

disp "Eigenvalues from BEKK-t" cv

 

@mvjb(sigma=%identity(%nvar))

# stdmvu

 

Calculation of VIRF

HH compute the VIRF from two episodes in the data. The first is "Black Wednesday'' (September 16, 1992), when the Italian lira and the UK dropped out of the European Exchange Rate Mechanism (ERM). The second is August 2, 1993, when the EC finance ministers changed the variability bands on currencies in the ERM. Responses for 400 steps (roughly 1 1/2 years with five day a week data) are computed.

 

compute blackwed=1992:09:16

compute ecpolicy=1993:08:02

 

We'll look at the calculation of the VIRF for the Black Wednesday shock in detail.

 

compute eps0=rv(blackwed)

compute sigma0=hh(blackwed)

compute shock=1.e+4*%vec(%outerxx(eps0)-sigma0)

 

EPS0 is the vector of residuals on the date, and SIGMA0 is the model's predicted covariance matrix for that date (that is, the prediction of the variance given data through the day before). The "shock" to the covariance matrix is the difference between the outer product of EPS0 and SIGMA0. (This is multiplied by 10000 to get a better scale for the graphs. As noted above, that wouldn't be necessary if the returns had been scaled up by 100 at the beginning). There are three components to the VECH of 2 by 2 matrix: the (1,1), (2,1) and (2,2) elements of the covariance matrix in that order. This computes and saves the VIRF.
 

dec vect[series] sept92virf(3)

do i=1,3

   set sept92virf(i) 1 nstep = 0.0

end do i


 

do step=1,nstep

   if step==1

      compute hvec=%%vech_a*shock

   else

      compute hvec=(%%vech_a+%%vech_b)*hvec

   compute %pt(sept92virf,step,hvec)

end do step

 

The response for the first step out (for the day after the shock) requires just the "A" term in the VECH representation times the shock, while all remaining ones use both the "A" and "B" terms times the previous step's response. The %PT function unpacks the vector of responses into the separate elements of the time series of responses.


 

This graphs the responses. Note that this was all enclosed within an SPGRAPH instruction to organize the graphs from the two experiments onto a single page.

 

do i=1,3

   graph(min=0.0,column=1,row=i,picture="*.###",vticks=5,nodates)

   # sept92virf(i) 1 nstep

end do i

 

The EC policy VIRF is done using a "baseline" for the covariance matrix of zero, rather than of the predicted covariance matrix, which is an alternative that they propose. Note that the only difference is that the "shock" calculation doesn't subtract off SIGMA0:

 

compute eps0=rv(ecpolicy)

compute sigma0=hh(ecpolicy)

compute shock=1.e+4*%vec(%outerxx(eps0))

 

As would be expected given the near-unit eigenvalues, the effect of a shock (either one) take quite a while to dissipate.

 

Output
 

GARCH Model - Estimation by BFGS

Convergence in    18 Iterations. Final criterion was  0.0000011 <=  0.0000100

 

With Heteroscedasticity/Misspecification Adjusted Standard Errors

Dependent Variable DEMRET

Irregular Data From 1980:01:02 To 1994:04:01

Usable Observations                      3718

Log Likelihood                     13312.5266
 

    Variable                        Coeff      Std Error      T-Stat      Signif

************************************************************************************

1.  Constant                      -4.2686e-05   1.3146e-04     -0.32470  0.74540440

2.  DEMRET{1}                          0.0292       0.0161      1.81967  0.06880870

 

3.  C                              1.3640e-06   3.2080e-07      4.25170  0.00002122

4.  A                                  0.0735   9.5631e-03      7.69044  0.00000000

5.  B                                  0.9008       0.0115     78.55691  0.00000000


 

GARCH Model - Estimation by BFGS

Convergence in    24 Iterations. Final criterion was  0.0000043 <=  0.0000100

 

With Heteroscedasticity/Misspecification Adjusted Standard Errors

Dependent Variable GBPRET

Irregular Data From 1980:01:02 To 1994:04:01

Usable Observations                      3718

Log Likelihood                     13356.3494

 

    Variable                        Coeff      Std Error      T-Stat      Signif

************************************************************************************

1.  Constant                      -6.1799e-05   1.2989e-04     -0.47577  0.63423843

2.  GBPRET{1}                          0.0564       0.0167      3.36932  0.00075355

 

3.  C                              6.5797e-07   2.1892e-07      3.00555  0.00265100

4.  A                                  0.0474   8.2642e-03      5.73904  0.00000001

5.  B                                  0.9395       0.0109     86.48694  0.00000000


 

ARCH-LM(1)    JB     Q(10)   Q(20)

DEM/USD

    1.103  259.544  19.367  32.157

   (0.294)  (0.000) (0.022) (0.030)

GBP/USD

    0.692  435.111   9.994  24.910

   (0.406)  (0.000) (0.351) (0.164)


 

MV-GARCH, BEKK - Estimation by BFGS

Convergence in    53 Iterations. Final criterion was  0.0000074 <=  0.0000100

 

Irregular Data From 1980:01:02 To 1994:04:01

Usable Observations                      3718

Log Likelihood                     28606.7936
 

    Variable                        Coeff      Std Error      T-Stat      Signif

************************************************************************************

Mean Model(DEMRET)

1.  Constant                     -0.000044869  0.000098167     -0.45707  0.64762151

2.  DEMRET{1}                     0.026382217  0.014787080      1.78414  0.07440096

Mean Model(GBPRET)

3.  Constant                     -0.000059095  0.000093973     -0.62885  0.52944481

4.  GBPRET{1}                     0.044781074  0.015372533      2.91306  0.00357909

 

5.  C(1,1)                        0.000966444  0.000083838     11.52750  0.00000000

6.  C(2,1)                        0.000450386  0.000125609      3.58562  0.00033628

7.  C(2,2)                        0.000650053  0.000059989     10.83621  0.00000000

8.  A(1,1)                        0.287528737  0.019078038     15.07119  0.00000000

9.  A(1,2)                       -0.030077557  0.017118946     -1.75697  0.07892210

10. A(2,1)                       -0.063615022  0.020189978     -3.15082  0.00162812

11. A(2,2)                        0.258475962  0.018273313     14.14500  0.00000000

12. B(1,1)                        0.948639022  0.006275196    151.17280  0.00000000

13. B(1,2)                        0.016075586  0.005015470      3.20520  0.00134968

14. B(2,1)                        0.016759873  0.006616611      2.53300  0.01130910

15. B(2,2)                        0.953470924  0.005582240    170.80437  0.00000000

 

Eigenvalues from BEKK-Gaussian (    0.98557,    0.00000) (    0.97697,   -0.00679) (    0.97697,    0.00679)

 

Var    JB    P-Value

  1  266.040   0.000

  2 3292.914   0.000

All 3558.954   0.000


 

MV-GARCH, BEKK - Estimation by BFGS

Convergence in    74 Iterations. Final criterion was  0.0000000 <=  0.0000100

 

Irregular Data From 1980:01:02 To 1994:04:01

Usable Observations                      3718

Log Likelihood                     28984.5373

 

    Variable                        Coeff      Std Error      T-Stat      Signif

************************************************************************************

Mean Model(DEMRET)

1.  Constant                     -0.000086045  0.000076731     -1.12138  0.26212556

2.  DEMRET{1}                     0.003503778  0.011771167      0.29766  0.76596445

Mean Model(GBPRET)

3.  Constant                      0.000029887  0.000073638      0.40587  0.68483983

4.  GBPRET{1}                     0.018359843  0.011720040      1.56653  0.11722361

 

5.  C(1,1)                        0.000962449  0.000122075      7.88409  0.00000000

6.  C(2,1)                        0.000707654  0.000137086      5.16212  0.00000024

7.  C(2,2)                       -0.000455501  0.000072080     -6.31935  0.00000000

8.  A(1,1)                        0.289112748  0.024142352     11.97533  0.00000000

9.  A(1,2)                       -0.007043956  0.027323490     -0.25780  0.79656240

10. A(2,1)                       -0.051853003  0.023502632     -2.20626  0.02736554

11. A(2,2)                        0.245709343  0.027364231      8.97922  0.00000000

12. B(1,1)                        0.956476832  0.007047515    135.71832  0.00000000

13. B(1,2)                        0.004568053  0.008632405      0.52918  0.59668404

14. B(2,1)                        0.009988195  0.007467217      1.33761  0.18102485

15. B(2,2)                        0.963674467  0.008396694    114.76833  0.00000000

16. Shape(t degrees)              4.386659383  0.245154125     17.89348  0.00000000

 

Eigenvalues from BEKK-t (    0.99416,   -0.00000) (    0.99325,    0.00447) (    0.99325,   -0.00447)

 

Var    JB    P-Value

  1  266.475   0.000

  2 5099.162   0.000

All 5365.637   0.000


 

Graphs


 


Copyright © 2025 Thomas A. Doan