def test_standardized_forecasts_error(): # Simple test that standardized forecasts errors are calculated correctly. # Just uses a different calculation method on a univariate series. # Get the dataset true = results_kalman_filter.uc_uni data = pd.DataFrame(true['data'], index=pd.date_range('1947-01-01', '1995-07-01', freq='QS'), columns=['GDP']) data['lgdp'] = np.log(data['GDP']) # Fit an ARIMA(1,1,0) to log GDP mod = sarimax.SARIMAX(data['lgdp'], order=(1, 1, 0)) res = mod.fit(disp=-1) standardized_forecasts_error = ( res.filter_results.forecasts_error[0] / np.sqrt(res.filter_results.forecasts_error_cov[0, 0])) assert_allclose( res.filter_results.standardized_forecasts_error[0], standardized_forecasts_error, )
def __init__(self, alternate_timing=True, *args, **kwargs): # Dataset path = current_path + os.sep + 'results/results_wpi1_ar3_stata.csv' self.stata = pd.read_csv(path) self.stata.index = pd.date_range(start='1960-01-01', periods=124, freq='QS') # Matlab comparison path = current_path + os.sep + 'results/results_wpi1_missing_ar3_matlab_ssm.csv' matlab_names = [ 'a1', 'a2', 'a3', 'detP', 'alphahat1', 'alphahat2', 'alphahat3', 'detV', 'eps', 'epsvar', 'eta', 'etavar' ] self.matlab_ssm = pd.read_csv(path, header=None, names=matlab_names) # Regression tests data path = current_path + os.sep + 'results/results_wpi1_missing_ar3_regression.csv' self.regression = pd.read_csv(path) # Create missing observations self.stata['dwpi'] = self.stata['wpi'].diff() self.stata.ix[10:21, 'dwpi'] = np.nan self.model = sarimax.SARIMAX(self.stata.ix[1:, 'dwpi'], order=(3, 0, 0), hamilton_representation=True, *args, **kwargs) if alternate_timing: self.model.timing_init_filtered = True # Parameters from from Stata's sspace MLE estimation params = np.r_[.5270715, .0952613, .2580355, .5307459] self.results = self.model.smooth(params, return_ssm=True) # Calculate the determinant of the covariance matrices (for easy # comparison to other languages without having to store 2-dim arrays) self.results.det_predicted_state_cov = np.zeros((1, self.model.nobs)) self.results.det_smoothed_state_cov = np.zeros((1, self.model.nobs)) for i in range(self.model.nobs): self.results.det_predicted_state_cov[0, i] = np.linalg.det( self.results.predicted_state_cov[:, :, i]) self.results.det_smoothed_state_cov[0, i] = np.linalg.det( self.results.smoothed_state_cov[:, :, i]) # Perform simulation smoothing n_disturbance_variates = ((self.model.k_endog + self.model.k_posdef) * self.model.nobs) self.sim = self.model.simulation_smoother() self.sim.simulate( disturbance_variates=np.zeros(n_disturbance_variates), initial_state_variates=np.zeros(self.model.k_states))
def get_dummy_mod(fit=True, pandas=False): # This tests time-varying parameters regression when in fact the parameters # are not time-varying, and in fact the regression fit is perfect endog = np.arange(100)*1.0 exog = 2*endog if pandas: index = pd.date_range('1960-01-01', periods=100, freq='MS') endog = pd.TimeSeries(endog, index=index) exog = pd.TimeSeries(exog, index=index) mod = sarimax.SARIMAX(endog, exog=exog, order=(0,0,0), time_varying_regression=True, mle_regression=False) if fit: with warnings.catch_warnings(): warnings.simplefilter("ignore") res = mod.fit(disp=-1) else: res = None return mod, res
def test_fit_misc(): true = results_sarimax.wpi1_stationary endog = np.diff(true['data'])[1:] mod = sarimax.SARIMAX(endog, order=(1,0,1), trend='c') # Test optim_hessian={'opg','oim','cs'} with warnings.catch_warnings(): warnings.simplefilter("ignore") res1 = mod.fit(method='ncg', disp=True, optim_hessian='opg') res2 = mod.fit(method='ncg', disp=True, optim_hessian='oim') res3 = mod.fit(method='ncg', disp=True, optim_hessian='cs') assert_raises(NotImplementedError, mod.fit, method='ncg', disp=False, optim_hessian='a') # Check that the Hessians broadly result in the same optimum assert_allclose(res1.llf, res2.llf, rtol=1e-2) assert_allclose(res1.llf, res3.llf, rtol=1e-2) # Test return_params=True mod, _ = get_dummy_mod(fit=False) with warnings.catch_warnings(): warnings.simplefilter("ignore") res_params = mod.fit(disp=-1, return_params=True) assert_almost_equal(res_params, [0,0], 7)
def test_simulate(): # Test for simulation of new time-series from scipy.signal import lfilter # Common parameters nsimulations = 10 sigma2 = 2 measurement_shocks = np.zeros(nsimulations) state_shocks = np.random.normal(scale=sigma2**0.5, size=nsimulations) # Random walk model, so simulated series is just the cumulative sum of # the shocks mod = KalmanFilter(k_endog=1, k_states=1) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. actual = mod.simulate(nsimulations, measurement_shocks=measurement_shocks, state_shocks=state_shocks)[0].squeeze() desired = np.r_[0, np.cumsum(state_shocks)[:-1]] assert_allclose(actual, desired) # Local level model, so simulated series is just the cumulative sum of # the shocks plus the measurement shock mod = KalmanFilter(k_endog=1, k_states=1) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. actual = mod.simulate(nsimulations, measurement_shocks=np.ones(nsimulations), state_shocks=state_shocks)[0].squeeze() desired = np.r_[1, np.cumsum(state_shocks)[:-1] + 1] assert_allclose(actual, desired) # Local level-like model with observation and state intercepts, so # simulated series is just the cumulative sum of the shocks minus the state # intercept, plus the observation intercept and the measurement shock mod = KalmanFilter(k_endog=1, k_states=1) mod['obs_intercept', 0, 0] = 5. mod['design', 0, 0] = 1. mod['state_intercept', 0, 0] = -2. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. actual = mod.simulate(nsimulations, measurement_shocks=np.ones(nsimulations), state_shocks=state_shocks)[0].squeeze() desired = np.r_[1 + 5, np.cumsum(state_shocks - 2)[:-1] + 1 + 5] assert_allclose(actual, desired) # Model with time-varying observation intercept mod = KalmanFilter(k_endog=1, k_states=1, nobs=10) mod['obs_intercept'] = (np.arange(10) * 1.).reshape(1, 10) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. actual = mod.simulate(nsimulations, measurement_shocks=measurement_shocks, state_shocks=state_shocks)[0].squeeze() desired = np.r_[0, np.cumsum(state_shocks)[:-1] + np.arange(1, 10)] assert_allclose(actual, desired) # Model with time-varying observation intercept, check that error is raised # if more simulations are requested than are nobs. mod = KalmanFilter(k_endog=1, k_states=1, nobs=10) mod['obs_intercept'] = (np.arange(10) * 1.).reshape(1, 10) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. assert_raises(ValueError, mod.simulate, nsimulations + 1, measurement_shocks, state_shocks) # ARMA(1,1): phi = [0.1], theta = [0.5], sigma^2 = 2 phi = np.r_[0.1] theta = np.r_[0.5] mod = sarimax.SARIMAX([0], order=(1, 0, 1)) mod.update(np.r_[phi, theta, sigma2]) actual = mod.ssm.simulate(nsimulations, measurement_shocks=measurement_shocks, state_shocks=state_shocks)[0].squeeze() desired = lfilter([1, theta], [1, -phi], np.r_[0, state_shocks[:-1]]) assert_allclose(actual, desired) # SARIMAX(1,0,1)x(1,0,1,4), this time using the results object call mod = sarimax.SARIMAX([0.1, 0.5, -0.2], order=(1, 0, 1), seasonal_order=(1, 0, 1, 4)) res = mod.filter([0.1, 0.5, 0.2, -0.3, 1]) actual = res.simulate(nsimulations, measurement_shocks=measurement_shocks, state_shocks=state_shocks).squeeze() desired = lfilter(res.polynomial_reduced_ma, res.polynomial_reduced_ar, np.r_[0, state_shocks[:-1]]) assert_allclose(actual, desired)
def test_impulse_responses(): # Test for impulse response functions # Random walk: 1-unit impulse response (i.e. non-orthogonalized irf) is 1 # for all periods mod = KalmanFilter(k_endog=1, k_states=1) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. mod['state_cov', 0, 0] = 2. actual = mod.impulse_responses(steps=10) desired = np.ones((11, 1)) assert_allclose(actual, desired) # Random walk: 1-standard-deviation response (i.e. orthogonalized irf) is # sigma for all periods (here sigma^2 = 2) mod = KalmanFilter(k_endog=1, k_states=1) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. mod['state_cov', 0, 0] = 2. actual = mod.impulse_responses(steps=10, orthogonalized=True) desired = np.ones((11, 1)) * 2**0.5 assert_allclose(actual, desired) # Random walk: 1-standard-deviation cumulative response (i.e. cumulative # orthogonalized irf) mod = KalmanFilter(k_endog=1, k_states=1) mod['design', 0, 0] = 1. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. mod['state_cov', 0, 0] = 2. actual = mod.impulse_responses(steps=10, orthogonalized=True, cumulative=True) desired = np.cumsum(np.ones((11, 1)) * 2**0.5)[:, np.newaxis] assert_allclose(actual, desired) # Random walk: 1-unit impulse response (i.e. non-orthogonalized irf) is 1 # for all periods, even when intercepts are present mod = KalmanFilter(k_endog=1, k_states=1) mod['state_intercept', 0] = 100. mod['design', 0, 0] = 1. mod['obs_intercept', 0] = -1000. mod['transition', 0, 0] = 1. mod['selection', 0, 0] = 1. mod['state_cov', 0, 0] = 2. actual = mod.impulse_responses(steps=10) desired = np.ones((11, 1)) assert_allclose(actual, desired) # Univariate model (random walk): test that an error is thrown when # a multivariate or empty "impulse" is sent mod = KalmanFilter(k_endog=1, k_states=1) assert_raises(ValueError, mod.impulse_responses, impulse=1) assert_raises(ValueError, mod.impulse_responses, impulse=[1, 1]) assert_raises(ValueError, mod.impulse_responses, impulse=[]) # Univariate model with two uncorrelated shocks mod = KalmanFilter(k_endog=1, k_states=2) mod['design', 0, 0:2] = 1. mod['transition', :, :] = np.eye(2) mod['selection', :, :] = np.eye(2) mod['state_cov', :, :] = np.eye(2) desired = np.ones((11, 1)) actual = mod.impulse_responses(steps=10, impulse=0) assert_allclose(actual, desired) actual = mod.impulse_responses(steps=10, impulse=1) assert_allclose(actual, desired) # In this case (with sigma=sigma^2=1), orthogonalized is the same as not actual = mod.impulse_responses(steps=10, impulse=0, orthogonalized=True) assert_allclose(actual, desired) # Univariate model with two correlated shocks mod = KalmanFilter(k_endog=1, k_states=2) mod['design', 0, 0:2] = 1. mod['transition', :, :] = np.eye(2) mod['selection', :, :] = np.eye(2) mod['state_cov', :, :] = np.array([[1, 0.5], [0.5, 1.25]]) desired = np.ones((11, 1)) # Non-orthogonalized (i.e. 1-unit) impulses still just generate 1's actual = mod.impulse_responses(steps=10, impulse=0) assert_allclose(actual, desired) actual = mod.impulse_responses(steps=10, impulse=1) assert_allclose(actual, desired) # Orthogonalized (i.e. 1-std-dev) impulses now generate different responses actual = mod.impulse_responses(steps=10, impulse=0, orthogonalized=True) assert_allclose(actual, desired + desired * 0.5) actual = mod.impulse_responses(steps=10, impulse=1, orthogonalized=True) assert_allclose(actual, desired) # Multivariate model with two correlated shocks mod = KalmanFilter(k_endog=2, k_states=2) mod['design', :, :] = np.eye(2) mod['transition', :, :] = np.eye(2) mod['selection', :, :] = np.eye(2) mod['state_cov', :, :] = np.array([[1, 0.5], [0.5, 1.25]]) ones = np.ones((11, 1)) zeros = np.zeros((11, 1)) # Non-orthogonalized (i.e. 1-unit) impulses still just generate 1's, but # only for the appropriate series actual = mod.impulse_responses(steps=10, impulse=0) assert_allclose(actual, np.c_[ones, zeros]) actual = mod.impulse_responses(steps=10, impulse=1) assert_allclose(actual, np.c_[zeros, ones]) # Orthogonalized (i.e. 1-std-dev) impulses now generate different # responses, and only for the appropriate series actual = mod.impulse_responses(steps=10, impulse=0, orthogonalized=True) assert_allclose(actual, np.c_[ones, ones * 0.5]) actual = mod.impulse_responses(steps=10, impulse=1, orthogonalized=True) assert_allclose(actual, np.c_[zeros, ones]) # AR(1) model generates a geometrically declining series mod = sarimax.SARIMAX([0.1, 0.5, -0.2], order=(1, 0, 0)) phi = 0.5 mod.update([phi, 1]) desired = np.cumprod(np.r_[1, [phi] * 10])[:, np.newaxis] # Test going through the model directly actual = mod.ssm.impulse_responses(steps=10) assert_allclose(actual, desired) # Test going through the results object res = mod.filter([phi, 1.]) actual = res.impulse_responses(steps=10) assert_allclose(actual, desired)