def test_recursive_olsresiduals_bad_input(reset_randomstate): from statsmodels.tsa.arima.model import ARIMA e = np.random.standard_normal(250) y = e.copy() for i in range(1, y.shape[0]): y[i] += 0.1 + 0.8 * y[i - 1] + e[i] res = ARIMA(y[20:], order=(1,0,0), trend="c").fit() with pytest.raises(TypeError, match="res a regression results instance"): recursive_olsresiduals(res)
def test_cusum(): mod = RecursiveLS(endog, exog) res = mod.fit() # Test the cusum statistics against those from R (strucchange) # These values are not even close to ours, to Statas, or to the alternate # statsmodels values # assert_allclose(res.cusum, results_R['cusum']) # Test the cusum statistics against Stata (cusum6) # Note: cusum6 excludes the first 3 elements due to OLS initialization # whereas we exclude only the first 2. Also there are initialization # differences (as seen above in the recursive residuals). # Here we explicitly reverse engineer our cusum to match their to show the # equivalence d = res.nobs_diffuse cusum = res.cusum * np.std(res.resid_recursive[d:], ddof=1) cusum -= res.resid_recursive[d] cusum /= np.std(res.resid_recursive[d + 1:], ddof=1) cusum = cusum[1:] assert_allclose(cusum, results_stata.iloc[3:]['cusum'], atol=1e-6, rtol=1e-5) # Test the cusum statistics against statsmodels estimates mod_ols = OLS(endog, exog) res_ols = mod_ols.fit() desired_cusum = recursive_olsresiduals(res_ols)[-2][1:] assert_allclose(res.cusum, desired_cusum, rtol=1e-6) # Test the cusum bounds against Stata (cusum6) # Again note that cusum6 excludes the first 3 elements, so we need to # change the ddof and points. actual_bounds = res._cusum_significance_bounds(alpha=0.05, ddof=1, points=np.arange( d + 1, res.nobs)) desired_bounds = results_stata.iloc[3:][['lw', 'uw']].T assert_allclose(actual_bounds, desired_bounds, rtol=1e-6) # Test the cusum bounds against statsmodels actual_bounds = res._cusum_significance_bounds(alpha=0.05, ddof=0, points=np.arange( d, res.nobs)) desired_bounds = recursive_olsresiduals(res_ols)[-1] assert_allclose(actual_bounds, desired_bounds) # Test for invalid calls assert_raises(ValueError, res._cusum_squares_significance_bounds, alpha=0.123)
def test_resid_recursive(): mod = RecursiveLS(endog, exog) res = mod.fit() # Test the recursive residuals against those from R (strucchange) # Due to initialization issues, we get more agreement as we get # farther from the initial values. assert_allclose(res.resid_recursive[2:10].T, results_R.iloc[:8]['rec_resid'], atol=1e-2, rtol=1e-3) assert_allclose(res.resid_recursive[9:20].T, results_R.iloc[7:18]['rec_resid'], atol=1e-3, rtol=1e-4) assert_allclose(res.resid_recursive[19:].T, results_R.iloc[17:]['rec_resid'], atol=1e-4, rtol=1e-4) # Test the RLS estimates against those from Stata (cusum6) assert_allclose(res.resid_recursive[3:], results_stata.iloc[3:]['rr'], atol=1e-3) # Test the RLS estimates against statsmodels estimates mod_ols = OLS(endog, exog) res_ols = mod_ols.fit() desired_resid_recursive = recursive_olsresiduals(res_ols)[4][2:] assert_allclose(res.resid_recursive[2:], desired_resid_recursive, atol=1e-4, rtol=1e-4)
def test_recursive_residuals(self): reccumres_standardize = np.array([ -2.151, -3.748, -3.114, -3.096, -1.865, -2.230, -1.194, -3.500, -3.638, -4.447, -4.602, -4.631, -3.999, -4.830, -5.429, -5.435, -6.554, -8.093, -8.567, -7.532, -7.079, -8.468, -9.320, -12.256, -11.932, -11.454, -11.690, -11.318, -12.665, -12.842, -11.693, -10.803, -12.113, -12.109, -13.002, -11.897, -10.787, -10.159, -9.038, -9.007, -8.634, -7.552, -7.153, -6.447, -5.183, -3.794, -3.511, -3.979, -3.236, -3.793, -3.699, -5.056, -5.724, -4.888, -4.309, -3.688, -3.918, -3.735, -3.452, -2.086, -6.520, -7.959, -6.760, -6.855, -6.032, -4.405, -4.123, -4.075, -3.235, -3.115, -3.131, -2.986, -1.813, -4.824, -4.424, -4.796, -4.000, -3.390, -4.485, -4.669, -4.560, -3.834, -5.507, -3.792, -2.427, -1.756, -0.354, 1.150, 0.586, 0.643, 1.773, -0.830, -0.388, 0.517, 0.819, 2.240, 3.791, 3.187, 3.409, 2.431, 0.668, 0.957, -0.928, 0.327, -0.285, -0.625, -2.316, -1.986, -0.744, -1.396, -1.728, -0.646, -2.602, -2.741, -2.289, -2.897, -1.934, -2.532, -3.175, -2.806, -3.099, -2.658, -2.487, -2.515, -2.224, -2.416, -1.141, 0.650, -0.947, 0.725, 0.439, 0.885, 2.419, 2.642, 2.745, 3.506, 4.491, 5.377, 4.624, 5.523, 6.488, 6.097, 5.390, 6.299, 6.656, 6.735, 8.151, 7.260, 7.846, 8.771, 8.400, 8.717, 9.916, 9.008, 8.910, 8.294, 8.982, 8.540, 8.395, 7.782, 7.794, 8.142, 8.362, 8.400, 7.850, 7.643, 8.228, 6.408, 7.218, 7.699, 7.895, 8.725, 8.938, 8.781, 8.350, 9.136, 9.056, 10.365, 10.495, 10.704, 10.784, 10.275, 10.389, 11.586, 11.033, 11.335, 11.661, 10.522, 10.392, 10.521, 10.126, 9.428, 9.734, 8.954, 9.949, 10.595, 8.016, 6.636, 6.975 ]) rr = smsdia.recursive_olsresiduals(self.res, skip=3, alpha=0.95) assert_equal(np.round(rr[5][1:], 3), reccumres_standardize) #extra zero in front #assert_equal(np.round(rr[3][4:], 3), np.diff(reccumres_standardize)) assert_almost_equal(rr[3][4:], np.diff(reccumres_standardize), 3) assert_almost_equal(rr[4][3:].std(ddof=1), 10.7242, decimal=4) #regression number, visually checked with graph from gretl ub0 = np.array( [13.37318571, 13.50758959, 13.64199346, 13.77639734, 13.91080121]) ub1 = np.array( [39.44753774, 39.58194162, 39.7163455, 39.85074937, 39.98515325]) lb, ub = rr[6] assert_almost_equal(ub[:5], ub0, decimal=7) assert_almost_equal(lb[:5], -ub0, decimal=7) assert_almost_equal(ub[-5:], ub1, decimal=7) assert_almost_equal(lb[-5:], -ub1, decimal=7) #test a few values with explicit OLS endog = self.res.model.endog exog = self.res.model.exog params = [] ypred = [] for i in range(3, 10): resi = OLS(endog[:i], exog[:i]).fit() ypred.append(resi.model.predict(resi.params, exog[i])) params.append(resi.params) assert_almost_equal(rr[2][3:10], ypred, decimal=12) assert_almost_equal(rr[0][3:10], endog[3:10] - ypred, decimal=12) assert_almost_equal(rr[1][2:9], params, decimal=12)
def test_cusum(): mod = RecursiveLS(endog, exog) res = mod.fit() # Test the cusum statistics against those from R (strucchange) # These values are not even close to ours, to Statas, or to the alternate # statsmodels values # assert_allclose(res.cusum, results_R['cusum']) # Test the cusum statistics against Stata (cusum6) # Note: cusum6 excludes the first 3 elements due to OLS initialization # whereas we exclude only the first 2. Also there are initialization # differences (as seen above in the recursive residuals). # Here we explicitly reverse engineer our cusum to match their to show the # equivalence d = res.nobs_diffuse cusum = res.cusum * np.std(res.resid_recursive[d:], ddof=1) cusum -= res.resid_recursive[d] cusum /= np.std(res.resid_recursive[d+1:], ddof=1) cusum = cusum[1:] assert_allclose(cusum, results_stata.iloc[3:]['cusum'], atol=1e-6, rtol=1e-5) # Test the cusum statistics against statsmodels estimates mod_ols = OLS(endog, exog) res_ols = mod_ols.fit() desired_cusum = recursive_olsresiduals(res_ols)[-2][1:] assert_allclose(res.cusum, desired_cusum, rtol=1e-6) # Test the cusum bounds against Stata (cusum6) # Again note that cusum6 excludes the first 3 elements, so we need to # change the ddof and points. actual_bounds = res._cusum_significance_bounds( alpha=0.05, ddof=1, points=np.arange(d+1, res.nobs)) desired_bounds = results_stata.iloc[3:][['lw', 'uw']].T assert_allclose(actual_bounds, desired_bounds, rtol=1e-6) # Test the cusum bounds against statsmodels actual_bounds = res._cusum_significance_bounds( alpha=0.05, ddof=0, points=np.arange(d, res.nobs)) desired_bounds = recursive_olsresiduals(res_ols)[-1] assert_allclose(actual_bounds, desired_bounds) # Test for invalid calls assert_raises(ValueError, res._cusum_squares_significance_bounds, alpha=0.123)
def test_recursive_residuals(self): reccumres_standardize = np.array([-2.151, -3.748, -3.114, -3.096, -1.865, -2.230, -1.194, -3.500, -3.638, -4.447, -4.602, -4.631, -3.999, -4.830, -5.429, -5.435, -6.554, -8.093, -8.567, -7.532, -7.079, -8.468, -9.320, -12.256, -11.932, -11.454, -11.690, -11.318, -12.665, -12.842, -11.693, -10.803, -12.113, -12.109, -13.002, -11.897, -10.787, -10.159, -9.038, -9.007, -8.634, -7.552, -7.153, -6.447, -5.183, -3.794, -3.511, -3.979, -3.236, -3.793, -3.699, -5.056, -5.724, -4.888, -4.309, -3.688, -3.918, -3.735, -3.452, -2.086, -6.520, -7.959, -6.760, -6.855, -6.032, -4.405, -4.123, -4.075, -3.235, -3.115, -3.131, -2.986, -1.813, -4.824, -4.424, -4.796, -4.000, -3.390, -4.485, -4.669, -4.560, -3.834, -5.507, -3.792, -2.427, -1.756, -0.354, 1.150, 0.586, 0.643, 1.773, -0.830, -0.388, 0.517, 0.819, 2.240, 3.791, 3.187, 3.409, 2.431, 0.668, 0.957, -0.928, 0.327, -0.285, -0.625, -2.316, -1.986, -0.744, -1.396, -1.728, -0.646, -2.602, -2.741, -2.289, -2.897, -1.934, -2.532, -3.175, -2.806, -3.099, -2.658, -2.487, -2.515, -2.224, -2.416, -1.141, 0.650, -0.947, 0.725, 0.439, 0.885, 2.419, 2.642, 2.745, 3.506, 4.491, 5.377, 4.624, 5.523, 6.488, 6.097, 5.390, 6.299, 6.656, 6.735, 8.151, 7.260, 7.846, 8.771, 8.400, 8.717, 9.916, 9.008, 8.910, 8.294, 8.982, 8.540, 8.395, 7.782, 7.794, 8.142, 8.362, 8.400, 7.850, 7.643, 8.228, 6.408, 7.218, 7.699, 7.895, 8.725, 8.938, 8.781, 8.350, 9.136, 9.056, 10.365, 10.495, 10.704, 10.784, 10.275, 10.389, 11.586, 11.033, 11.335, 11.661, 10.522, 10.392, 10.521, 10.126, 9.428, 9.734, 8.954, 9.949, 10.595, 8.016, 6.636, 6.975]) rr = smsdia.recursive_olsresiduals(self.res, skip=3, alpha=0.95) assert_equal(np.round(rr[5][1:], 3), reccumres_standardize) #extra zero in front #assert_equal(np.round(rr[3][4:], 3), np.diff(reccumres_standardize)) assert_almost_equal(rr[3][4:], np.diff(reccumres_standardize),3) assert_almost_equal(rr[4][3:].std(ddof=1), 10.7242, decimal=4) #regression number, visually checked with graph from gretl ub0 = np.array([ 13.37318571, 13.50758959, 13.64199346, 13.77639734, 13.91080121]) ub1 = np.array([ 39.44753774, 39.58194162, 39.7163455 , 39.85074937, 39.98515325]) lb, ub = rr[6] assert_almost_equal(ub[:5], ub0, decimal=7) assert_almost_equal(lb[:5], -ub0, decimal=7) assert_almost_equal(ub[-5:], ub1, decimal=7) assert_almost_equal(lb[-5:], -ub1, decimal=7) #test a few values with explicit OLS endog = self.res.model.endog exog = self.res.model.exog params = [] ypred = [] for i in range(3,10): resi = OLS(endog[:i], exog[:i]).fit() ypred.append(resi.model.predict(resi.params, exog[i])) params.append(resi.params) assert_almost_equal(rr[2][3:10], ypred, decimal=12) assert_almost_equal(rr[0][3:10], endog[3:10] - ypred, decimal=12) assert_almost_equal(rr[1][2:9], params, decimal=12)
def test_resid_recursive(): mod = RecursiveLS(endog, exog) res = mod.fit() # Test the recursive residuals against those from R (strucchange) assert_allclose(res.resid_recursive[2:10].T, results_R.iloc[:8]['rec_resid']) assert_allclose(res.resid_recursive[9:20].T, results_R.iloc[7:18]['rec_resid']) assert_allclose(res.resid_recursive[19:].T, results_R.iloc[17:]['rec_resid']) # Test the RLS estimates against those from Stata (cusum6) assert_allclose(res.resid_recursive[3:], results_stata.iloc[3:]['rr'], atol=1e-5, rtol=1e-5) # Test the RLS estimates against statsmodels estimates mod_ols = OLS(endog, exog) res_ols = mod_ols.fit() desired_resid_recursive = recursive_olsresiduals(res_ols)[4][2:] assert_allclose(res.resid_recursive[2:], desired_resid_recursive)
def test_resid_recursive(): mod = RecursiveLS(endog, exog) res = mod.fit() # Test the recursive residuals against those from R (strucchange) assert_allclose(res.resid_recursive[2:10].T, results_R.iloc[:8]['rec_resid']) assert_allclose(res.resid_recursive[9:20].T, results_R.iloc[7:18]['rec_resid']) assert_allclose(res.resid_recursive[19:].T, results_R.iloc[17:]['rec_resid']) # Test the RLS estimates against those from Stata (cusum6) assert_allclose(res.resid_recursive[3:], results_stata.iloc[3:]['rr'], atol=1e-5, rtol=1e-5) # Test the RLS estimates against statsmodels estimates mod_ols = OLS(endog, exog) res_ols = mod_ols.fit() desired_resid_recursive = recursive_olsresiduals(res_ols)[4][2:] assert_allclose(res.resid_recursive[2:], desired_resid_recursive)
def test_resid_recursive(): mod = RecursiveLS(endog, exog) res = mod.fit() # Test the recursive residuals against those from R (strucchange) # Due to initialization issues, we get more agreement as we get # farther from the initial values. assert_allclose(res.resid_recursive[2:10].T, results_R.iloc[:8]['rec_resid'], atol=1e-2, rtol=1e-3) assert_allclose(res.resid_recursive[9:20].T, results_R.iloc[7:18]['rec_resid'], atol=1e-3, rtol=1e-4) assert_allclose(res.resid_recursive[19:].T, results_R.iloc[17:]['rec_resid'], atol=1e-4, rtol=1e-4) # Test the RLS estimates against those from Stata (cusum6) assert_allclose(res.resid_recursive[3:], results_stata.iloc[3:]['rr'], atol=1e-3) # Test the RLS estimates against statsmodels estimates mod_ols = OLS(endog, exog) res_ols = mod_ols.fit() desired_resid_recursive = recursive_olsresiduals(res_ols)[4][2:] assert_allclose(res.resid_recursive[2:], desired_resid_recursive, atol=1e-4, rtol=1e-4)
# stack x = np.concatenate((x1,x2),0) y = np.concatenate((y1,y2)) if example_groups == '2': groupind = (np.arange(2*nobs)>nobs-1).astype(int) else: groupind = np.mod(np.arange(2*nobs),4) groupind.sort() #x = np.column_stack((x,x*groupind[:,None])) res1 = sm.OLS(y, x).fit() skip = 8 rresid, rparams, rypred, rresid_standardized, rresid_scaled, rcusum, rcusumci = \ recursive_olsresiduals(res1, skip) print(rcusum) print(rresid_scaled[skip-1:]) assert_almost_equal(rparams[-1], res1.params) import matplotlib.pyplot as plt plt.plot(rcusum) plt.plot(rcusumci[0]) plt.plot(rcusumci[1]) plt.figure() plt.plot(rresid) plt.plot(np.abs(rresid)) print('cusum test reject:') print(((rcusum[1:]>rcusumci[1])|(rcusum[1:]<rcusumci[0])).any())
# stack x = np.concatenate((x1, x2), 0) y = np.concatenate((y1, y2)) if example_groups == '2': groupind = (np.arange(2 * nobs) > nobs - 1).astype(int) else: groupind = np.mod(np.arange(2 * nobs), 4) groupind.sort() #x = np.column_stack((x,x*groupind[:,None])) res1 = sm.OLS(y, x).fit() skip = 8 rresid, rparams, rypred, rresid_standardized, rresid_scaled, rcusum, rcusumci = \ recursive_olsresiduals(res1, skip) print rcusum print rresid_scaled[skip - 1:] assert_almost_equal(rparams[-1], res1.params) import matplotlib.pyplot as plt plt.plot(rcusum) plt.plot(rcusumci[0]) plt.plot(rcusumci[1]) plt.figure() plt.plot(rresid) plt.plot(np.abs(rresid)) print 'cusum test reject:' print((rcusum[1:] > rcusumci[1]) | (rcusum[1:] < rcusumci[0])).any()