def test_transform_untransform(self): true_constrained = self.true_params # Sometimes the parameters given by Stata are not stationary and / or # invertible, so we need to skip those transformations for those # parameter sets self.model.update(self.true_params) contracted_polynomial_seasonal_ar = self.model.polynomial_seasonal_ar[self.model.polynomial_seasonal_ar.nonzero()] self.model.enforce_stationarity = ( (self.model.k_ar == 0 or tools.is_invertible(np.r_[1, -self.model.polynomial_ar[1:]])) and (len(contracted_polynomial_seasonal_ar) <= 1 or tools.is_invertible(np.r_[1, -contracted_polynomial_seasonal_ar[1:]])) ) contracted_polynomial_seasonal_ma = self.model.polynomial_seasonal_ma[self.model.polynomial_seasonal_ma.nonzero()] self.model.enforce_invertibility = ( (self.model.k_ma == 0 or tools.is_invertible(np.r_[1, -self.model.polynomial_ma[1:]])) and (len(contracted_polynomial_seasonal_ma) <= 1 or tools.is_invertible(np.r_[1, -contracted_polynomial_seasonal_ma[1:]])) ) unconstrained = self.model.untransform_params(true_constrained) constrained = self.model.transform_params(unconstrained) assert_almost_equal(constrained, true_constrained, 4) self.model.enforce_stationarity = True self.model.enforce_invertibility = True
def validate_params(self, params): """ Validate parameter vector by raising ValueError on invalid values. Parameters ---------- params : array_like Array of model parameters. Notes ----- Primarily checks that the parameters have the right shape and are not NaN or infinite. Also checks if parameters are consistent with a stationary process if `enforce_stationarity=True` and that they are consistent with an invertible process if `enforce_invertibility=True`. Finally, checks that the variance term is positive, unless `concentrate_scale=True`. Examples -------- >>> spec = SARIMAXSpecification(ar_order=1) >>> spec.validate_params([-0.5, 4.]) # returns None >>> spec.validate_params([-0.5, -2]) ValueError: Non-positive variance term. >>> spec.validate_params([-1.5, 4.]) ValueError: Non-stationary autoregressive polynomial. """ # Note: split_params includes basic validation params = self.split_params(params) # Specific checks if self.enforce_stationarity: if self.k_ar_params: ar_poly = np.r_[1, -params['ar_params']] if not is_invertible(ar_poly): raise ValueError('Non-stationary autoregressive' ' polynomial.') if self.k_seasonal_ar_params: seasonal_ar_poly = np.r_[1, -params['seasonal_ar_params']] if not is_invertible(seasonal_ar_poly): raise ValueError('Non-stationary seasonal autoregressive' ' polynomial.') if self.enforce_invertibility: if self.k_ma_params: ma_poly = np.r_[1, params['ma_params']] if not is_invertible(ma_poly): raise ValueError('Non-invertible moving average' ' polynomial.') if self.k_seasonal_ma_params: seasonal_ma_poly = np.r_[1, params['seasonal_ma_params']] if not is_invertible(seasonal_ma_poly): raise ValueError('Non-invertible seasonal moving average' ' polynomial.') if not self.concentrate_scale: if params['sigma2'] <= 0: raise ValueError('Non-positive variance term.')
def is_stationary(self): """(bool) Is the reduced autoregressive lag poylnomial stationary.""" validate_basic(self.ar_params, self.k_ar_params, title='AR coefficients') validate_basic(self.seasonal_ar_params, self.k_seasonal_ar_params, title='seasonal AR coefficients') ar_stationary = True seasonal_ar_stationary = True if self.k_ar_params > 0: ar_stationary = is_invertible(self.ar_poly.coef) if self.k_seasonal_ar_params > 0: seasonal_ar_stationary = is_invertible(self.seasonal_ar_poly.coef) return ar_stationary and seasonal_ar_stationary
def is_invertible(self): """(bool) Is the reduced moving average lag poylnomial invertible.""" # Short-circuit if there is no MA component validate_basic(self.ma_params, self.k_ma_params, title='MA coefficients') validate_basic(self.seasonal_ma_params, self.k_seasonal_ma_params, title='seasonal MA coefficients') ma_stationary = True seasonal_ma_stationary = True if self.k_ma_params > 0: ma_stationary = is_invertible(self.ma_poly.coef) if self.k_seasonal_ma_params > 0: seasonal_ma_stationary = is_invertible(self.seasonal_ma_poly.coef) return ma_stationary and seasonal_ma_stationary
def test_cases(self): for polynomial, invertible in self.cases: assert_equal(tools.is_invertible(polynomial), invertible)
n_iterations = 10000 trace = np.zeros((n_iterations + 1, 3)) trace_accepts = np.zeros(n_iterations) trace[0] = [0, 0, 1.] # Initial values # Iterations for s in range(1, n_iterations + 1): # 1. Gibbs step: draw the states using the simulation smoother model.update(trace[s - 1], transformed=True) sim_smoother.simulate() states = sim_smoother.simulated_state[:, :-1] # 2. Gibbs step: draw the autoregressive parameters, and apply # rejection sampling to ensure an invertible lag polynomial phi = draw_posterior_phi(model, states, trace[s - 1, 2]) while not is_invertible([1, -phi]): phi = draw_posterior_phi(model, states, trace[s - 1, 2]) trace[s, 0] = phi # 3. Gibbs step: draw the variance parameter sigma2 = draw_posterior_sigma2(model, states, phi) trace[s, 2] = sigma2 # 4. Metropolis-step for the moving-average parameter theta = trace[s - 1, 1] proposal = theta + rw_proposal.rvs() if proposal > -1 and proposal < 1: acceptance_probability = np.exp( model.loglike([phi, proposal, sigma2]) - model.loglike([phi, theta, sigma2]))