*! version 1.3.10 16Dec2001 C F Baum / R Sperling * corr 0711 for r(nobs), * corr 0712 to use all available obs in QD regr * mod 0717 to add Cheung-Lai response surface crit vals, ERS option * mod 0913 to correct SC per R.Sperling * mod 0921 to add MAIC optimal lag length * corr 0922 for markout of initial obs per VLW; published STB-57 * corr 0A27 for calculation of ldty2 in conjunction with in clause; published STB-58 * mod 1616 to add output of variable name, alter table * 1.3.6 : 1620 to return chosen MAIC, SC * 1.3.7 : 1729 for ldty2 indexing * 1.3.8 : 1917 added GENerate option for residuals * 1.3.9 : 1C14 B. Durand located problem using float rather than double * 1.3.10: 1C16 Bugfix for 1.3.9 program define dfgls, rclass version 6 syntax varname(ts) [if] [in] [ , Maxlag(integer -1) GENerate(string) noTrend ERS] local resflag 0 local generat = cond("`generate'" == "", "", "`generate'") if "`generat'" != "" { capture confirm new variable `generat' if _rc { di in r "`generat' already exists: " _c di in r "specify new variable with generate( ) option" exit 110 } local resflag 1 } marksample touse /* get time variables */ _ts timevar, sort markout `touse' `timevar' tsreport if `touse', report if r(N_gaps) { di in red "sample may not contain gaps" exit } tempvar trd y yh iota qdtrd dty yhat tempname nobs cbar alpha vcv cv stat i rzt1 rzt5 rzt10 first count kmax tempname resp10 resp5 ldty2 sldty2 tau t2 if "`trend'"=="notrend" { local trend 0 local stat "mu" } else { local trend 1 local stat "tau" } gen `count'=sum(`touse') local nobs=`count'[_N] if `maxlag'==-1 { * set maxlag via Schwert criterion (Ng/Perron JASA 1995) local maxlag = int(12*(`nobs'/100)^0.25) local kmax = "Maxlag = `maxlag' chosen by Schwert criterion" } else { local kmax "" } if `trend' {gen `trd' = _n} * cbars appropriate for trended, detrended case (follow Stock Hbk Metr fn 9) local cbar -7.0 if `trend' {local cbar -13.5} local alpha = 1+`cbar'/`nobs' qui { *** 1C16 double fix gen double `yh' = `varlist' gen double `y' = `varlist' if `count'==1 gen double `iota' = 1 if `count'==1 if `trend' {gen double `qdtrd' = `trd' if `count'==1} *** 1C16 double fix: replace `y' = `varlist'-`alpha'*L.`varlist' if `count'>1 replace `y' = `yh'-`alpha'*L.`yh' if `count'>1 replace `iota' = 1-`alpha' if `count'>1 if `trend' {replace `qdtrd' = `trd'-`alpha'*L.`trd' if `count'>1} * run the GLS regression to detrend (or demean) the data via quasi-differencing * mod 0712: run over all available observations by relocating additional markout below if `trend' { qui reg `y' `iota' `qdtrd' if `touse', noc} else { qui reg `y' `iota' if `touse', noc} * 0922 correction for missing initial obs gen byte `t2' = 1 if `touse' *** 1729 markout `touse' L(1/`maxl1').`t2' markout `touse' L(1/`maxlag').`t2' * generate OLS residual, not GLS residual, which becomes object of (A)DF regression *** 1C16 double fix: gen double `dty'=`varlist'-_b[`iota'] gen double `dty'=`yh'-_b[`iota'] if `trend' {replace `dty'=`dty'-_b[`qdtrd']*`trd'} * Richard Sperling: sldty2 is used in the calculation of MAIC below * Richard Sperling: See p. 8 in Ng & Perron (2000). * cfb double *** 1729 gen double `ldty2'=sum((L.`dty')^2) if `touse' gen double `ldty2' = (L.`dty')^2 if `touse' * cfb 0A27 ensure that only obs defined by touse are considered qui summarize `ldty2' if `touse',meanonly *** 1729 local sldty2=`ldty2'[r(N)] local sldty2 = r(sum) if `trend' { GetCritE `nobs' } else { GetCritD `nobs'} local rzt1=r(Zt1) local rzt5=r(Zt5) local rzt10=r(Zt10) } di " " * 0712 markout one more to account for lag of delta local maxl1 = `maxlag'+1 markout `touse' L(1/`maxl1').`t2' qui summarize D.`dty' if `touse',meanonly local nobs=r(N) di in gr "DF-GLS for " in ye "`varlist'" _col(30) /* */ in gr "Number of obs = " in ye %5.0f `nobs' if "`kmax'" !="" {di in gr "`kmax'"} di " " local first 1 if `maxlag' == 0 { * run the DF regression, no constant nor trend qui reg D.`dty' L.`dty' if `touse', noc if `resflag' {qui predict double `generat',r} mat `vcv'=e(V) return scalar dft0=_b[L.`dty']/sqrt(`vcv'[1,1]) return scalar rmse0=sqrt(e(rss)/`nobs') if `trend' { GetCritT `nobs' `maxlag' } else { GetCritM `nobs' `maxlag' } local resp5=r(resp5) local resp10=r(resp10) if "`ers'"=="ers" { Out `stat' `first' 0 `return(dft0)' `rzt1' `rzt5' `rzt10'} else { Out `stat' `first' 0 `return(dft0)' `rzt1' `resp5' `resp10'} } else { * loop over lags 1..maxlag local i = `maxlag' local first 1 local bRMSE . local lOpt . local bSC . local lSC . local bmaic . local lmaic . while `i'>0 { * run the ADF regression, no constant nor trend * 1C14: L()D fix qui reg D.`dty' L.`dty' L(1/`i')D.`dty' if `touse', noc if `resflag' { qui predict double `generat',r local resflag 0 } mat `vcv'=e(V) local col=e(df_m) return scalar dft`i'=_b[L.`dty']/sqrt(`vcv'[1,1]) return scalar rmse`i'=sqrt(e(rss)/`nobs') * 1C14: L()D fix local tprob=tprob(e(df_r),_b[L`i'D.`dty']/sqrt(`vcv'[`col',`col'])) if `tprob'<0.10 & `lOpt'==. { local lOpt = `i' local bRMSE = return(rmse`i') } * Calculate SC return scalar sc`i'=log(return(rmse`i')^2)+(`i'+1)*log(`nobs')/`nobs' local lSC = cond(return(sc`i')<`bSC',`i',`lSC') local bSC = min(`bSC',return(sc`i')) * Richard Sperling: Calculate MAIC, but first calculate tau variable * Richard Sperling: See p. 8 in Ng & Perron (2000) local tau = (return(rmse`i')^2)^(-1)*(_b[L.`dty'])^2*`sldty2' return scalar maic`i'=log(return(rmse`i')^2)+2*(`tau'+`i')/`nobs' local lmaic = cond(return(maic`i')<`bmaic',`i',`lmaic') local bmaic = min(`bmaic',return(maic`i')) if `trend' { GetCritT `nobs' `i' } else { GetCritM `nobs' `i' } local resp5=r(resp5) local resp10=r(resp10) if "`ers'"=="ers" { Out `stat' `first' `i' `return(dft`i')' `rzt1' `rzt5' `rzt10'} else { Out `stat' `first' `i' `return(dft`i')' `rzt1' `resp5' `resp10'} local i = `i' - 1 local first 0 * end while over lags } if `maxlag' > 1 { return scalar optlag = `lOpt' di " " if `lOpt' !=. { di in gr "Opt Lag (Ng-Perron seq t) = " %2.0f `lOpt' _col(22) " with RMSE " %9.0g `bRMSE' } else { di in gr "Opt Lag (Ng-Perron seq t) = 0 [use maxlag(0)]" } di in gr "Min SC = " %9.0g `bSC' " at lag " %2.0f `lSC' " with RMSE " %9.0g return(rmse`lSC') di in gr "Min MAIC = " %9.0g `bmaic' " at lag " %2.0f `lmaic' " with RMSE " %9.0g return(rmse`lmaic') return scalar maiclag = `lmaic' return scalar sclag = `lSC' } * end switch over nolags/lags } return scalar N =`nobs' * 1620 correction: should be maxlag, as scalar return scalar maxlag = `maxlag' end program define Out, nclass args stat first lags dft rzt1 rzt5 rzt10 if (`first') { di in gr _col (16) "DF-GLS `stat'" /* */ _col(32) "1% Critical" _col(50) "5% Critical" /* */ _col(67) "10% Critical" di in gr " [lags]" _col (14) "Test Statistic" /* */ _col(36) "Value" _col(54) "Value" _col(72) "Value" di in gr _dup(78) "-" } di in gr _col(5) "`lags'" /* */ _col(14) in ye %10.3f `dft' _col(31) %10.3f `rzt1' /* */ _col(49) %10.3f `rzt5' _col(67) %10.3f `rzt10' end program define GetCritE, rclass * interp values from Elliott et al, Econometrica 64:4 1996 Table 1c args N tempname zt mat `zt' = ( -3.77,-3.58,-3.46,-3.48\ /* */ -3.19,-3.03,-2.93,-2.89\ /* */ -2.89,-2.74,-2.64,-2.57) if `N' <= 50 { local zt1 = `zt'[1,1] local zt5 = `zt'[2,1] local zt10 = `zt'[3,1] } else if `N' <= 100 { local zt1 = `zt'[1,1] + (`N'-50)/50 * (`zt'[1,2]-`zt'[1,1]) local zt5 = `zt'[2,1] + (`N'-50)/50 * (`zt'[2,2]-`zt'[2,1]) local zt10 = `zt'[3,1] + (`N'-50)/50 * (`zt'[3,2]-`zt'[3,1]) } else if `N' <= 200 { local zt1 = `zt'[1,2] + (`N'-100)/100 * (`zt'[1,3]-`zt'[1,2]) local zt5 = `zt'[2,2] + (`N'-100)/100 * (`zt'[2,3]-`zt'[2,2]) local zt10 = `zt'[3,2] + (`N'-100)/100 * (`zt'[3,3]-`zt'[3,2]) } else { local zt1 = `zt'[1,4] local zt5 = `zt'[2,4] local zt10 = `zt'[3,4] } return scalar Zt1 = `zt1' return scalar Zt5 = `zt5' return scalar Zt10 = `zt10' end program define GetCritD, rclass * hacked from official dfuller.ado args N tempname zt mat `zt' = ( -2.66,-2.62,-2.60,-2.58,-2.58,-2.58\ /* */ -1.95,-1.95,-1.95,-1.95,-1.95,-1.95\ /* */ -1.60,-1.61,-1.61,-1.62,-1.62,-1.62) if `N' <= 25 { local zt1 = `zt'[1,1] local zt5 = `zt'[2,1] local zt10 = `zt'[3,1] } else if `N' <= 50 { local zt1 = `zt'[1,1] + (`N'-25)/25 * (`zt'[1,2]-`zt'[1,1]) local zt5 = `zt'[2,1] + (`N'-25)/25 * (`zt'[2,2]-`zt'[2,1]) local zt10 = `zt'[3,1] + (`N'-25)/25 * (`zt'[3,2]-`zt'[3,1]) } else if `N' <= 100 { local zt1 = `zt'[1,2] + (`N'-50)/50 * (`zt'[1,3]-`zt'[1,2]) local zt5 = `zt'[2,2] + (`N'-50)/50 * (`zt'[2,3]-`zt'[2,2]) local zt10 = `zt'[3,2] + (`N'-50)/50 * (`zt'[3,3]-`zt'[3,2]) } else if `N' <= 250 { local zt1 = `zt'[1,3] + (`N'-100)/150 * (`zt'[1,4]-`zt'[1,3]) local zt5 = `zt'[2,3] + (`N'-100)/150 * (`zt'[2,4]-`zt'[2,3]) local zt10 = `zt'[3,3] + (`N'-100)/150 * (`zt'[3,4]-`zt'[3,3]) } else if `N' <= 500 { local zt1 = `zt'[1,4] + (`N'-250)/250 * (`zt'[1,5]-`zt'[1,4]) local zt5 = `zt'[2,4] + (`N'-250)/250 * (`zt'[2,5]-`zt'[2,4]) local zt10 = `zt'[3,4] + (`N'-250)/250 * (`zt'[3,5]-`zt'[3,4]) } else { local zt1 = `zt'[1,6] local zt5 = `zt'[2,6] local zt10 = `zt'[3,6] } return scalar Zt1 = `zt1' return scalar Zt5 = `zt5' return scalar Zt10 = `zt10' end program define GetCritM, rclass * response surface values from Cheung and Lai OBES 1995 Table 1, cols 1-2 args N p tempname rsm mat `rsm' = ( -1.624, -19.888, 155.231, 0.709, 5.480, -16.055 \ /* */ -1.948, -17.839, 104.086, 0.802, 5.558, -18.332 ) local n1 = 1.0/`N' local pt = `p'/`N' local cr10 = `rsm'[1,1] + `rsm'[1,2]*`n1' + `rsm'[1,3]*(`n1'^2) + /* */ `rsm'[1,4]*`pt' + `rsm'[1,5]*(`pt'^2) + `rsm'[1,6]*(`pt'^3) local cr05 = `rsm'[2,1] + `rsm'[2,2]*`n1' + `rsm'[2,3]*(`n1'^2) + /* */ `rsm'[2,4]*`pt' + `rsm'[2,5]*(`pt'^2) + `rsm'[2,6]*(`pt'^3) return scalar resp10 = `cr10' return scalar resp5 = `cr05' end program define GetCritT, rclass * response surface values from Cheung and Lai OBES 1995 Table 1, cols 3-4 args N p tempname rst mat `rst' = ( -2.550, -20.166, 155.215, 1.133, 9.808, -20.313 \ /* */ -2.838, -20.328, 124.191, 1.267, 10.530, -24.600 ) local n1 = 1.0/`N' local pt = `p'/`N' local cr10 = `rst'[1,1] + `rst'[1,2]*`n1' + `rst'[1,3]*(`n1'^2) + /* */ `rst'[1,4]*`pt' + `rst'[1,5]*(`pt'^2) + `rst'[1,6]*(`pt'^3) local cr05 = `rst'[2,1] + `rst'[2,2]*`n1' + `rst'[2,3]*(`n1'^2) + /* */ `rst'[2,4]*`pt' + `rst'[2,5]*(`pt'^2) + `rst'[2,6]*(`pt'^3) return scalar resp10 = `cr10' return scalar resp5 = `cr05' end exit