def _fit_no_arch_normal_errors(self, cov_type: str = "robust" ) -> ARCHModelResult: """ Estimates model parameters Parameters ---------- cov_type : str, optional Covariance estimator to use when estimating parameter variances and covariances. One of 'hetero' or 'heteroskedastic' for Whites's covariance estimator, or 'mle' for the classic OLS estimator appropriate for homoskedastic data. 'hetero' is the the default. Returns ------- result : ARCHModelResult Results class containing parameter estimates, estimated parameter covariance and related estimates Notes ----- See :class:`ARCHModelResult` for details on computed results """ assert self._fit_y is not None nobs = self._fit_y.shape[0] if nobs < self.num_params: raise ValueError("Insufficient data, " + str(self.num_params) + " regressors, " + str(nobs) + " data points available") x = self._fit_regressors y = self._fit_y # Fake convergence results, see GH #87 opt = OptimizeResult({"status": 0, "message": ""}) if x.shape[1] > 0: regression_params = np.linalg.pinv(x).dot(y) xpxi = np.linalg.inv(x.T.dot(x) / nobs) fitted = x.dot(regression_params) else: regression_params = np.empty(0) xpxi = np.empty((0, 0)) fitted = 0.0 e = y - fitted sigma2 = e.T.dot(e) / nobs params = np.hstack((regression_params, sigma2)) hessian = np.zeros((self.num_params + 1, self.num_params + 1)) hessian[:self.num_params, :self.num_params] = -xpxi hessian[-1, -1] = -1 if cov_type in ("mle", ): param_cov = sigma2 * -hessian param_cov[self.num_params, self.num_params] = 2 * sigma2**2.0 param_cov /= nobs cov_type = COV_TYPES["classic_ols"] elif cov_type in ("robust", ): scores = np.zeros((nobs, self.num_params + 1)) scores[:, :self.num_params] = x * e[:, None] scores[:, -1] = e**2.0 - sigma2 score_cov = scores.T.dot(scores) / nobs param_cov = hessian.dot(score_cov).dot(hessian) / nobs cov_type = COV_TYPES["white"] else: raise ValueError("Unknown cov_type") r2 = self._r2(regression_params) first_obs, last_obs = self._fit_indices resids = np.empty_like(self._y, dtype=np.float64) resids.fill(np.nan) resids[first_obs:last_obs] = e vol = np.zeros_like(resids) vol.fill(np.nan) vol[first_obs:last_obs] = np.sqrt(sigma2) names = self._all_parameter_names() loglikelihood = self._static_gaussian_loglikelihood(e) # Throw away names in the case of starting values num_params = params.shape[0] if len(names) != num_params: names = ["p" + str(i) for i in range(num_params)] fit_start, fit_stop = self._fit_indices return ARCHModelResult( params, param_cov, r2, resids, vol, cov_type, self._y_series, names, loglikelihood, self._is_pandas, opt, fit_start, fit_stop, copy.deepcopy(self), )
def _fit_no_arch_normal_errors(self, cov_type='robust'): """ Estimates model parameters Parameters ---------- cov_type : str, optional Covariance estimator to use when estimating parameter variances and covariances. One of 'hetero' or 'heteroskedastic' for Whites's covariance estimator, or 'mle' for the classic OLS estimator appropriate for homoskedastic data. 'hetero' is the the default. Returns ------- result : ARCHModelResult Results class containing parameter estimates, estimated parameter covariance and related estimates Notes ----- See :class:`ARCHModelResult` for details on computed results """ nobs = self._fit_y.shape[0] if nobs == 0: from warnings import warn warn('Cannot estimate model with no data', RuntimeWarning) return None if nobs < self.num_params: raise ValueError('Insufficient data, ' + str(self.num_params) + ' regressors, ' + str(nobs) + ' data points available') x = self._fit_regressors y = self._fit_y # Fake convergence results, see GH #87 opt = OptimizeResult({'status': 0, 'message': ''}) if x.shape[1] == 0: loglikelihood = self._static_gaussian_loglikelihood(y) names = self._all_parameter_names() sigma2 = y.dot(y) / nobs params = np.array([sigma2]) param_cov = np.array([[np.mean(y**2 - sigma2) / nobs]]) vol = np.zeros_like(y) * np.sqrt(sigma2) # Throw away names in the case of starting values num_params = params.shape[0] if len(names) != num_params: names = ['p' + str(i) for i in range(num_params)] fit_start, fit_stop = self._fit_indices return ARCHModelResult(params, param_cov, 0.0, y, vol, cov_type, self._y_series, names, loglikelihood, self._is_pandas, opt, fit_start, fit_stop, copy.deepcopy(self)) regression_params = np.linalg.pinv(x).dot(y) xpxi = np.linalg.inv(x.T.dot(x) / nobs) e = y - x.dot(regression_params) sigma2 = e.T.dot(e) / nobs params = np.hstack((regression_params, sigma2)) hessian = np.zeros((self.num_params + 1, self.num_params + 1)) hessian[:self.num_params, :self.num_params] = -xpxi hessian[-1, -1] = -1 if cov_type in ('mle', ): param_cov = sigma2 * -hessian param_cov[self.num_params, self.num_params] = 2 * sigma2**2.0 param_cov /= nobs cov_type = COV_TYPES['classic_ols'] elif cov_type in ('robust', ): scores = np.zeros((nobs, self.num_params + 1)) scores[:, :self.num_params] = x * e[:, None] scores[:, -1] = e**2.0 - sigma2 score_cov = scores.T.dot(scores) / nobs param_cov = hessian.dot(score_cov).dot(hessian) / nobs cov_type = COV_TYPES['white'] else: raise ValueError('Unknown cov_type') r2 = self._r2(regression_params) first_obs, last_obs = self._fit_indices resids = np.empty_like(self._y, dtype=np.float64) resids.fill(np.nan) resids[first_obs:last_obs] = e vol = np.zeros_like(resids) vol.fill(np.nan) vol[first_obs:last_obs] = np.sqrt(sigma2) names = self._all_parameter_names() loglikelihood = self._static_gaussian_loglikelihood(e) # Throw away names in the case of starting values num_params = params.shape[0] if len(names) != num_params: names = ['p' + str(i) for i in range(num_params)] fit_start, fit_stop = self._fit_indices return ARCHModelResult(params, param_cov, r2, resids, vol, cov_type, self._y_series, names, loglikelihood, self._is_pandas, opt, fit_start, fit_stop, copy.deepcopy(self))