def _omega_forc_cov(self, steps): # Approximate MSE matrix \Omega(h) as defined in Lut p97 G = self._zz Ginv = L.inv(G) # memoize powers of B for speedup # TODO: see if can memoize better B = self._bmat_forc_cov() _B = {} def bpow(i): if i not in _B: _B[i] = np.linalg.matrix_power(B, i) return _B[i] phis = self.ma_rep(steps) sig_u = self.sigma_u omegas = np.zeros((steps, self.neqs, self.neqs)) for h in range(1, steps + 1): if h == 1: omegas[h-1] = self.df_model * self.sigma_u continue om = omegas[h-1] for i in range(h): for j in range(h): Bi = bpow(h - 1 - i) Bj = bpow(h - 1 - j) mult = np.trace(chain_dot(Bi.T, Ginv, Bj, G)) om += mult * chain_dot(phis[i], sig_u, phis[j].T) omegas[h-1] = om return omegas
def mse(self, steps): """ Compute theoretical forecast error variance matrices Parameters ---------- steps : int Number of steps ahead Notes ----- .. math:: \mathrm{MSE}(h) = \sum_{i=0}^{h-1} \Phi \Sigma_u \Phi^T Returns ------- forc_covs : ndarray (steps x neqs x neqs) """ ma_coefs = self.ma_rep(steps) k = len(self.sigma_u) forc_covs = np.zeros((steps, k, k)) prior = np.zeros((k, k)) for h in xrange(steps): # Sigma(h) = Sigma(h-1) + Phi Sig_u Phi' phi = ma_coefs[h] var = chain_dot(phi, self.sigma_u, phi.T) forc_covs[h] = prior = prior + var return forc_covs
def cum_effect_cov(self, orth=False): """ Compute asymptotic standard errors for cumulative impulse response coefficients Parameters ---------- orth : boolean Notes ----- eq. 3.7.7 (non-orth), 3.7.10 (orth) Returns ------- """ Ik = np.eye(self.neqs) PIk = np.kron(self.P.T, Ik) F = 0. covs = self._empty_covm(self.periods + 1) for i in range(self.periods + 1): if i > 0: F = F + self.G[i - 1] if orth: if i == 0: apiece = 0 else: Bn = np.dot(PIk, F) apiece = chain_dot(Bn, self.cov_a, Bn.T) Bnbar = np.dot(np.kron(Ik, self.cum_effects[i]), self.H) bpiece = chain_dot(Bnbar, self.cov_sig, Bnbar.T) / self.T covs[i] = apiece + bpiece else: if i == 0: covs[i] = np.zeros((self.neqs**2, self.neqs**2)) continue covs[i] = chain_dot(F, self.cov_a, F.T) return covs
def lr_effect_cov(self, orth=False): """ Returns ------- """ lre = self.lr_effects Finfty = np.kron(np.tile(lre.T, self.lags), lre) Ik = np.eye(self.neqs) if orth: Binf = np.dot(np.kron(self.P.T, np.eye(self.neqs)), Finfty) Binfbar = np.dot(np.kron(Ik, lre), self.H) return (chain_dot(Binf, self.cov_a, Binf.T) + chain_dot(Binfbar, self.cov_sig, Binfbar.T)) else: return chain_dot(Finfty, self.cov_a, Finfty.T)
def _cov_sigma(self): """ Estimated covariance matrix of vech(sigma_u) """ D_K = tsa.duplication_matrix(self.neqs) D_Kinv = npl.pinv(D_K) sigxsig = np.kron(self.sigma_u, self.sigma_u) return 2 * chain_dot(D_Kinv, sigxsig, D_Kinv.T)
def _orth_cov(self): # Lutkepohl 3.7.8 Ik = np.eye(self.neqs) PIk = np.kron(self.P.T, Ik) H = self.H covs = self._empty_covm(self.periods + 1) for i in range(self.periods + 1): if i == 0: apiece = 0 else: Ci = np.dot(PIk, self.G[i-1]) apiece = chain_dot(Ci, self.cov_a, Ci.T) Cibar = np.dot(np.kron(Ik, self.irfs[i]), H) bpiece = chain_dot(Cibar, self.cov_sig, Cibar.T) / self.T # Lutkepohl typo, cov_sig correct covs[i] = apiece + bpiece return covs
def H(self): k = self.neqs Lk = tsa.elimination_matrix(k) Kkk = tsa.commutation_matrix(k, k) Ik = np.eye(k) # B = chain_dot(Lk, np.eye(k**2) + commutation_matrix(k, k), # np.kron(self.P, np.eye(k)), Lk.T) # return np.dot(Lk.T, L.inv(B)) B = chain_dot(Lk, np.dot(np.kron(Ik, self.P), Kkk) + np.kron(self.P, Ik), Lk.T) return np.dot(Lk.T, L.inv(B))
def cov_ybar(self): r"""Asymptotically consistent estimate of covariance of the sample mean .. math:: \sqrt(T) (\bar{y} - \mu) \rightarrow {\cal N}(0, \Sigma_{\bar{y}})\\ \Sigma_{\bar{y}} = B \Sigma_u B^\prime, \text{where } B = (I_K - A_1 - \cdots - A_p)^{-1} Notes ----- Lutkepohl Proposition 3.3 """ Ainv = L.inv(np.eye(self.neqs) - self.coefs.sum(0)) return chain_dot(Ainv, self.sigma_u, Ainv.T)
def cov(self, orth=False): """ Compute asymptotic standard errors for impulse response coefficients Notes ----- Lutkepohl eq 3.7.5 Returns ------- """ if orth: return self._orth_cov() covs = self._empty_covm(self.periods + 1) covs[0] = np.zeros((self.neqs ** 2, self.neqs ** 2)) for i in range(1, self.periods + 1): Gi = self.G[i - 1] covs[i] = chain_dot(Gi, self.cov_a, Gi.T) return covs
def cov(self, orth=False): """ Compute asymptotic standard errors for impulse response coefficients Notes ----- Lütkepohl eq 3.7.5 Returns ------- """ if orth: return self._orth_cov() covs = self._empty_covm(self.periods + 1) covs[0] = np.zeros((self.neqs**2, self.neqs**2)) for i in range(1, self.periods + 1): Gi = self.G[i - 1] covs[i] = chain_dot(Gi, self.cov_a, Gi.T) return covs
def forecast_cov(ma_coefs, sig_u, steps): """ Compute theoretical forecast error variance matrices Parameters ---------- Returns ------- forc_covs : ndarray (steps x neqs x neqs) """ k = len(sig_u) forc_covs = np.zeros((steps, k, k)) prior = np.zeros((k, k)) for h in xrange(steps): # Sigma(h) = Sigma(h-1) + Phi Sig_u Phi' phi = ma_coefs[h] var = chain_dot(phi, sig_u, phi.T) forc_covs[h] = prior = prior + var return forc_covs
def swar_transform(subset, position, theta): '''Apply to a sub-group of observations''' n = subset.shape[0] B = np.ones((n, n)) / n out = subset - chain_dot(np.diag(theta[position]), B, subset) return out
def a_test_causality(self, caused, causing=None, kind='f', signif=0.05): if not (0 < signif < 1): raise ValueError("signif has to be between 0 and 1") allowed_types = (string_types, int) if isinstance(caused, allowed_types): caused = [caused] if not all(isinstance(c, allowed_types) for c in caused): raise TypeError("caused has to be of type string or int (or a " "sequence of these types).") caused = [self.names[c] if type(c) == int else c for c in caused] caused_ind = [util.get_index(self.names, c) for c in caused] if causing is not None: if isinstance(causing, allowed_types): causing = [causing] if not all(isinstance(c, allowed_types) for c in causing): raise TypeError("causing has to be of type string or int (or " "a sequence of these types) or None.") causing = [self.names[c] if type(c) == int else c for c in causing] causing_ind = [util.get_index(self.names, c) for c in causing] if causing is None: causing_ind = [i for i in range(self.neqs) if i not in caused_ind] causing = [self.names[c] for c in caused_ind] k, p = self.neqs, self.k_ar # number of restrictions num_restr = len(causing) * len(caused) * p num_det_terms = self.k_exog # Make restriction matrix C = np.zeros((num_restr, k * num_det_terms + k ** 2 * p), dtype=float) cols_det = k * num_det_terms row = 0 for j in range(p): for ing_ind in causing_ind: for ed_ind in caused_ind: C[row, cols_det + ed_ind + k * ing_ind + k ** 2 * j] = 1 row += 1 # Lutkepohl 3.6.5 Cb = np.dot(C, vec(self.params.T)) middle = scipy.linalg.inv(chain_dot(C, self.cov_params, C.T)) # wald statistic lam_wald = statistic = chain_dot(Cb, middle, Cb) if kind.lower() == 'wald': df = num_restr dist = stats.chi2(df) elif kind.lower() == 'f': statistic = lam_wald / num_restr df = (num_restr, k * self.df_resid) dist = stats.f(*df) else: raise Exception('kind %s not recognized' % kind) pvalue = dist.sf(statistic) crit_value = dist.ppf(1 - signif) # print(pvalue) # print("---====--") return pvalue, CausalityTestResults(causing, caused, statistic, crit_value, pvalue, df, signif, test="granger", method=kind)
def kalmanfilter(F, A, H, Q, R, y, X, xi10, ntrain, history=False): """ Returns the negative log-likelihood of y conditional on the information set Assumes that the initial state and all innovations are multivariate Gaussian. Parameters ----------- F : array-like The (r x r) array holding the transition matrix for the hidden state. A : array-like The (nobs x k) array relating the predetermined variables to the observed data. H : array-like The (nobs x r) array relating the hidden state vector to the observed data. Q : array-like (r x r) variance/covariance matrix on the error term in the hidden state transition. R : array-like (nobs x nobs) variance/covariance of the noise in the observation equation. y : array-like The (nobs x 1) array holding the observed data. X : array-like The (nobs x k) array holding the predetermined variables data. xi10 : array-like Is the (r x 1) initial prior on the initial state vector. ntrain : int The number of training periods for the filter. This is the number of observations that do not affect the likelihood. Returns ------- likelihood The negative of the log likelihood history or priors, history of posterior If history is True. Notes ----- No input checking is done. """ # uses log of Hamilton 13.4.1 F = np.asarray(F) H = np.atleast_2d(np.asarray(H)) n = H.shape[1] # remember that H gets transposed y = np.asarray(y) A = np.asarray(A) X = np.asarray(X) if y.ndim == 1: # note that Y is in rows for now y = y[:, None] nobs = y.shape[0] xi10 = np.atleast_2d(np.asarray(xi10)) # if xi10.ndim == 1: # xi10[:,None] if history: state_vector = [xi10] Q = np.asarray(Q) r = xi10.shape[0] # Eq. 12.2.21, other version says P0 = Q # p10 = np.dot(np.linalg.inv(np.eye(r**2)-np.kron(F,F)),Q.ravel('F')) # p10 = np.reshape(P0, (r,r), order='F') # Assume a fixed, known intial point and set P0 = Q #TODO: this looks *slightly * different than Durbin-Koopman exact likelihood # initialization p 112 unless I've misunderstood the notational translation. p10 = Q loglikelihood = 0 for i in range(nobs): HTPHR = np.atleast_1d(np.squeeze(chain_dot(H.T, p10, H) + R)) # print HTPHR # print HTPHR.ndim # print HTPHR.shape if HTPHR.ndim == 1: HTPHRinv = 1. / HTPHR else: HTPHRinv = np.linalg.inv(HTPHR) # correct # print A.T # print X # print H.T # print xi10 # print y[i] part1 = y[i] - np.dot(A.T, X) - np.dot(H.T, xi10) # correct if i >= ntrain: # zero-index, but ntrain isn't HTPHRdet = np.linalg.det(np.atleast_2d(HTPHR)) # correct part2 = -.5 * chain_dot(part1.T, HTPHRinv, part1) # correct #TODO: Need to test with ill-conditioned problem. loglike_interm = (-n/2.) * np.log(2*np.pi) - .5*\ np.log(HTPHRdet) + part2 loglikelihood += loglike_interm # 13.2.15 Update current state xi_t based on y xi11 = xi10 + chain_dot(p10, H, HTPHRinv, part1) # 13.2.16 MSE of that state p11 = p10 - chain_dot(p10, H, HTPHRinv, H.T, p10) # 13.2.17 Update forecast about xi_{t+1} based on our F xi10 = np.dot(F, xi11) if history: state_vector.append(xi10) # 13.2.21 Update the MSE of the forecast p10 = chain_dot(F, p11, F.T) + Q if not history: return -loglikelihood else: return -loglikelihood, np.asarray(state_vector[:-1])
def kalmanfilter(F, A, H, Q, R, y, X, xi10, ntrain, history=False): """ Returns the negative log-likelihood of y conditional on the information set Assumes that the initial state and all innovations are multivariate Gaussian. Parameters ----------- F : array-like The (r x r) array holding the transition matrix for the hidden state. A : array-like The (nobs x k) array relating the predetermined variables to the observed data. H : array-like The (nobs x r) array relating the hidden state vector to the observed data. Q : array-like (r x r) variance/covariance matrix on the error term in the hidden state transition. R : array-like (nobs x nobs) variance/covariance of the noise in the observation equation. y : array-like The (nobs x 1) array holding the observed data. X : array-like The (nobs x k) array holding the predetermined variables data. xi10 : array-like Is the (r x 1) initial prior on the initial state vector. ntrain : int The number of training periods for the filter. This is the number of observations that do not affect the likelihood. Returns ------- likelihood The negative of the log likelihood history or priors, history of posterior If history is True. Notes ----- No input checking is done. """ # uses log of Hamilton 13.4.1 F = np.asarray(F) H = np.atleast_2d(np.asarray(H)) n = H.shape[1] # remember that H gets transposed y = np.asarray(y) A = np.asarray(A) X = np.asarray(X) if y.ndim == 1: # note that Y is in rows for now y = y[:,None] nobs = y.shape[0] xi10 = np.atleast_2d(np.asarray(xi10)) # if xi10.ndim == 1: # xi10[:,None] if history: state_vector = [xi10] Q = np.asarray(Q) r = xi10.shape[0] # Eq. 12.2.21, other version says P0 = Q # p10 = np.dot(np.linalg.inv(np.eye(r**2)-np.kron(F,F)),Q.ravel('F')) # p10 = np.reshape(P0, (r,r), order='F') # Assume a fixed, known intial point and set P0 = Q #TODO: this looks *slightly * different than Durbin-Koopman exact likelihood # initialization p 112 unless I've misunderstood the notational translation. p10 = Q loglikelihood = 0 for i in range(nobs): HTPHR = np.atleast_1d(np.squeeze(chain_dot(H.T,p10,H)+R)) # print HTPHR # print HTPHR.ndim # print HTPHR.shape if HTPHR.ndim == 1: HTPHRinv = 1./HTPHR else: HTPHRinv = np.linalg.inv(HTPHR) # correct # print A.T # print X # print H.T # print xi10 # print y[i] part1 = y[i] - np.dot(A.T,X) - np.dot(H.T,xi10) # correct if i >= ntrain: # zero-index, but ntrain isn't HTPHRdet = np.linalg.det(np.atleast_2d(HTPHR)) # correct part2 = -.5*chain_dot(part1.T,HTPHRinv,part1) # correct #TODO: Need to test with ill-conditioned problem. loglike_interm = (-n/2.) * np.log(2*np.pi) - .5*\ np.log(HTPHRdet) + part2 loglikelihood += loglike_interm # 13.2.15 Update current state xi_t based on y xi11 = xi10 + chain_dot(p10, H, HTPHRinv, part1) # 13.2.16 MSE of that state p11 = p10 - chain_dot(p10, H, HTPHRinv, H.T, p10) # 13.2.17 Update forecast about xi_{t+1} based on our F xi10 = np.dot(F,xi11) if history: state_vector.append(xi10) # 13.2.21 Update the MSE of the forecast p10 = chain_dot(F,p11,F.T) + Q if not history: return -loglikelihood else: return -loglikelihood, np.asarray(state_vector[:-1])
def fit(self, q=.5, vcov='robust', kernel='epa', bandwidth='hsheather', max_iter=1000, p_tol=1e-6, **kwargs): '''Solve by Iterative Weighted Least Squares Parameters ---------- q : float Quantile must be between 0 and 1 vcov : string, method used to calculate the variance-covariance matrix of the parameters. Default is ``robust``: - robust : heteroskedasticity robust standard errors (as suggested in Greene 6th edition) - iid : iid errors (as in Stata 12) kernel : string, kernel to use in the kernel density estimation for the asymptotic covariance matrix: - epa: Epanechnikov - cos: Cosine - gau: Gaussian - par: Parzene bandwidth: string, Bandwidth selection method in kernel density estimation for asymptotic covariance estimate (full references in QuantReg docstring): - hsheather: Hall-Sheather (1988) - bofinger: Bofinger (1975) - chamberlain: Chamberlain (1994) ''' if q < 0 or q > 1: raise Exception('p must be between 0 and 1') kern_names = ['biw', 'cos', 'epa', 'gau', 'par'] if kernel not in kern_names: raise Exception("kernel must be one of " + ', '.join(kern_names)) else: kernel = kernels[kernel] if bandwidth == 'hsheather': bandwidth = hall_sheather elif bandwidth == 'bofinger': bandwidth = bofinger elif bandwidth == 'chamberlain': bandwidth = chamberlain else: raise Exception("bandwidth must be in 'hsheather', 'bofinger', 'chamberlain'") endog = self.endog exog = self.exog nobs = self.nobs exog_rank = np_matrix_rank(self.exog) self.rank = exog_rank self.df_model = float(self.rank - self.k_constant) self.df_resid = self.nobs - self.rank n_iter = 0 xstar = exog beta = np.ones(exog_rank) # TODO: better start, initial beta is used only for convergence check # Note the following doesn't work yet, # the iteration loop always starts with OLS as initial beta # if start_params is not None: # if len(start_params) != rank: # raise ValueError('start_params has wrong length') # beta = start_params # else: # # start with OLS # beta = np.dot(np.linalg.pinv(exog), endog) diff = 10 cycle = False history = dict(params = [], mse=[]) while n_iter < max_iter and diff > p_tol and not cycle: n_iter += 1 beta0 = beta xtx = np.dot(xstar.T, exog) xty = np.dot(xstar.T, endog) beta = np.dot(pinv(xtx), xty) resid = endog - np.dot(exog, beta) mask = np.abs(resid) < .000001 resid[mask] = ((resid[mask] >= 0) * 2 - 1) * .000001 resid = np.where(resid < 0, q * resid, (1-q) * resid) resid = np.abs(resid) xstar = exog / resid[:, np.newaxis] diff = np.max(np.abs(beta - beta0)) history['params'].append(beta) history['mse'].append(np.mean(resid*resid)) if (n_iter >= 300) and (n_iter % 100 == 0): # check for convergence circle, shouldn't happen for ii in range(2, 10): if np.all(beta == history['params'][-ii]): cycle = True break warnings.warn("Convergence cycle detected", ConvergenceWarning) if n_iter == max_iter: warnings.warn("Maximum number of iterations (1000) reached.", IterationLimitWarning) e = endog - np.dot(exog, beta) # Greene (2008, p.407) writes that Stata 6 uses this bandwidth: # h = 0.9 * np.std(e) / (nobs**0.2) # Instead, we calculate bandwidth as in Stata 12 iqre = stats.scoreatpercentile(e, 75) - stats.scoreatpercentile(e, 25) h = bandwidth(nobs, q) h = min(np.std(endog), iqre / 1.34) * (norm.ppf(q + h) - norm.ppf(q - h)) fhat0 = 1. / (nobs * h) * np.sum(kernel(e / h)) if vcov == 'robust': d = np.where(e > 0, (q/fhat0)**2, ((1-q)/fhat0)**2) xtxi = pinv(np.dot(exog.T, exog)) xtdx = np.dot(exog.T * d[np.newaxis, :], exog) vcov = chain_dot(xtxi, xtdx, xtxi) elif vcov == 'iid': vcov = (1. / fhat0)**2 * q * (1 - q) * pinv(np.dot(exog.T, exog)) else: raise Exception("vcov must be 'robust' or 'iid'") lfit = QuantRegResults(self, beta, normalized_cov_params=vcov) lfit.q = q lfit.iterations = n_iter lfit.sparsity = 1. / fhat0 lfit.bandwidth = h lfit.history = history return RegressionResultsWrapper(lfit)
def test_chain_dot(): A = np.arange(1, 13).reshape(3, 4) B = np.arange(3, 15).reshape(4, 3) C = np.arange(5, 8).reshape(3, 1) assert_equal(tools.chain_dot(A, B, C), np.array([[1820], [4300], [6780]]))
def fit(self, q=.5, vcov='robust', kernel='epa', bandwidth='hsheather', max_iter=1000, p_tol=1e-6, **kwargs): """ Solve by Iterative Weighted Least Squares Parameters ---------- q : float Quantile must be between 0 and 1 vcov : str, method used to calculate the variance-covariance matrix of the parameters. Default is ``robust``: - robust : heteroskedasticity robust standard errors (as suggested in Greene 6th edition) - iid : iid errors (as in Stata 12) kernel : str, kernel to use in the kernel density estimation for the asymptotic covariance matrix: - epa: Epanechnikov - cos: Cosine - gau: Gaussian - par: Parzene bandwidth : str, Bandwidth selection method in kernel density estimation for asymptotic covariance estimate (full references in QuantReg docstring): - hsheather: Hall-Sheather (1988) - bofinger: Bofinger (1975) - chamberlain: Chamberlain (1994) """ if q < 0 or q > 1: raise Exception('p must be between 0 and 1') kern_names = ['biw', 'cos', 'epa', 'gau', 'par'] if kernel not in kern_names: raise Exception("kernel must be one of " + ', '.join(kern_names)) else: kernel = kernels[kernel] if bandwidth == 'hsheather': bandwidth = hall_sheather elif bandwidth == 'bofinger': bandwidth = bofinger elif bandwidth == 'chamberlain': bandwidth = chamberlain else: raise Exception("bandwidth must be in 'hsheather', 'bofinger', 'chamberlain'") endog = self.endog exog = self.exog nobs = self.nobs exog_rank = np.linalg.matrix_rank(self.exog) self.rank = exog_rank self.df_model = float(self.rank - self.k_constant) self.df_resid = self.nobs - self.rank n_iter = 0 xstar = exog beta = np.ones(exog_rank) # TODO: better start, initial beta is used only for convergence check # Note the following does not work yet, # the iteration loop always starts with OLS as initial beta # if start_params is not None: # if len(start_params) != rank: # raise ValueError('start_params has wrong length') # beta = start_params # else: # # start with OLS # beta = np.dot(np.linalg.pinv(exog), endog) diff = 10 cycle = False history = dict(params = [], mse=[]) while n_iter < max_iter and diff > p_tol and not cycle: n_iter += 1 beta0 = beta xtx = np.dot(xstar.T, exog) xty = np.dot(xstar.T, endog) beta = np.dot(pinv(xtx), xty) resid = endog - np.dot(exog, beta) mask = np.abs(resid) < .000001 resid[mask] = ((resid[mask] >= 0) * 2 - 1) * .000001 resid = np.where(resid < 0, q * resid, (1-q) * resid) resid = np.abs(resid) xstar = exog / resid[:, np.newaxis] diff = np.max(np.abs(beta - beta0)) history['params'].append(beta) history['mse'].append(np.mean(resid*resid)) if (n_iter >= 300) and (n_iter % 100 == 0): # check for convergence circle, should not happen for ii in range(2, 10): if np.all(beta == history['params'][-ii]): cycle = True warnings.warn("Convergence cycle detected", ConvergenceWarning) break if n_iter == max_iter: warnings.warn("Maximum number of iterations (" + str(max_iter) + ") reached.", IterationLimitWarning) e = endog - np.dot(exog, beta) # Greene (2008, p.407) writes that Stata 6 uses this bandwidth: # h = 0.9 * np.std(e) / (nobs**0.2) # Instead, we calculate bandwidth as in Stata 12 iqre = stats.scoreatpercentile(e, 75) - stats.scoreatpercentile(e, 25) h = bandwidth(nobs, q) h = min(np.std(endog), iqre / 1.34) * (norm.ppf(q + h) - norm.ppf(q - h)) fhat0 = 1. / (nobs * h) * np.sum(kernel(e / h)) if vcov == 'robust': d = np.where(e > 0, (q/fhat0)**2, ((1-q)/fhat0)**2) xtxi = pinv(np.dot(exog.T, exog)) xtdx = np.dot(exog.T * d[np.newaxis, :], exog) vcov = chain_dot(xtxi, xtdx, xtxi) elif vcov == 'iid': vcov = (1. / fhat0)**2 * q * (1 - q) * pinv(np.dot(exog.T, exog)) else: raise Exception("vcov must be 'robust' or 'iid'") lfit = QuantRegResults(self, beta, normalized_cov_params=vcov) lfit.q = q lfit.iterations = n_iter lfit.sparsity = 1. / fhat0 lfit.bandwidth = h lfit.history = history return RegressionResultsWrapper(lfit)
def swar_transform(subset, position, theta): '''Apply to a sub-group of observations''' n = subset.shape[0] B = np.ones((n,n)) / n out = subset - chain_dot(np.diag(theta[position]), B, subset) return out
def test_causality(self, equation, variables, kind='f', signif=0.05, verbose=True): """Compute test statistic for null hypothesis of Granger-noncausality, general function to test joint Granger-causality of multiple variables Parameters ---------- equation : string or int Equation to test for causality variables : sequence (of strings or ints) List, tuple, etc. of variables to test for Granger-causality kind : {'f', 'wald'} Perform F-test or Wald (chi-sq) test signif : float, default 5% Significance level for computing critical values for test, defaulting to standard 0.95 level Notes ----- Null hypothesis is that there is no Granger-causality for the indicated variables. The degrees of freedom in the F-test are based on the number of variables in the VAR system, that is, degrees of freedom are equal to the number of equations in the VAR times degree of freedom of a single equation. Returns ------- results : dict """ if isinstance(variables, (basestring, int, np.integer)): variables = [variables] k, p = self.neqs, self.k_ar # number of restrictions N = len(variables) * self.k_ar # Make restriction matrix C = np.zeros((N, k ** 2 * p + k), dtype=float) eq_index = self.get_eq_index(equation) vinds = mat([self.get_eq_index(v) for v in variables]) # remember, vec is column order! offsets = np.concatenate([k + k ** 2 * j + k * vinds + eq_index for j in range(p)]) C[np.arange(N), offsets] = 1 # Lutkepohl 3.6.5 Cb = np.dot(C, vec(self.params.T)) middle = L.inv(chain_dot(C, self.cov_params, C.T)) # wald statistic lam_wald = statistic = chain_dot(Cb, middle, Cb) if kind.lower() == 'wald': df = N dist = stats.chi2(df) elif kind.lower() == 'f': statistic = lam_wald / N df = (N, k * self.df_resid) dist = stats.f(*df) else: raise Exception('kind %s not recognized' % kind) pvalue = dist.sf(statistic) crit_value = dist.ppf(1 - signif) conclusion = 'fail to reject' if statistic < crit_value else 'reject' results = { 'statistic' : statistic, 'crit_value' : crit_value, 'pvalue' : pvalue, 'df' : df, 'conclusion' : conclusion, 'signif' : signif } if verbose: summ = output.causality_summary(results, variables, equation, kind) print summ return results