*! version 1.3.0 17jul2026 kperrony *! Kejriwal-Perron (2010, JBES) tests for multiple structural changes in *! cointegrated regressions and Kejriwal-Perron-Yu (2021, JTSA) two-step *! partial parameter stability tests *! Port of the original MATLAB code by Xuewen Yu (June 2021), Pierre Perron *! code archive, to Stata/Mata. Author: Ozan Eruygur program define kperrony, rclass version 14.0 syntax varlist(numeric ts min=2) [if] [in] [, XZero(varlist numeric ts) LAGs(integer 4) TRend NODOLS NOENDO NOSC LEVel(real 95) NOTWOstep NOAKtest AKREPs(integer 10000) SEED(integer -1) PMseed(integer 0) FULLprecision] * ---------- parse variables (allow time-series operators) ---------- local origvl `varlist' tsrevar `varlist' local vlist `r(varlist)' gettoken yvar zvars : vlist gettoken origy origz : origvl local xvars "" local origx "" if "`xzero'" != "" { local origx `xzero' tsrevar `xzero' local xvars `r(varlist)' } marksample touse markout `touse' `zvars' `xvars' * ---------- tsset checks ---------- quietly tsset if "`r(panelvar)'" != "" { di as error "kperrony requires time-series data (tsset without a panel variable)" exit 198 } local tvar `r(timevar)' local tdelta = r(tdelta) quietly count if `touse' local T0 = r(N) if `T0' == 0 error 2000 quietly summarize `tvar' if `touse', meanonly local tmin = r(min) local tmax = r(max) if (`tmax' - `tmin')/`tdelta' + 1 != `T0' { di as error "estimation sample contains gaps in `tvar'" exit 198 } * ---------- dimensions and critical value availability ---------- local q : word count `zvars' local p : word count `xvars' local ok = 0 if `p' == 0 & inrange(`q', 1, 4) local ok = 1 if `p' == 1 & inrange(`q', 1, 2) local ok = 1 if `p' == 2 & inrange(`q', 1, 2) local ok = 1 if !`ok' { di as error "critical values are available only for p=0 with q=1..4 and (p,q) in {(1,1),(1,2),(2,1),(2,2)}, where q is the number of I(1) regressors and p the number of I(0) regressors in xzero()" exit 198 } * ---------- significance level ---------- local sig "" if `level' == 90 local sig "0.10" if `level' == 95 local sig "0.05" if `level' == 97.5 local sig "0.025" if `level' == 99 local sig "0.01" if "`sig'" == "" { di as error "level() must be 90, 95, 97.5, or 99" exit 198 } * ---------- options ---------- local optr = ("`trend'" != "") local sc = ("`nosc'" == "") if "`noendo'" != "" local nodols nodols local endo = ("`nodols'" == "") if `endo' { if `lags' < 1 | `lags' > 12 { di as error "lags() must be between 1 and 12" exit 198 } local lT = `lags' } else local lT = 0 local dots = ("`notwostep'" == "") local doak = ("`noaktest'" == "") if `akreps' < 10 | `akreps' > 100000 { di as error "akreps() must be between 10 and 100000" exit 198 } if `seed' >= 0 set seed `seed' * ---------- minimal sample checks ---------- if `endo' local Te = `T0' - 2*`lT' - 1 else local Te = `T0' local pq = 1 + `p' + `q' local hh = round(0.15*`Te') if `hh' < `pq' + 2 { di as error "effective sample too small for trimming 0.15 with `pq' breaking coefficients" exit 198 } * ---------- Mata engine ---------- mata: kperrony_main("`yvar'", "`zvars'", "`xvars'", "`touse'", `lT', `endo', `sc', `optr', `sig', `dots', `doak', `akreps', `pmseed') local nb = __kp_nb local Teff = __kp_T local heff = __kp_h local lagdim = __kp_lagdim * ---------- display ---------- local dfmt %12.3f local wS = 12 local HL1 = 50 local HL2 = 41 local HL3 = 62 local HLC = 70 local HLA = 62 if "`fullprecision'" != "" { local dfmt %21.0g local wS = 21 local HL1 = 68 local HL2 = 50 local HL3 = 71 local HLC = 66 local HLA = 66 } local tfmt : format `tvar' di di as text "Kejriwal-Perron (2010) tests for multiple structural changes in cointegrated regression" local ds1 : di `tfmt' `tmin' local ds2 : di `tfmt' `tmax' di as text "Sample: " as result trim("`ds1'") as text " - " as result trim("`ds2'") as text " T = " as result `T0' as text ", effective T = " as result `Teff' di as text "Trimming: " as result "0.15" as text " (h = " as result `heff' as text ") Maximum breaks: " as result "5" as text " Significance level: " as result `=100-`level'' as text "%" if `endo' di as text "Endogeneity correction: " as result "DOLS with `lT' leads/lags" as text " (`lagdim' columns)" else di as text "Endogeneity correction: " as result "none (static regression)" if `sc' di as text "Serial correlation correction: " as result "yes (hybrid QS long-run variance)" else di as text "Serial correlation correction: " as result "no" di as text "Dependent variable: " as result "`origy'" as text " I(1) regressors (q=`q'): " as result "`origz'" if `p' > 0 di as text "I(0) regressors (p=`p'): " as result "`origx'" di di as text "[1] Kejriwal-Perron (2010) tests of H0: no structural change in the cointegrating equation" di as text "{hline `HL1'}" di as text " k " %`wS's "supF(k)" " " %12s "crit. value" " " %`wS's "SSR(k)" di as text "{hline `HL1'}" forvalues k = 1/5 { _kp_stars `=__kp_supf[`k',1]' `=__kp_cvk4[1,`k']' `=__kp_cvk4[2,`k']' `=__kp_cvk4[3,`k']' `=__kp_cvk4[4,`k']' di as text %5.0f `k' " " as result `dfmt' `=__kp_supf[`k',1]' as result %-4s "`st'" as text " " as result %12.2f `=__kp_cvk[`k',1]' as text " " as result `dfmt' `=__kp_ssr[`k',1]' } di as text "{hline `HL1'}" _kp_stars `=__kp_udmax' `=__kp_ud4[1,1]' `=__kp_ud4[2,1]' `=__kp_ud4[3,1]' `=__kp_ud4[4,1]' di as text "UDmax " as result `dfmt' `=__kp_udmax' as result %-4s "`st'" as text " " as result %12.2f `=__kp_udcv' di as text "{hline `HL1'}" if `=__kp_udmax' > `=__kp_udcv' { di as text " Decision: UDmax = " as result %9.3f `=__kp_udmax' as text " > cv = " as result %8.2f `=__kp_udcv' as text " -> at least one break at the `=100-`level''% level;" di as text " the sequential procedure in [2] selects how many." } else { di as text " Decision: UDmax = " as result %9.3f `=__kp_udmax' as text " <= cv = " as result %8.2f `=__kp_udcv' as text " -> no structural break is detected" di as text " at the `=100-`level''% level." } di as text "Estimated break dates by number of breaks k (last observation of each regime):" forvalues k = 1/5 { local dl "" forvalues r = 1/`k' { local idx = __kp_dv[`r',`k'] local tval = `tmin' + (`idx' - 1)*`tdelta' local dst : di `tfmt' `tval' local dst = trim("`dst'") local dl "`dl' `dst'" } di as text " k=" as result `k' as text ":" as result "`dl'" } di if `nb' == 0 { di as text "UDmax test does not reject: no structural breaks detected." } else { di as text "[2] Sequential procedure SEQ(k+1|k) for selecting the number of breaks:" di as text "{hline `HL2'}" di as text " " %-10s "test" %`wS's "statistic" " " %12s "crit. value" di as text "{hline `HL2'}" local nseq = rowsof(__kp_seq) forvalues j = 1/`nseq' { local kk = __kp_seq[`j',1] local lab "SEQ(`=`kk'+1'|`kk')" _kp_stars `=__kp_seq[`j',2]' `=__kp_seqcv4[1,`kk']' `=__kp_seqcv4[2,`kk']' `=__kp_seqcv4[3,`kk']' `=__kp_seqcv4[4,`kk']' di as text " " %-10s "`lab'" as result `dfmt' `=__kp_seq[`j',2]' as result %-4s "`st'" as text " " as result %12.2f `=__kp_seq[`j',3]' } di as text "{hline `HL2'}" di di as text " Decision: SEQ selects " as result `nb' as text " break(s) at the `=100-`level''% level." di di as text "[3] Estimated break dates and regime-wise coefficients:" forvalues j = 1/`nb' { local idx = __kp_brdate[`j',1] local tval = `tmin' + (`idx' - 1)*`tdelta' local dst : di `tfmt' `tval' di as text " Break `j': last observation of regime `j' = " as result trim("`dst'") as text " (obs " as result `idx' as text " of the sample)" } } di local zq = invnormal(1 - (100 - `level')/200) di as text "Regime-wise coefficient estimates with HAC standard errors:" di as text "{hline `HLC'}" if "`fullprecision'" != "" di as text " Regime coefficient " %21s "estimate" " " %21s "HAC s.e." else di as text " Regime coefficient " %12s "estimate" %12s "HAC s.e." %23s "[`level'% conf. interval]" di as text "{hline `HLC'}" local cnames _cons `origx' `origz' local nreg = `nb' + 1 forvalues j = 1/`nreg' { forvalues c = 1/`pq' { local cn : word `c' of `cnames' local bv = __kp_coef[`j',`c'] local sv = __kp_hacse[`j',`c'] if "`fullprecision'" != "" di as text %7.0f `j' " " %-14s "`cn'" as result %21.0g `bv' as result " " %21.0g `sv' else { local lo = `bv' - `zq'*`sv' local hi = `bv' + `zq'*`sv' di as text %7.0f `j' " " %-14s "`cn'" as result %12.3f `bv' as result %12.3f `sv' as result %12.3f `lo' as result %11.3f `hi' } } if `j' < `nreg' di as text "{hline `HLC'}" } di as text "{hline `HLC'}" di as text " HAC standard errors: quadratic spectral kernel with automatic bandwidth" di as text " (Andrews 1991), as in the empirical application of KPY (2021)." if `dots' & `nb' > 0 { di di as text "[4] Kejriwal-Perron-Yu (2021) two-step partial stability tests (step 2, chi-squared):" di as text "{hline `HL3'}" di as text " " %-16s "coefficient" %`wS's "F statistic" " " %12s "chi2 c.v." " " %4s "df" di as text "{hline `HL3'}" local cnames _cons `origx' `origz' forvalues c = 1/`pq' { local cn : word `c' of `cnames' local decision = cond(`=__kp_ts[`c',1]' > `=__kp_ts[`c',2]', "unstable", "stable") if "`decision'" == "unstable" local unstl "`unstl' `cn'" di as text " " %-16s "`cn'" as result `dfmt' `=__kp_ts[`c',1]' as text " " as result %12.3f `=__kp_ts[`c',2]' as text " " as result %4.0f `=__kp_ts[`c',3]' as text " `decision'" } di as text "{hline `HL3'}" di as text "H0: coefficient is stable across regimes, allowing all other coefficients to break at the estimated dates." if "`unstl'" != "" di as text " Decision: coefficients found unstable at the `=100-`level''% level:" as result "`unstl'" else di as text " Decision: no individual coefficient is found unstable at the `=100-`level''% level." } if "`noaktest'" == "" { di di as text "[5] Arai-Kurozumi (2007) test of the null of cointegration with the estimated breaks:" di as text "{hline `HLA'}" if "`fullprecision'" != "" di as text " AK statistic = " as result %21.0g `=__kp_ak' as text " simulated cv (`=100-`level''%) = " as result %21.0g `=__kp_akcv' else di as text " AK statistic = " as result %9.3f `=__kp_ak' as text " simulated cv (`=100-`level''%) = " as result %9.3f `=__kp_akcv' di as text "{hline `HLA'}" if `=__kp_ak' > `=__kp_akcv' { di as text " Decision: the null of cointegration (with the estimated breaks) is" di as text " rejected at the `=100-`level''% level; the regime-wise regression may be" di as text " spurious and the results above should be interpreted with caution." } else { di as text " Decision: the null of cointegration with the estimated breaks is not" di as text " rejected at the `=100-`level''% level." } di as text " Critical value simulated from the asymptotic distribution at the" di as text " estimated break fractions (`akreps' replications)." } di di as text "Note: the tests presuppose that the regressors are I(1) and the errors are I(0)" di as text "throughout the sample. Shifts in the persistence of the individual series can be" di as text "tested with the kypshift package (Kejriwal-Yu-Perron 2020), available from SSC." * ---------- returned results ---------- tempname supftab seqtab brtab coeftab tstab kcol matrix `kcol' = J(5,1,.) forvalues k = 1/5 { matrix `kcol'[`k',1] = `k' } matrix `supftab' = `kcol', __kp_supf, __kp_cvk, __kp_ssr matrix colnames `supftab' = k supF cv SSR return matrix supf = `supftab' if `nb' > 0 { matrix `seqtab' = __kp_seq matrix colnames `seqtab' = k SEQ cv return matrix seq = `seqtab' matrix `brtab' = J(`nb', 2, .) forvalues j = 1/`nb' { matrix `brtab'[`j',1] = __kp_brdate[`j',1] matrix `brtab'[`j',2] = `tmin' + (__kp_brdate[`j',1] - 1)*`tdelta' } matrix colnames `brtab' = obs tvalue return matrix brdates = `brtab' } matrix `coeftab' = __kp_coef tempname setab sdtab matrix `setab' = __kp_hacse return matrix hacse = `setab' matrix `sdtab' = __kp_stdse return matrix stdse = `sdtab' return matrix coef = `coeftab' if `dots' & `nb' > 0 { matrix `tstab' = __kp_ts matrix colnames `tstab' = F chi2cv df return matrix twostep = `tstab' } return matrix datevec = __kp_dv if "`noaktest'" == "" { return scalar ak = __kp_ak return scalar akcv = __kp_akcv return scalar akreps = `akreps' } return scalar nb = `nb' return scalar udmax = __kp_udmax return scalar udmax_cv = __kp_udcv return scalar T = `T0' return scalar Teff = `Teff' return scalar h = `heff' return scalar lags = `lT' return scalar p = `p' return scalar q = `q' return scalar level = `level' return local coefnames "_cons `origx' `origz'" return local depvar "`origy'" return local cmd "kperrony" capture matrix drop __kp_supf __kp_cvk __kp_cvk4 __kp_ud4 __kp_seqcv4 __kp_ssr __kp_seq __kp_brdate __kp_coef __kp_dv __kp_ts __kp_hacse __kp_stdse capture scalar drop __kp_nb __kp_udmax __kp_udcv __kp_T __kp_h __kp_lagdim __kp_ak __kp_akcv end program define _kp_stars args v c1 c2 c3 c4 if `v' > `c4' { c_local st "****" } else if `v' > `c3' { c_local st "***" } else if `v' > `c2' { c_local st "**" } else if `v' > `c1' { c_local st "*" } else c_local st "" end mata: // ------------------------------------------------------------------ // kperrony Mata engine: port of the MATLAB code accompanying // Kejriwal-Perron (2010, JBES) and Kejriwal-Perron-Yu (2021, JTSA) // (dating.m, ssr.m, parti.m, nldat.m, pzbar.m, olsqr.m, leadslag.m, // UDmax.m, seq_nbr.m, pvdel.m, correct.m, psigmq.m, spflp1.m, // onebp.m, pftest.m, twostep.m, get_UDcv.m, get_SEQcv.m) // MATLAB left-to-right operation order is preserved where feasible. // ------------------------------------------------------------------ void kperrony_olsqr(real colvector y, real matrix X, b, res) { b = (luinv(X'*X)*X')*y res = y - X*b } real matrix kperrony_pzbar(real matrix zz, real scalar m, real colvector bb) { real scalar nt, q1, i, d, prev real matrix zb nt = rows(zz) q1 = cols(zz) zb = J(nt, (m+1)*q1, 0) prev = 0 for (i=1; i<=m; i++) { d = bb[i] zb[|prev+1, (i-1)*q1+1 \ d, i*q1|] = zz[|prev+1, 1 \ d, q1|] prev = d } zb[|prev+1, m*q1+1 \ nt, (m+1)*q1|] = zz[|prev+1, 1 \ nt, q1|] return(zb) } real matrix kperrony_leadslag(real matrix z, real scalar lT) { real matrix dz, zlag, lead, lag real scalar n, i dz = z[|2, 1 \ rows(z), cols(z)|] - z[|1, 1 \ rows(z)-1, cols(z)|] n = rows(dz) zlag = dz[|lT+1, 1 \ n-lT, cols(dz)|] for (i=1; i<=lT; i++) { lead = dz[|lT+1+i, 1 \ n-lT+i, cols(dz)|] lag = dz[|lT+1-i, 1 \ n-lT-i, cols(dz)|] zlag = lag, zlag, lead } return(zlag) } real colvector kperrony_ssrvec(real scalar start, real colvector y, real matrix z, real scalar h, real scalar last) { real scalar bigt, r, v, f real colvector vec, delta1, invz, y0, res real matrix inv1, Z0 real rowvector zr bigt = rows(y) vec = J(bigt, 1, 0) Z0 = z[|start, 1 \ start+h-1, cols(z)|] y0 = y[|start \ start+h-1|] inv1 = luinv(Z0'*Z0) delta1 = inv1*(Z0'*y0) res = y0 - Z0*delta1 vec[start+h-1] = res'*res for (r=start+h; r<=last; r++) { zr = z[r, .] v = y[r] - zr*delta1 invz = inv1*zr' f = 1 + zr*invz delta1 = delta1 + invz*(v/f) inv1 = inv1 - (invz*invz')/f vec[r] = vec[r-1] + v*v/f } return(vec) } real scalar kperrony_bigidx(real scalar i, real scalar j, real scalar bigt) { return((i-1)*bigt - i*(i-1)/2 + j) } real colvector kperrony_bigvec(real colvector y, real matrix z, real scalar h, real scalar bigt) { real colvector bigvec, vec real scalar i, j bigvec = J(bigt*(bigt+1)/2, 1, 0) for (i=1; i<=bigt-h+1; i++) { vec = kperrony_ssrvec(i, y, z, h, bigt) for (j=i; j<=bigt; j++) bigvec[kperrony_bigidx(i, j, bigt)] = vec[j] } return(bigvec) } void kperrony_minfirst(real colvector v, real scalar lo, real scalar hi, mval, midx) { real scalar k mval = v[lo] midx = lo for (k=lo+1; k<=hi; k++) { if (v[k] < mval) { mval = v[k] midx = k } } } void kperrony_parti(real scalar start, real scalar b1, real scalar b2, real scalar last, real colvector bigvec, real scalar bigt, ssrmin, dx) { real colvector dvec real scalar j dvec = J(bigt, 1, .) for (j=b1; j<=b2; j++) dvec[j] = bigvec[kperrony_bigidx(start, j, bigt)] + bigvec[kperrony_bigidx(j+1, last, bigt)] kperrony_minfirst(dvec, b1, b2, ssrmin, dx) } void kperrony_dating(real colvector y, real matrix z, real scalar h, real scalar m, real scalar bigt, glb, datevec) { real matrix optdat, optssr real colvector bigvec, dvec real scalar j1, s, d, ib, jlast, jb, mv, mi, i, xx datevec = J(m, m, 0) optdat = J(bigt, m, 0) optssr = J(bigt, m, 0) glb = J(m, 1, 0) bigvec = kperrony_bigvec(y, z, h, bigt) if (m == 1) { s = . d = . kperrony_parti(1, h, bigt-h, bigt, bigvec, bigt, s, d) datevec[1,1] = d glb[1] = s return } for (j1=2*h; j1<=bigt; j1++) { s = . d = . kperrony_parti(1, h, j1-h, j1, bigvec, bigt, s, d) optssr[j1,1] = s optdat[j1,1] = d } glb[1] = optssr[bigt,1] datevec[1,1] = optdat[bigt,1] for (ib=2; ib<=m; ib++) { if (ib == m) { jlast = bigt dvec = J(bigt, 1, .) for (jb=ib*h; jb<=jlast-h; jb++) dvec[jb] = optssr[jb,ib-1] + bigvec[kperrony_bigidx(jb+1, bigt, bigt)] mv = . mi = . kperrony_minfirst(dvec, ib*h, jlast-h, mv, mi) optssr[jlast,ib] = mv optdat[jlast,ib] = mi } else { for (jlast=(ib+1)*h; jlast<=bigt; jlast++) { dvec = J(bigt, 1, .) for (jb=ib*h; jb<=jlast-h; jb++) dvec[jb] = optssr[jb,ib-1] + bigvec[kperrony_bigidx(jb+1, jlast, bigt)] mv = . mi = . kperrony_minfirst(dvec, ib*h, jlast-h, mv, mi) optssr[jlast,ib] = mv optdat[jlast,ib] = mi } } datevec[ib,ib] = optdat[bigt,ib] for (i=1; i<=ib-1; i++) { xx = ib - i datevec[xx,ib] = optdat[datevec[xx+1,ib], xx] } glb[ib] = optssr[bigt,ib] } } void kperrony_nldat(real colvector y, real matrix z, real matrix x, real scalar h, real scalar m, real scalar bigt, glb, datevec) { real scalar p, q, mi, ssr1, ssrn, len, it real matrix zz, zbar, xbar, XX, d0, d1 real colvector g0, g1, teta, teta1, delta1, beta1, e, res, rtmp p = cols(x) q = cols(z) glb = J(m, 1, 0) datevec = J(m, m, 0) for (mi=1; mi<=m; mi++) { zz = x, z g0 = J(0,1,0) d0 = J(0,0,0) kperrony_dating(y, zz, h, mi, bigt, g0, d0) zbar = kperrony_pzbar(z, mi, d0[|1,mi \ mi,mi|]) xbar = kperrony_pzbar(x, mi, d0[|1,mi \ mi,mi|]) teta = J(0,1,0) rtmp = J(0,1,0) kperrony_olsqr(y, (zbar, xbar), teta, rtmp) delta1 = teta[|1 \ q*(mi+1)|] beta1 = J(0,1,0) kperrony_olsqr(y - zbar*delta1, x, beta1, rtmp) e = y - x*beta1 - zbar*delta1 ssr1 = e'*e len = 99999999 it = 1 while (len > 1e-4) { g1 = J(0,1,0) d1 = J(0,0,0) kperrony_dating(y - x*beta1, z, h, mi, bigt, g1, d1) zbar = kperrony_pzbar(z, mi, d1[|1,mi \ mi,mi|]) XX = x, zbar teta1 = J(0,1,0) res = J(0,1,0) kperrony_olsqr(y, XX, teta1, res) beta1 = teta1[|1 \ p|] ssrn = res'*res len = abs(ssrn - ssr1) if (it >= 20) _error("kperrony: iterative estimation of the partial model did not converge") it = it + 1 ssr1 = ssrn glb[mi] = ssrn datevec[|1,mi \ mi,mi|] = d1[|1,mi \ mi,mi|] } } } real scalar kperrony_lrv(real colvector ur, real colvector uu) { real scalar T, rho, a2, eband, sig, lam, j, d, kern real colvector eb, ef T = rows(ur) eb = uu[|1 \ T-1|] ef = uu[|2 \ T|] rho = (eb'*ef)/(eb'*eb) a2 = 4*rho^2/(1-rho)^4 eband = 1.3221*(a2*T)^0.2 sig = ur'*ur lam = 0 for (j=1; j<=T-1; j++) { d = (j/eband)*1.2*pi() kern = ((sin(d)/d - cos(d))/(d^2))*3 lam = lam + (ur[|1 \ T-j|]'*ur[|1+j \ T|])*kern } return((sig + 2*lam)/T) } real scalar kperrony_qskern(real scalar x) { real scalar d d = 6*pi()*x/5 return(3*(sin(d)/d - cos(d))/(d*d)) } real scalar kperrony_bandw(real matrix vhat) { real scalar nt, dd, a2n, a2d, i, b, sig, a2 real colvector yv, xv, e nt = rows(vhat) dd = cols(vhat) a2n = 0 a2d = 0 for (i=1; i<=dd; i++) { yv = vhat[|2, i \ nt, i|] xv = vhat[|1, i \ nt-1, i|] b = (xv'*yv)/(xv'*xv) e = yv - b*xv sig = (e'*e)/(nt-1) a2n = a2n + 4*b*b*sig*sig/(1-b)^8 a2d = a2d + sig*sig/(1-b)^4 } a2 = a2n/a2d return(1.3221*(a2*nt)^0.2) } real matrix kperrony_jhatpr(real matrix vmat) { real scalar nt, dd, st, j real matrix jhat nt = rows(vmat) dd = cols(vmat) st = kperrony_bandw(vmat) jhat = vmat'*vmat for (j=1; j<=nt-1; j++) jhat = jhat + kperrony_qskern(j/st)*(vmat[|j+1, 1 \ nt, dd|]'*vmat[|1, 1 \ nt-j, dd|]) for (j=1; j<=nt-1; j++) jhat = jhat + kperrony_qskern(j/st)*(vmat[|1, 1 \ nt-j, dd|]'*vmat[|j+1, 1 \ nt, dd|]) return(jhat/(nt-dd)) } real matrix kperrony_correct(real matrix reg, real colvector res) { return(kperrony_jhatpr(reg :* res)) } real matrix kperrony_psigmq(real colvector res, real colvector b, real scalar i, real scalar nt) { real matrix sig real colvector r real scalar prev, kk, d sig = J(i+1, i+1, 0) prev = 0 for (kk=1; kk<=i; kk++) { d = b[kk] r = res[|prev+1 \ d|] sig[kk,kk] = (r'*r)/(d-prev) prev = d } r = res[|prev+1 \ nt|] sig[i+1,i+1] = (r'*r)/(nt-prev) return(sig) } real matrix kperrony_pvdel(real colvector y, real matrix z, real scalar i, real scalar q, real scalar bigt, real colvector b, real scalar robust, real matrix x, real scalar p, real scalar withb) { real matrix zbar, reg, sig, gg, irr, hac, rseg real colvector delv, res real scalar K, ie, jj, d, prev zbar = kperrony_pzbar(z, i, b) delv = J(0,1,0) res = J(0,1,0) if (p == 0) { kperrony_olsqr(y, zbar, delv, res) reg = zbar } else { kperrony_olsqr(y, (zbar, x), delv, res) if (withb == 0) reg = zbar - x*(luinv(x'*x)*(x'*zbar)) else reg = x, zbar } if (robust == 0) { if (p == 0) { sig = kperrony_psigmq(res, b, i, bigt) return((sig#I(q))*luinv(reg'*reg)) } else { K = (i+1)*q + p*withb gg = J(K, K, 0) sig = kperrony_psigmq(res, b, i, bigt) prev = 0 for (ie=1; ie<=i+1; ie++) { d = (ie<=i ? b[ie] : bigt) rseg = reg[|prev+1, 1 \ d, cols(reg)|] gg = gg + sig[ie,ie]*(rseg'*rseg) prev = d } irr = luinv(reg'*reg) return(irr*gg*irr) } } else { if (p == 0) { hac = J((i+1)*q, (i+1)*q, 0) prev = 0 for (jj=1; jj<=i+1; jj++) { d = (jj<=i ? b[jj] : bigt) hac[|(jj-1)*q+1, (jj-1)*q+1 \ jj*q, jj*q|] = (d-prev)*kperrony_correct(z[|prev+1, 1 \ d, cols(z)|], res[|prev+1 \ d|]) prev = d } irr = luinv(reg'*reg) return(irr*hac*irr) } else { hac = kperrony_correct(reg, res) irr = luinv(reg'*reg) return(bigt*(irr*hac*irr)) } } } real matrix kperrony_rmat(real scalar i, real scalar k) { real matrix rsub real scalar j rsub = J(i, i+1, 0) for (j=1; j<=i; j++) { rsub[j,j] = -1 rsub[j,j+1] = 1 } return(rsub#I(k)) } void kperrony_udmax(real colvector y, real matrix X, real scalar M, real scalar p, real scalar pq, real scalar bigt, real matrix datevec, real matrix lls, real scalar lagdim, real scalar sc, UDF, supF) { real scalar T, i, robust, lrv, fstar real matrix rmat, zbar, MG, vdel real colvector delta, uu, dbdel supF = J(M, 1, 0) T = rows(y) for (i=1; i<=M; i++) { rmat = kperrony_rmat(i, pq) zbar = kperrony_pzbar(X, i, datevec[|1,i \ i,i|]) delta = J(0,1,0) uu = J(0,1,0) if (lagdim == 0) { kperrony_olsqr(y, zbar, delta, uu) } else { dbdel = J(0,1,0) kperrony_olsqr(y, (zbar, lls), dbdel, uu) delta = dbdel[|1 \ (i+1)*pq|] } if (p != 0) { robust = sc vdel = kperrony_pvdel(y, X, i, pq, bigt, datevec[|1,i \ i,i|], robust, lls, lagdim, 0) fstar = delta'*rmat'*luinv(rmat*vdel*rmat')*rmat*delta supF[i] = (bigt - (i+1)*pq - lagdim)*fstar/(bigt*i) } else { if (lagdim == 0) MG = I(T) else MG = I(T) - lls*luinv(lls'*lls)*lls' vdel = luinv(zbar'*MG*zbar) fstar = delta'*rmat'*luinv(rmat*vdel*rmat')*rmat*delta lrv = kperrony_lrv(uu, uu) supF[i] = (fstar/i)/lrv } } UDF = max(supF) } real scalar kperrony_spflp1p0(real colvector brdate, real scalar m, real colvector y, real matrix X, real scalar h, real scalar pq, real matrix zlag, real scalar lagdim, real scalar trim) { real scalar T, SSR0, best, i, lo, hiend, Ti, hi, t1, s, lrv real colvector dv, b0, ur, b1, uut, uu, nbr real matrix Xbar, nXbar, D0, D1 T = rows(y) dv = 0 \ brdate \ T Xbar = kperrony_pzbar(X, m-1, brdate) if (lagdim > 0) D0 = Xbar, zlag else D0 = Xbar b0 = J(0,1,0) ur = J(0,1,0) kperrony_olsqr(y, D0, b0, ur) SSR0 = ur'*ur best = . uu = ur for (i=1; i<=m; i++) { lo = dv[i] + 1 hiend = dv[i+1] Ti = hiend - lo + 1 hi = min((ceil(Ti*trim), pq+lagdim+1)) t1 = lo + hi while (t1 <= hiend - hi + 1) { nbr = sort((brdate \ t1), 1) nXbar = kperrony_pzbar(X, m, nbr) if (lagdim > 0) D1 = nXbar, zlag else D1 = nXbar b1 = J(0,1,0) uut = J(0,1,0) kperrony_olsqr(y, D1, b1, uut) s = uut'*uut if (s < best) { best = s uu = uut } t1 = t1 + 1 } } lrv = kperrony_lrv(ur, uu) return((SSR0 - best)/lrv) } void kperrony_onebp(real colvector y, real matrix z, real matrix x, real scalar h, real scalar start, real scalar last, ssrind, bd) { real scalar i, bdat, rr, n real matrix zb, D, xs, zs real colvector bb, rres, ys ssrind = . bdat = . n = last - start + 1 ys = y[|start \ last|] zs = z[|start, 1 \ last, cols(z)|] if (cols(x) > 0) xs = x[|start, 1 \ last, cols(x)|] else xs = J(n, 0, 0) i = h while (i <= n - h) { zb = kperrony_pzbar(zs, 1, J(1,1,i)) D = xs, zb bb = J(0,1,0) rres = J(0,1,0) kperrony_olsqr(ys, D, bb, rres) rr = rres'*rres if (rr < ssrind) { ssrind = rr bdat = i } i = i + 1 } bd = bdat + start - 1 } real scalar kperrony_pftest(real colvector y, real matrix z, real scalar q, real scalar bigt, real scalar date, real scalar robust, real matrix x, real scalar p) { real matrix rmat, zbar, vdel real colvector delta, dbdel, rr real scalar fstar rmat = kperrony_rmat(1, q) zbar = kperrony_pzbar(z, 1, J(1,1,date)) delta = J(0,1,0) rr = J(0,1,0) if (p == 0) { kperrony_olsqr(y, zbar, delta, rr) } else { dbdel = J(0,1,0) kperrony_olsqr(y, (zbar, x), dbdel, rr) delta = dbdel[|1 \ 2*q|] } vdel = kperrony_pvdel(y, z, 1, q, bigt, J(1,1,date), robust, x, p, 0) fstar = delta'*rmat'*luinv(rmat*vdel*rmat')*rmat*delta return((bigt - 2*q - p)*fstar/bigt) } real scalar kperrony_spflp1(real colvector dt, real scalar nseg, real colvector y, real matrix z, real scalar h, real scalar q, real scalar robust, real matrix x, real scalar p) { real scalar bigt, maxf, is, len, si, ds, f real colvector dv, yseg real matrix zseg, xseg bigt = rows(z) dv = 0 \ dt \ bigt maxf = 0 for (is=1; is<=nseg; is++) { len = dv[is+1] - dv[is] if (len >= 2*h) { si = . ds = . kperrony_onebp(y, z, x, h, dv[is]+1, dv[is+1], si, ds) yseg = y[|dv[is]+1 \ dv[is+1]|] zseg = z[|dv[is]+1, 1 \ dv[is+1], cols(z)|] if (p == 0) f = kperrony_pftest(yseg, zseg, q, len, ds - dv[is], robust, J(len,0,0), 0) else { xseg = x[|dv[is]+1, 1 \ dv[is+1], cols(x)|] f = kperrony_pftest(yseg, zseg, q, len, ds - dv[is], robust, xseg, p) } if (f > maxf) maxf = f } } return(maxf) } real scalar kperrony_twostep(real colvector y, real matrix z, real matrix x, real matrix Xfull, real colvector testvec, real scalar nb, real colvector brdate, real scalar sc, real scalar endo, real scalar lT) { real scalar i, testdim, K, c, lTe, lagdim, bigt, n0, p, robust, lagrestdim, fstar, lrv real colvector restvec, ebr, ye, dbdel, uu, delta, b0, ur real matrix Xtest, Xrest, zlag, Xrestbar, Xtest_e, Xrest_e, rmat, Xtestbar, D1, Xrz, vdel, D0 i = nb testdim = rows(testvec) K = cols(Xfull) restvec = J(0, 1, 0) for (c=1; c<=K; c++) { if (!anyof(testvec, c)) restvec = restvec \ c } Xtest = Xfull[., testvec'] if (rows(restvec) > 0) Xrest = Xfull[., restvec'] else Xrest = J(rows(Xfull), 0, 0) if (endo == 0) { lTe = 0 zlag = J(rows(y), 0, 0) lagdim = 0 bigt = rows(y) ye = y ebr = brdate if (cols(Xrest) > 0) Xrestbar = kperrony_pzbar(Xrest, i, ebr) else Xrestbar = J(bigt, 0, 0) Xtest_e = Xtest } else { lTe = lT zlag = kperrony_leadslag(z, lTe) bigt = rows(zlag) lagdim = cols(zlag) n0 = rows(y) ye = y[|lTe+2 \ n0-lTe|] Xtest_e = Xtest[|lTe+2, 1 \ n0-lTe, cols(Xtest)|] ebr = brdate :- lTe if (cols(Xrest) > 0) { Xrest_e = Xrest[|lTe+2, 1 \ n0-lTe, cols(Xrest)|] Xrestbar = kperrony_pzbar(Xrest_e, i, ebr) } else Xrestbar = J(bigt, 0, 0) } rmat = kperrony_rmat(i, testdim) Xtestbar = kperrony_pzbar(Xtest_e, i, ebr) D1 = Xtestbar, Xrestbar, zlag dbdel = J(0,1,0) uu = J(0,1,0) kperrony_olsqr(ye, D1, dbdel, uu) delta = dbdel[|1 \ (i+1)*testdim|] p = cols(x) - 1 if (p != 0) { robust = sc Xrz = Xrestbar, zlag lagrestdim = cols(Xrz) vdel = kperrony_pvdel(ye, Xtest_e, i, testdim, bigt, ebr, robust, Xrz, lagrestdim, 0) fstar = delta'*rmat'*luinv(rmat*vdel*rmat')*rmat*delta return((bigt - (i+1)*testdim - lagrestdim)*fstar/(bigt*i)) } else { D0 = Xtest_e, Xrestbar, zlag b0 = J(0,1,0) ur = J(0,1,0) kperrony_olsqr(ye, D0, b0, ur) lrv = kperrony_lrv(ur, uu) return((ur'*ur - uu'*uu)/lrv) } } real scalar kperrony_pmu(state) { state = mod(16807*state, 2147483647) return(state/2147483647) } void kperrony_pmnormfill(real matrix A, state) { real scalar n, i, u1, u2, r, th, z1, z2 n = rows(A)*cols(A) i = 1 while (i <= n) { u1 = kperrony_pmu(state) u2 = kperrony_pmu(state) r = sqrt(-2*ln(u1)) th = 2*pi()*u2 z1 = r*cos(th) z2 = r*sin(th) A[mod(i-1, rows(A)) + 1, floor((i-1)/rows(A)) + 1] = z1 i = i + 1 if (i <= n) { A[mod(i-1, rows(A)) + 1, floor((i-1)/rows(A)) + 1] = z2 i = i + 1 } } } real scalar kperrony_akstats(real colvector y, real matrix x) { real scalar T, k, nume, rho, a1, a2, bw, lam, sig, s, omega real matrix invxx real colvector b, res, sqcs T = rows(x) k = cols(x) invxx = luinv(x'*x) b = invxx*(x'*y) res = y - x*b sqcs = runningsum(res):^2 nume = sum(sqcs)/T^2 rho = (res[|1 \ T-1|]'*res[|2 \ T|])/(res[|1 \ T-1|]'*res[|1 \ T-1|]) a1 = 1.1447*((4*rho^2*T)/((1+rho)^2*(1-rho)^2))^(1/3) a2 = 1.1447*((4*0.81*T)/((1.9)^2*(0.1)^2))^(1/3) bw = min((a1, a2)) lam = 0 sig = res'*res for (s=1; s<=floor(bw); s++) lam = lam + (1 - s/(floor(bw)+1))*(res[|s+1 \ T|]'*res[|1 \ T-s|]) omega = (sig + 2*lam)/T return(nume/omega) } real scalar kperrony_akcv(real scalar q, real scalar brnum, real colvector brdate, real scalar T, real scalar siglev, real scalar mrep, real scalar pmseed) { real scalar TT, mm, i, t1, t2, Glast, usepm, state real colvector lamv, V, w1, G, w1i, g1i, brvec, dw real matrix w2, w, wi, sV TT = 2000 usepm = (pmseed > 0) state = pmseed if (brnum > 0) lamv = brdate/T else lamv = J(0, 1, 0) V = J(mrep, 1, 0) for (mm=1; mm<=mrep; mm++) { w1 = J(TT, 1, 0) w2 = J(TT, q, 0) if (usepm) { kperrony_pmnormfill(w1, state) kperrony_pmnormfill(w2, state) } else { w1 = rnormal(TT, 1, 0, 1) w2 = rnormal(TT, q, 0, 1) } w1 = runningsum(w1)/sqrt(TT) for (i=1; i<=q; i++) w2[., i] = runningsum(w2[., i])/sqrt(TT) w = J(TT, 1, 1), w2 if (brnum > 0) brvec = 0 \ floor(lamv*TT) \ TT else brvec = 0 \ TT G = J(TT, 1, 0) for (i=1; i<=brnum+1; i++) { t1 = brvec[i] + 1 t2 = brvec[i+1] wi = w[|t1, 1 \ t2, cols(w)|] w1i = w1[|t1 \ t2|] dw = 0 \ (w1i[|2 \ rows(w1i)|] - w1i[|1 \ rows(w1i)-1|]) g1i = luinv(wi'*wi)*(wi'*dw) if (i != 1) Glast = G[t1-1] else Glast = 0 G[|t1 \ t2|] = Glast :+ runningsum(wi*g1i) } V[mm] = mean((w1 - G):^2) } sV = sort(V, 1) return(sV[ceil((1-siglev)*mrep)]) } void kperrony_regout(real colvector y, real matrix D, real scalar pq, real scalar nb, coefs, hacse, stdse) { real scalar T, k, sigsq real matrix invxx, vmat, hacv, varcov real colvector b, res, hs, ss real scalar jj T = rows(D) k = cols(D) invxx = luinv(D'*D) b = invxx*(D'*y) res = y - D*b sigsq = (res'*res)/(T - k) varcov = sigsq*invxx vmat = D :* res hacv = T*invxx*kperrony_jhatpr(vmat)*invxx hs = J(k, 1, 0) ss = J(k, 1, 0) for (jj=1; jj<=k; jj++) { hs[jj] = sqrt(hacv[jj,jj]) ss[jj] = sqrt(varcov[jj,jj]) } coefs = J(nb+1, pq, 0) hacse = J(nb+1, pq, 0) stdse = J(nb+1, pq, 0) for (jj=1; jj<=nb+1; jj++) { coefs[jj, .] = b[|(jj-1)*pq+1 \ jj*pq|]' hacse[jj, .] = hs[|(jj-1)*pq+1 \ jj*pq|]' stdse[jj, .] = ss[|(jj-1)*pq+1 \ jj*pq|]' } } real matrix kperrony_udcvtab(real scalar p, real scalar q) { if (p==0 & q==1) return((10.34, 8.85, 7.66, 6.66, 5.3, 10.53, 11.18, 9.25, 8.09, 6.95, 5.53, 11.33 \ 12.11, 9.96, 8.6, 7.36, 5.9, 12.25, 13.03, 10.39, 8.94, 7.6, 6.12, 13.07 \ 13.85, 11.41, 9.4, 7.99, 6.42, 13.91, 15.08, 11.49, 9.66, 8.28, 6.67, 15.13 \ 17.03, 12.41, 10.4, 8.71, 7.08, 17.4, 16.86, 12.73, 10.82, 8.95, 7.32, 16.86)) else if (p==0 & q==2) return((12.36, 11.01, 9.6, 8.45, 6.96, 12.64, 11.88, 10.31, 9.0, 7.98, 6.62, 12.13 \ 14.3, 12.11, 10.41, 9.19, 7.64, 14.47, 13.63, 11.34, 9.94, 8.68, 7.31, 13.99 \ 15.72, 13.37, 11.26, 9.75, 8.15, 15.9, 15.51, 12.57, 10.86, 9.37, 7.92, 15.53 \ 17.67, 14.73, 12.21, 10.77, 8.82, 17.67, 17.31, 14.63, 12.1, 10.51, 8.73, 17.31)) else if (p==0 & q==3) return((14.88, 12.84, 11.49, 10.19, 8.53, 15.09, 14.39, 12.14, 10.79, 9.61, 8.22, 14.65 \ 16.66, 14.11, 12.38, 10.94, 9.12, 16.71, 16.5, 13.22, 11.66, 10.33, 8.92, 16.61 \ 18.32, 15.24, 13.01, 11.52, 9.61, 18.35, 18.08, 14.45, 12.54, 11.04, 9.44, 18.24 \ 20.78, 16.29, 14.36, 12.37, 10.23, 20.78, 20.28, 15.55, 13.8, 12.02, 10.1, 20.28)) else if (p==0 & q==4) return((16.87, 14.72, 13.2, 11.75, 9.9, 17.05, 16.27, 13.8, 12.41, 11.17, 9.62, 16.46 \ 19.08, 15.9, 14.15, 12.68, 10.72, 19.16, 18.36, 15.08, 13.38, 12.07, 10.28, 18.46 \ 20.81, 17.15, 15.21, 13.38, 11.43, 20.89, 20.52, 17.01, 14.33, 12.98, 10.93, 20.52 \ 22.59, 18.85, 16.44, 14.25, 11.98, 22.59, 23.12, 18.71, 15.77, 13.87, 11.72, 23.12)) else if (p==1 & q==1) return((11.69, 9.88, 8.63, 7.52, 6.27, 11.99, 11.98, 10.29, 8.96, 7.83, 6.63, 12.27 \ 13.24, 10.96, 9.62, 8.29, 6.87, 13.43, 13.74, 11.64, 9.92, 8.66, 7.28, 14.06 \ 14.78, 12.1, 10.54, 8.99, 7.56, 14.87, 15.86, 12.85, 10.87, 9.3, 7.87, 15.91 \ 17.28, 13.4, 11.53, 9.75, 8.11, 17.39, 17.99, 14.27, 11.87, 10.2, 8.44, 17.99)) else if (p==1 & q==2) return((13.85, 12.05, 10.48, 9.35, 7.99, 14.23, 13.42, 11.33, 10.06, 9.0, 7.73, 13.64 \ 15.91, 13.45, 11.5, 10.23, 8.64, 16.07, 15.42, 12.76, 11.03, 9.86, 8.44, 15.47 \ 17.68, 14.6, 12.44, 11.06, 9.3, 18.06, 17.5, 13.95, 12.05, 10.58, 8.97, 17.5 \ 19.89, 16.02, 13.8, 11.88, 10.14, 20.03, 19.61, 15.23, 13.05, 11.38, 9.59, 19.61)) else if (p==2 & q==1) return((12.88, 11.06, 9.55, 8.53, 7.52, 13.26, 13.24, 11.17, 9.79, 8.85, 7.69, 13.51 \ 15.1, 12.13, 10.53, 9.42, 8.16, 15.25, 15.16, 12.19, 10.85, 9.61, 8.29, 15.2 \ 17.51, 13.04, 11.3, 9.98, 8.71, 17.6, 16.89, 13.33, 11.59, 10.48, 8.87, 16.89 \ 19.1, 14.68, 12.35, 11.07, 9.51, 19.1, 18.95, 14.43, 12.79, 11.23, 9.9, 18.95)) else if (p==2 & q==2) return((14.82, 13.09, 11.64, 10.4, 9.04, 15.24, 14.91, 12.5, 11.14, 10.06, 8.83, 15.28 \ 17.02, 14.49, 12.51, 11.19, 9.73, 17.33, 17.17, 14.02, 12.23, 10.91, 9.59, 17.22 \ 19.59, 15.57, 13.39, 11.85, 10.29, 19.59, 19.48, 15.41, 13.18, 11.57, 10.23, 19.48 \ 21.66, 17.07, 14.35, 12.81, 10.85, 21.66, 21.46, 16.5, 14.18, 12.6, 10.82, 21.46)) _error("kperrony: no critical values for this p,q combination") } real matrix kperrony_seqcvtab(real scalar p, real scalar q) { if (p==0 & q==1) return((12.0, 12.94, 13.74, 14.53, 15.23, 12.94, 13.99, 14.93, 15.5, 15.73 \ 13.78, 15.25, 16.38, 17.02, 17.7, 15.01, 15.85, 16.53, 16.86, 17.04 \ 16.38, 17.7, 18.24, 18.53, 19.18, 16.53, 17.04, 17.17, 17.43, 18.04 \ 18.53, 19.33, 19.92, 20.5, 21.34, 17.43, 18.58, 19.11, 19.22, 19.54)) else if (p==0 & q==2) return((14.26, 15.02, 15.64, 16.02, 16.51, 13.57, 14.78, 15.4, 15.87, 16.12 \ 15.65, 16.61, 17.12, 17.66, 17.85, 15.51, 16.18, 17.08, 17.31, 17.5 \ 17.12, 17.85, 18.22, 19.04, 19.27, 17.08, 17.5, 19.27, 19.62, 19.7 \ 19.04, 19.35, 19.9, 19.99, 20.01, 19.62, 19.79, 21.52, 22.58, 22.75)) else if (p==0 & q==3) return((16.64, 17.57, 18.28, 18.86, 19.53, 16.38, 17.3, 17.92, 18.4, 18.62 \ 18.3, 19.58, 20.21, 20.77, 21.45, 17.99, 18.74, 19.77, 20.28, 20.89 \ 20.21, 21.45, 22.67, 23.36, 23.48, 19.77, 20.89, 21.56, 22.11, 22.28 \ 23.36, 23.52, 24.13, 24.43, 25.16, 22.11, 22.37, 22.83, 23.98, 24.54)) else if (p==0 & q==4) return((18.96, 19.91, 20.68, 21.13, 21.51, 18.29, 19.54, 20.43, 20.97, 21.32 \ 20.8, 21.59, 22.36, 22.58, 23.12, 20.51, 21.81, 22.4, 23.12, 23.78 \ 22.36, 23.12, 24.1, 25.73, 26.11, 22.4, 23.78, 25.1, 25.75, 25.84 \ 25.73, 27.01, 27.43, 27.47, 27.75, 25.75, 26.36, 26.66, 26.86, 27.71)) else if (p==1 & q==1) return((13.18, 13.92, 14.7, 15.08, 15.79, 13.72, 15.14, 15.72, 16.44, 16.75 \ 14.72, 15.82, 16.6, 17.28, 17.61, 15.73, 16.83, 17.54, 17.99, 18.17 \ 16.6, 17.61, 19.2, 19.43, 19.85, 17.54, 18.17, 19.27, 19.97, 20.53 \ 19.43, 20.02, 21.38, 21.43, 22.1, 19.97, 21.13, 22.77, 23.42, 23.98)) else if (p==1 & q==2) return((15.82, 16.69, 17.59, 18.15, 18.39, 15.21, 16.54, 17.44, 17.98, 18.46 \ 17.68, 18.63, 19.37, 19.89, 20.39, 17.49, 18.49, 19.26, 19.61, 20.27 \ 19.37, 20.39, 21.48, 22.63, 22.84, 19.26, 20.27, 20.76, 21.69, 22.03 \ 22.63, 23.82, 24.73, 25.4, 25.62, 21.69, 22.37, 22.94, 24.08, 24.08)) else if (p==2 & q==1) return((15.06, 16.32, 17.39, 17.83, 18.22, 15.09, 16.21, 16.85, 17.33, 17.85 \ 17.44, 18.25, 18.65, 19.1, 19.96, 16.86, 17.87, 18.81, 18.95, 19.28 \ 18.65, 19.96, 20.06, 20.37, 20.69, 18.81, 19.28, 19.66, 21.1, 21.43 \ 20.37, 20.73, 21.96, 23.13, 23.22, 21.1, 21.61, 22.74, 23.7, 24.12)) else if (p==2 & q==2) return((16.95, 18.69, 19.46, 20.06, 20.44, 17.12, 18.56, 19.4, 19.92, 20.75 \ 19.48, 20.44, 21.33, 21.66, 21.97, 19.45, 20.42, 21.16, 21.46, 22.33 \ 21.33, 21.97, 22.39, 23.52, 24.03, 21.16, 21.86, 22.89, 23.41, 23.85 \ 23.52, 24.11, 24.75, 25.05, 25.12, 23.41, 23.85, 25.06, 25.94, 26.32)) _error("kperrony: no critical values for this p,q combination") } real scalar kperrony_sigrow(real scalar sig) { if (abs(sig - 0.10) < 1e-9) return(1) if (abs(sig - 0.05) < 1e-9) return(2) if (abs(sig - 0.025) < 1e-9) return(3) if (abs(sig - 0.01) < 1e-9) return(4) _error("kperrony: invalid significance level") } void kperrony_main(string scalar yname, string scalar znames, string scalar xnames, string scalar tousename, real scalar lT, real scalar endo, real scalar sc, real scalar optr, real scalar sig, real scalar dots, real scalar doak, real scalar akreps, real scalar pmseed) { real colvector y, ye, glb, supF, e, brml, orig, bb, rr, cvk real matrix z, xraw, x, X, zlag, datevec, cvtab, seqtab, seqres, Xb, coefs, dvorig, tsres, Xfull, hacse, stdse, Dse real scalar T0, M, trim, p, q, T, h, pq, lagdim, lTe, UDF, UDcv, srow, nb, stopk, i, supfl, cvs, jj, kk, r2, c, Fv, df, cvchi, akstat, akcv y = st_data(., yname, tousename) z = st_data(., tokens(znames), tousename) if (xnames != "") xraw = st_data(., tokens(xnames), tousename) else xraw = J(rows(y), 0, 0) x = J(rows(y), 1, 1), xraw T0 = rows(y) M = 5 trim = 0.15 p = cols(x) - 1 q = cols(z) glb = J(0,1,0) datevec = J(0,0,0) if (endo == 0) { X = x, z pq = cols(X) zlag = J(T0, 0, 0) lagdim = 0 lTe = 0 T = T0 h = round(trim*T) kperrony_dating(y, X, h, M, T, glb, datevec) ye = y } else { lTe = lT zlag = kperrony_leadslag(z, lTe) T = rows(zlag) lagdim = cols(zlag) X = x[|lTe+2, 1 \ T0-lTe, cols(x)|], z[|lTe+2, 1 \ T0-lTe, cols(z)|] ye = y[|lTe+2 \ T0-lTe|] pq = cols(X) h = round(trim*T) kperrony_nldat(ye, X, zlag, h, M, T, glb, datevec) } UDF = . supF = J(0,1,0) kperrony_udmax(ye, X, M, p, pq, T, datevec, zlag, lagdim, sc, UDF, supF) cvtab = kperrony_udcvtab(p, q) srow = kperrony_sigrow(sig) UDcv = cvtab[srow, optr*6 + 6] cvk = cvtab[|srow, optr*6+1 \ srow, optr*6+5|]' seqtab = kperrony_seqcvtab(p, q) seqres = J(0, 3, 0) if (UDF <= UDcv) nb = 0 else { stopk = 0 i = 1 nb = . while (stopk == 0 & i <= M) { if (p != 0) supfl = kperrony_spflp1(datevec[|1,i \ i,i|], i+1, ye, X, h, pq, sc, zlag, lagdim) else supfl = kperrony_spflp1p0(datevec[|1,i \ i,i|], i+1, ye, X, h, pq, zlag, lagdim, trim) cvs = seqtab[srow, optr*5 + i] seqres = seqres \ (i, supfl, cvs) if (supfl <= cvs) { stopk = 1 nb = i } i = i + 1 } if (i == M + 1) nb = M } if (nb > 0) { e = datevec[|1,nb \ nb,nb|] brml = e :+ lTe if (endo == 1) orig = e :+ (lTe + 1) else orig = e } else { e = J(0,1,0) brml = J(0,1,0) orig = J(0,1,0) } if (nb > 0) { Dse = kperrony_pzbar((x, z), nb, brml) if (endo == 1) Dse = Dse[|lTe+2, 1 \ T0-lTe, cols(Dse)|] } else Dse = X if (lagdim > 0) Dse = Dse, zlag coefs = J(0,0,0) hacse = J(0,0,0) stdse = J(0,0,0) kperrony_regout(ye, Dse, pq, nb, coefs, hacse, stdse) dvorig = J(M, M, .) for (kk=1; kk<=M; kk++) { for (r2=1; r2<=kk; r2++) { if (endo == 1) dvorig[r2,kk] = datevec[r2,kk] + lTe + 1 else dvorig[r2,kk] = datevec[r2,kk] } } tsres = J(0, 3, .) if (dots & nb > 0) { Xfull = x, z for (c=1; c<=cols(Xfull); c++) { Fv = kperrony_twostep(y, z, x, Xfull, J(1,1,c), nb, brml, sc, endo, lTe) df = nb cvchi = invchi2(df, 1 - sig) tsres = tsres \ (Fv, cvchi, df) } } st_numscalar("__kp_nb", nb) st_numscalar("__kp_udmax", UDF) st_numscalar("__kp_udcv", UDcv) st_numscalar("__kp_T", T) st_numscalar("__kp_h", h) st_numscalar("__kp_lagdim", lagdim) st_matrix("__kp_supf", supF) st_matrix("__kp_cvk", cvk) st_matrix("__kp_cvk4", cvtab[|1, optr*6+1 \ 4, optr*6+5|]) st_matrix("__kp_ud4", cvtab[|1, optr*6+6 \ 4, optr*6+6|]) st_matrix("__kp_seqcv4", seqtab[|1, optr*5+1 \ 4, optr*5+5|]) st_matrix("__kp_ssr", glb) st_matrix("__kp_seq", rows(seqres) > 0 ? seqres : J(1,3,.)) st_matrix("__kp_brdate", rows(orig) > 0 ? orig : J(1,1,.)) st_matrix("__kp_coef", coefs) akstat = . akcv = . if (doak) { akstat = kperrony_akstats(ye, Dse) akcv = kperrony_akcv(q, nb, (nb > 0 ? brml : J(0,1,0)), rows(Dse), sig, akreps, pmseed) } st_numscalar("__kp_ak", akstat) st_numscalar("__kp_akcv", akcv) st_matrix("__kp_hacse", hacse) st_matrix("__kp_stdse", stdse) st_matrix("__kp_dv", dvorig) st_matrix("__kp_ts", rows(tsres) > 0 ? tsres : J(1,3,.)) } end