def _estimate_svar(self, start_params, lags, maxiter, maxfun, trend='c', solver="nm", override=False): """ lags : int trend : string or None As per above """ k_trend = util.get_trendorder(trend) y = self.endog z = util.get_var_endog(y, lags, trend=trend) y_sample = y[lags:] # Lutkepohl p75, about 5x faster than stated formula var_params = np.linalg.lstsq(z, y_sample)[0] resid = y_sample - np.dot(z, var_params) # Unbiased estimate of covariance matrix $\Sigma_u$ of the white noise # process $u$ # equivalent definition # .. math:: \frac{1}{T - Kp - 1} Y^\prime (I_T - Z (Z^\prime Z)^{-1} # Z^\prime) Y # Ref: Lutkepohl p.75 # df_resid right now is T - Kp - 1, which is a suggested correction avobs = len(y_sample) df_resid = avobs - (self.neqs * lags + k_trend) sse = np.dot(resid.T, resid) #TODO: should give users the option to use a dof correction or not omega = sse / df_resid self.sigma_u = omega A, B = self._solve_AB(start_params, override=override, solver=solver, maxiter=maxiter, maxfun=maxfun) A_mask = self.A_mask B_mask = self.B_mask return SVARResults(y, z, var_params, omega, lags, names=self.endog_names, trend=trend, dates=self._data.dates, model=self, A=A, B=B, A_mask=A_mask, B_mask=B_mask)
def __init__(self, endog, endog_lagged, params, sigma_u, lag_order, model=None, trend='c', names=None, dates=None): self.model = model self.y = self.endog = endog #keep alias for now self.ys_lagged = self.endog_lagged = endog_lagged #keep alias for now self.dates = dates self.n_totobs, neqs = self.y.shape self.nobs = self.n_totobs - lag_order k_trend = util.get_trendorder(trend) if k_trend > 0: # make this the polynomial trend order trendorder = k_trend - 1 else: trendorder = None self.k_trend = k_trend self.trendorder = trendorder #TODO: deprecate coef_names self.coef_names = self.exog_names = util.make_lag_names(names, lag_order, k_trend) self.params = params # Initialize VARProcess parent class # construct coefficient matrices # Each matrix needs to be transposed reshaped = self.params[self.k_trend:] reshaped = reshaped.reshape((lag_order, neqs, neqs)) # Need to transpose each coefficient matrix intercept = self.params[0] coefs = reshaped.swapaxes(1, 2).copy() super(VARResults, self).__init__(coefs, intercept, sigma_u, names=names)
def __init__(self, endog, endog_lagged, params, sigma_u, lag_order, A=None, B=None, A_mask=None, B_mask=None, model=None, trend='c', names=None, dates=None): self.model = model self.y = self.endog = endog #keep alias for now self.ys_lagged = self.endog_lagged = endog_lagged #keep alias for now self.dates = dates self.n_totobs, self.neqs = self.y.shape self.nobs = self.n_totobs - lag_order k_trend = util.get_trendorder(trend) if k_trend > 0: # make this the polynomial trend order trendorder = k_trend - 1 else: trendorder = None self.k_trend = k_trend self.trendorder = trendorder self.coef_names = util.make_lag_names(names, lag_order, k_trend) self.params = params self.sigma_u = sigma_u # Each matrix needs to be transposed reshaped = self.params[self.k_trend:] reshaped = reshaped.reshape((lag_order, self.neqs, self.neqs)) # Need to transpose each coefficient matrix intercept = self.params[0] coefs = reshaped.swapaxes(1, 2).copy() #SVAR components #TODO: if you define these here, you don't also have to define #them in SVAR process, but I left them for now -ss self.A = A self.B = B self.A_mask = A_mask self.B_mask = B_mask super(SVARResults, self).__init__(coefs, intercept, sigma_u, A, B, names=names)
def test_get_trendorder(): results = { 'c' : 1, 'nc' : 0, 'ct' : 2, 'ctt' : 3 } for t, trendorder in results.iteritems(): assert(util.get_trendorder(t) == trendorder)
def fit(self, maxlags=None, method='ols', ic=None, trend='c', verbose=False): """ Fit the VAR model Parameters ---------- maxlags : int Maximum number of lags to check for order selection, defaults to 12 * (nobs/100.)**(1./4), see select_order function method : {'ols'} Estimation method to use ic : {'aic', 'fpe', 'hqic', 'bic', None} Information criterion to use for VAR order selection. aic : Akaike fpe : Final prediction error hqic : Hannan-Quinn bic : Bayesian a.k.a. Schwarz verbose : bool, default False Print order selection output to the screen trend, str {"c", "ct", "ctt", "nc"} "c" - add constant "ct" - constant and trend "ctt" - constant, linear and quadratic trend "nc" - co constant, no trend Note that these are prepended to the columns of the dataset. Notes ----- Lutkepohl pp. 146-153 Returns ------- est : VARResults """ lags = maxlags if ic is not None: selections = self.select_order(maxlags=maxlags, verbose=verbose) if ic not in selections: raise Exception("%s not recognized, must be among %s" % (ic, sorted(selections))) lags = selections[ic] if verbose: print 'Using %d based on %s criterion' % (lags, ic) else: if lags is None: lags = 1 k_trend = util.get_trendorder(trend) self.exog_names = util.make_lag_names(self.endog_names, lags, k_trend) self.nobs = len(self.endog) - lags return self._estimate_var(lags, trend=trend)
def _stackX(self, k_ar, trend): """ Private method to build the RHS matrix for estimation. Columns are trend terms then lags. """ endog = self.endog X = lagmat(endog, maxlag=k_ar, trim='both') k_trend = util.get_trendorder(trend) if k_trend: X = add_trend(X, prepend=True, trend=trend) self.k_trend = k_trend return X
def _estimate_var(self, lags, offset=0, trend='c'): """ lags : int offset : int Periods to drop from beginning-- for order selection so it's an apples-to-apples comparison trend : string or None As per above """ # have to do this again because select_order doesn't call fit self.k_trend = k_trend = util.get_trendorder(trend) if offset < 0: # pragma: no cover raise ValueError('offset must be >= 0') y = self.y[offset:] z = util.get_var_endog(y, lags, trend=trend) y_sample = y[lags:] # Lutkepohl p75, about 5x faster than stated formula params = np.linalg.lstsq(z, y_sample)[0] resid = y_sample - np.dot(z, params) # Unbiased estimate of covariance matrix $\Sigma_u$ of the white noise # process $u$ # equivalent definition # .. math:: \frac{1}{T - Kp - 1} Y^\prime (I_T - Z (Z^\prime Z)^{-1} # Z^\prime) Y # Ref: Lutkepohl p.75 # df_resid right now is T - Kp - 1, which is a suggested correction avobs = len(y_sample) df_resid = avobs - (self.neqs * lags + k_trend) sse = np.dot(resid.T, resid) omega = sse / df_resid varfit = VARResults(y, z, params, omega, lags, names=self.endog_names, trend=trend, dates=self._data.dates, model=self) return VARResultsWrapper(varfit)
def predict(self, params, start=None, end=None, lags=1, trend='c'): """ Returns in-sample predictions or forecasts """ start = self._get_predict_start(start, lags) end, out_of_sample = self._get_predict_end(end) if end < start: raise ValueError("end is before start") if end == start + out_of_sample: return np.array([]) k_trend = util.get_trendorder(trend) k = self.neqs k_ar = lags predictedvalues = np.zeros((end + 1 - start + out_of_sample, k)) if k_trend != 0: intercept = params[:k_trend] predictedvalues += intercept y = self.y X = util.get_var_endog(y, lags, trend=trend) fittedvalues = np.dot(X, params) fv_start = start - k_ar pv_end = min(len(predictedvalues), len(fittedvalues) - fv_start) fv_end = min(len(fittedvalues), end-k_ar+1) predictedvalues[:pv_end] = fittedvalues[fv_start:fv_end] if not out_of_sample: return predictedvalues # fit out of sample y = y[-k_ar:] coefs = params[k_trend:].reshape((k_ar, k, k)).swapaxes(1,2) predictedvalues[pv_end:] = forecast(y, coefs, intercept, out_of_sample) return predictedvalues