/***************************************************************************** **** Testing for Cointegration under Structural Breaks **** This file implements the tests described in "Tests for cointegration with structural breaks based on subsamples" by James Davidson and Andrea Monticini (http://people.ex.ac.uk/jehd201/minmintest.pdf) A total of 14 tests are available, for models with one or two regressors and intercept with optional trend. These are the seven subsampling variants described in the paper, implemented with a choice of two test statistics, the augmented Dickey Fuller test (ADF), and the Phillips-Perron (1988) nonparametric test(PP). The tests are tabulated for the minima of the statistics over subsamples defined by pairs {L1, L2} (start = [L1.T]+1, end = [L2.T]) as follows. QS: {0, 0.5} and {0.5, 1} QS*: {0, 0.5}, {0.5, 1} and {0,1} QI(0.5): {0, L2}, 0.5 <= L2 <= 1} and {L1, 1}, 0 <= L1 <= 0.5} QI(0.35): {0, L2}, 0.35 <= L2 <= 1} and {L1, 1}, 0 <= L1 <= 0.65} QI(0.2): {0, L2}, 0.2 <= L2 <= 1 and {L1, 1}, 0 <= L1 <= 0.8 QR(0.5): {L1, L1 + 0.5}, 0 <= L1 <= 0.5 QR(0.5): {L1, L1 + 0.5}, 0 <= L1 <= 0.5 and {0,1} Critical values for other cases have not yet been tabulated, but TSM can be used to generate additional tables as required. TO IMPLEMENT A TEST: 1. Open the dialog Model / Dynamic Equation. 2. Select a dependent variable, and one or two regressors of Type 1. 3. Open the Model / Coded Equations dialog. 4. Select the 'Statistic' radio button, under Supplied Ox Functions. 5 Select the test required by name, using the Next and Previous buttons to move through the list. 6. In the Model / Dynamic Equation diolog, check the 'Coded Function' checkbox. 7. Select the settings required for autocorrelation correction, as follows. PP test: choose the kernel and bandwidth in the Options / Tests and Diagnostics dialog. ADF test: the lag length can be selected in two ways. * To maximize a model selection criterion. The choice set is 0,...,0.6T^(1/3), where T denotes the subsample length (NOT the full sample size). Choose from the Akaike, Schwarz and Hannan Quinn criteria using the radio buttons in Options / Tests and Diagnostics, Model Selection Criteria. * Manually. Choose the option "None" under 'Model Selection Criteria', and set the lag length as for Type 1 regressors in Model / Dynamic Equation. 8. Choose the (overall) test sample by pressing the <<< Sample >>> button in Model / Dynamic Equation and moving the slider. 9. (Optional) Open the Model Manager dialog, click 'Store Current Model' and enter a name to identify the specifications. The setup can then be recalled at any time using 'Load Model'. 10. To Run the test, press the 'Run' or 'Evaluate' buttons on the tool bar, or press 'Go' in Model / Dynamic Equation. OUTPUTS: 1. The chosen statistic(s), with p-value(s) (expressed as inequalities) drawn from the included tabulations. When a single test is run the corresponding subsample is reported. 2. The regular full sample test (PP or ADF) and p-value inequality 3. The test of I(1) (PP or ADF) applied to the normalized (LHS) variable in the test and p-value inequality. NOTE: The signs of the statistics are reversed so that the rejection region corresponds to the upper tail. This is to allow p-values to be calculated in the usual way. ADDITIONAL OPTION: Test each variable in the set for I(1) (same statistic as for main test, PP or ADF) and normalize the regression on the case having the largest statistic. * Implement this option by naming parameter P[0] as 'Option' in Model / Coded Function (any name will serve). Then set P[0] = 1 in the Values / Equation dialog. CAUTION: The reported I(1) test is for this 'best' case, hence it does not have its nominal distribution. Ignore the p-value! *********************************************************************************/ extern run_olsc1(const vY, const mX, const vB); extern PP(const vcData, const dBW, const iType); extern ADFTest(const vcData, const iMaxlag, const iType); #include decl CRITVALS = { // 0: 0 regressors, intercept // 0.5 0.9 0.95 0.975 0.99 < 1.58238 , 2.583435, 2.878835, 3.14468, 3.447755 ; // DF 1.99951 , 2.87323 , 3.12748 , 3.375115, 3.668695 ; // QS 2.12464 , 2.98233 , 3.252595, 3.49584, 3.779345 ; // QS* 2.7265 , 3.597255, 3.85981 , 4.10037, 4.371325 ; // QI0.5 2.913435, 3.75304 , 4.01498 , 4.22723, 4.499695 ; // QI0.35 3.07985 , 3.865275, 4.110185, 4.319465, 4.59499 ; // QI0.2 2.88944 , 3.70529 , 3.95335 , 4.1824, 4.451945 ; // QR 2.89506 , 3.71634 , 3.966 , 4.18452, 4.4632 >, // QR* // 1: 0 regressors, intercept + trend // 0.5 0.9 0.95 0.975 0.99 < 2.19146 , 3.13294 , 3.43312 , 3.69237 , 4.0062 ; // DF 2.58651 , 3.41958 , 3.67591 , 3.90661 , 4.18857 ; // QS 2.72697 , 3.53719 , 3.78825 , 4.01648 , 4.30177 ; // QS* 3.32647 , 4.12508 , 4.37525 , 4.60617 , 4.87558 ; // QI0.5 3.48251 , 4.24329 , 4.48749 , 4.70351 , 4.97589 ; // QI0.35 3.63877 , 4.36689 , 4.59682 , 4.81717 , 5.06626 ; // QI0.2 3.43497 , 4.19928 , 4.43885 , 4.667 , 4.92938 ; // QR 3.44637 , 4.21069 , 4.45026 , 4.67841 , 4.92938 >, // QR* // 2: 1 regressor, intercept // 0.5 0.9 0.95 0.975 0.99 < 2.07266 , 3.06435 , 3.367295, 3.62166 , 3.91182 ; //ADF1 2.48687 , 3.346105, 3.616015, 3.8432 , 4.138005 ; //QS 2.61854 , 3.463695, 3.73189 , 3.96511 , 4.26828 ; //QS* 3.212635, 4.05839 , 4.30122 , 4.541975, 4.815155 ; //QI0.5 3.39617 , 4.200435, 4.452855, 4.668355, 4.941585 ; //QI0.35 3.563505, 4.32718 , 4.56742 , 4.772375, 5.03685 ; //QI0.2 3.34064 , 4.155415, 4.406395, 4.61776 , 4.88134 ; //QR 3.36463 , 4.159445, 4.3989 , 4.623925, 4.877685 >, //QR* // 3: 1 regressor + trend // 0.5 0.9 0.95 0.975 0.99 < 2.55217, 3.50336 , 3.79355 , 4.0515 , 4.35782 ; //DF 2.95916 , 3.79132 , 4.06121 , 4.29736 , 4.57849 ; //QS 3.08246 , 3.90957 , 4.16585 , 4.39884 , 4.66678 ; //QS* 3.6728 , 4.48019 , 4.7449 , 4.95668 , 5.22139 ; //QI0.5 3.84076 , 4.60268 , 4.86055 , 5.07154 , 5.32942 ; //QI0.35 3.99951 , 4.73577 , 4.96893 , 5.17754 , 5.43523 ; //QI0.2 3.78188 , 4.56328 , 4.80274 , 5.01699 , 5.29426 ; //QR 3.79448 , 4.56328 , 4.80274 , 5.0422 , 5.29426 >, //QR* // 4: 2 regressors, intercept // 0.5 0.9 0.95 0.975 0.99 < 2.478845, 3.466265, 3.778275, 4.028405, 4.340415 ; // DF 2.89262 , 3.74902 , 4.015005, 4.263515, 4.56164 ; // QS 3.03658 , 3.87548 , 4.134525, 4.375695, 4.652605 ; // QS* 3.62775 , 4.454475, 4.710335, 4.94175 , 5.20273 ; // QI0.5 3.79156 , 4.58551 , 4.83209 , 5.035185, 5.292485 ; // QI0.35 3.95213 , 4.708695, 4.947085, 5.14407 , 5.40068 ; // QI0.2 3.726 , 4.535305, 4.782855, 4.99685 , 5.249915 ; // QR 3.751055, 4.540825, 4.78837 , 5.016385, 5.269455 >, // QR* // 5: 2 regressors, intercept + trend // 0.5 0.9 0.95 0.975 0.99 < 2.88484 , 3.85633 , 4.15525 , 4.39438 , 4.6933 ; // DF 3.29425 , 4.14108 , 4.40723 , 4.64918 , 4.92742 ; // QS 3.4292 , 4.26052 , 4.52108 , 4.75682 , 5.05461 ; // QS* 4.00663 , 4.81757 , 5.07307 , 5.30635 , 5.57296 ; // QI0.5 4.16875 , 4.94402 , 5.18768 , 5.42026 , 5.68606 ; // QI0.35 4.33656 , 5.06655 , 5.30015 , 5.52402 , 5.77708 ; // QI0.2 4.09769 , 4.89366 , 5.14793 , 5.35798 , 5.61225 ; // QR 4.11791 , 4.90409 , 5.15178 , 5.36717 , 5.61487 >}; // QR* MinMinNames() { return {"PP-QS Test", "PP-QS* Test", "PP-QI(0.5) Test", "PP-QI(0.35) Test", "PP-QI(0.2) Test", "PP-QR(0.5) Test", "PP-QR*(0.5) Test", "All PP-Q Tests", "ADF-QS Test", "ADF-QS* Test", "ADF-QI(0.5) Test", "ADF-QI(0.35) Test", "ADF-QI(0.2) Test", "ADF-QR(0.5) Test", "ADF-QR*(0.5) Test", "All ADF-Q Tests"}; } CheckData(const mDataset, const vVars) { decl bgn = 0, end = rows(mDataset) - 1; for (decl k=0; k 0 && ismissing(mDataset[end][vVars[k]])) end--; for (decl j=bgn; j < end; j++) if (ismissing(mDataset[j][vVars[k]])) bgn = j+1; } return bgn~end; } PPStat(const y, const x) { decl res = y - x*invertsym(x'x)*x'y; decl bw = HAC_BANDWIDTH; return PP(res, &bw, 0)[0]; } ADFStat(const y, const x, const lags) { decl beta; run_olsc1(y, x, &beta); decl stat = ADFTest(y - x*beta, lags, 0); return stat[0]; } CointStat(const y, const x, const lags ) { if (lags == -1) return PPStat(y, x); else return ADFStat(y, x, lags); } MinMin_Test(const y, const x, const lags, const init, const rolling, const star, const cStart, const sSample) { decl crit, t0, minmin, n = rows(y); if (rolling) t0 = floor(n/2); else t0 = floor(init*n); if (rolling < 0) { crit = zeros(1, 3); if (star) crit[0] = -CointStat(y, x, lags); else crit[0] = -100; crit[1] = -CointStat(y[:t0][], x[:t0][], lags); crit[2] = -CointStat(y[t0+1:][], x[t0+1:][], lags); minmin = limits(crit'); if (minmin[3][0] == 0) sSample[0] = (1+ cStart)~(n + cStart); else if (minmin[3][0] == 1) sSample[0] = (1 + cStart)~(t0 + cStart); else sSample[0] = (t0 + cStart + 1)~(n + cStart); } else { crit = zeros(2,n-t0); if (rolling) { for (decl t = 0; t < n-t0; t += 5) { crit[0][t] = -CointStat(y[t:t+t0-1][], x[t:t+t0-1][], lags); } minmin = limits(crit'); sSample[0] = int(minmin[3][0] + 1 + cStart) ~int(minmin[3][0] + t0 + cStart); } else { for (decl t = t0; t minmin[1][1]) sSample[0] = (1 + cStart)~int(minmin[3][0] + t0 + 1 + cStart); else sSample[0] = int(minmin[3][1] + 1 + cStart + t0)~(n + cStart); } } if (rolling) return minmin[1][0]; else return max(minmin[1][0], minmin[1][1]); } Do_MinTests(const tests, const y, const x, const lags, const cStart, const Sample) { decl init = 0, rolling = 0, star = 0; if (tests > 1) { if (tests > 4) { if (tests > 5) star = 1; rolling = 1; init = 0.5; } else { if (tests > 3) init = 0.2; else if (tests > 2) init = 0.35; else init = 0.5; } } else { rolling = -1; if (tests > 0) star = 1; } decl sample; decl stat = MinMin_Test(y, x, lags, init, rolling, star, cStart, &sample); Sample[0] = sample; return stat; } Run_MinTests(const vParam, const mcDataset, const cStart, const cEnd, const cTests, const Norm, const bMode) { decl crit; decl lags; decl tests = cTests; if (tests > 7) // ADF { if (!INFO_CRIT) lags = REGR1_LAGS; else lags = (cEnd - cStart + 1)^(1/3); tests -= 8; } else lags = -1; //PP if (!bMode) { decl regs = columns(REGRESSORS_1)*2 + TREND; if (tests == 7) { crit = constant(-1, 1, 9)|zeros(5,9); crit[1:][:6] = (CRITVALS[regs][1:][])'; crit[1:][7] = (CRITVALS[regs][0][])'; crit [1:][8] = (CRITVALS[TREND][0][])'; } else { crit = constant(-1, 1, 3)|zeros(5,3); crit[1:][0] = (CRITVALS[regs][tests+1][])'; crit[1:][1] = (CRITVALS[regs][0][])'; crit[1:][2] = (CRITVALS[TREND][0][])'; } UserStore({cTests, crit, cStart, cEnd}); } decl stat = 0, y, yy = <>; decl nvar = 1+columns(REGRESSORS_1); decl x = ones(cEnd - cStart + 1, 1); if (TREND) x ~= range(1, cEnd-cStart+1); decl best, lim, loc, pretest = zeros(nvar, 1); if (vParam[0]) { yy = mcDataset[cStart:cEnd][VarNum(SERIES)~VarNum(REGRESSORS_1)]; for (decl j = 0; j < nvar; j++) pretest[j] = -CointStat(yy[][j], x, lags); lim = limits(pretest); best = lim[0]; loc = lim[2]; for (decl k=0; k; for (decl j=0; j<7; j++) stat ~= Do_MinTests(j, y, x, lags, cStart, &sample); } else stat = Do_MinTests(tests, y, x, lags, cStart, &sample); stat ~= -CointStat(y, x, lags); stat ~= best; if (!bMode) { decl names; if (tests == 7) { if (lags == -1) names = UserStatistic_Names()[:6]; else names = UserStatistic_Names()[8:14]; } else names = { UserStatistic_Names()[cTests] }; if (lags != -1) names ~= "ADF Statistic" ; else names ~= "PP Statistic" ; names ~= "I(1) test (PP)"; if (tests < 7) names ~= sprint("Sample ", sample[0], "-", sample[1]); return {stat, names}; } else return stat; } MinMinTest(const vParam, const mcDataset, const cStart, const cEnd, const aName, const bMode) { decl start, end, crit = 0, test = 0, stat, names, type, norm = 0; decl statnames = UserStatistic_Names(); decl j, name = aName[0]; decl cache = UserRetrieve(); if (!isarray(cache) || !bMode) { for (j=0; j columns(statnames)) { PrintCall(1, "Test name ", aName[0], " not recognised"); return; } } else { test = cache[0]; crit = cache[1]; start = cache[2]; end = cache[3]; } INTERCEPT_1 = 1; if (!bMode) { decl varnames = SERIES~REGRESSORS_1; decl lims = CheckData(mcDataset, VarNum(varnames)); start = max(cStart, lims[0]); end = min(cEnd, lims[1]); if (end <= start) { PrintCall(1, "No Sample!"); return; } [stat, names] = Run_MinTests(vParam, mcDataset, start, end, test, &norm, bMode); type = sprint(" for ", varnames[norm], " on\n"); for (j=0; j