def test_garch_no_symmetric(self): garch = GARCH(p=0, o=1, q=1) sv = garch.starting_values(self.resids) assert_equal(sv.shape[0], garch.num_params) bounds = garch.bounds(self.resids) assert_equal(bounds[0], (0.0, 10.0 * np.mean(self.resids ** 2.0))) assert_equal(bounds[1], (0.0, 2.0)) assert_equal(bounds[2], (0.0, 1.0)) var_bounds = garch.variance_bounds(self.resids) backcast = garch.backcast(self.resids) parameters = np.array([.1, .1, .8]) names = garch.parameter_names() names_target = ['omega', 'gamma[1]', 'beta[1]'] assert_equal(names, names_target) garch.compute_variance(parameters, self.resids, self.sigma2, backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) rec.garch_recursion(parameters, self.resids ** 2.0, np.sign(self.resids), cond_var_direct, 0, 1, 1, self.T, backcast, var_bounds) assert_allclose(self.sigma2, cond_var_direct) A, b = garch.constraints() A_target = np.vstack((np.eye(3), np.array([[0, -0.5, -1.0]]))) b_target = np.array([0.0, 0.0, 0.0, -1.0]) assert_array_equal(A, A_target) assert_array_equal(b, b_target) state = np.random.get_state() rng = Normal() sim_data = garch.simulate(parameters, self.T, rng.simulate([])) np.random.set_state(state) e = np.random.standard_normal(self.T + 500) initial_value = 1.0 sigma2 = np.zeros(self.T + 500) data = np.zeros(self.T + 500) for t in range(self.T + 500): sigma2[t] = parameters[0] shock = 0.5 * initial_value if t == 0 else \ data[t - 1] ** 2.0 * (data[t - 1] < 0) sigma2[t] += parameters[1] * shock lagged_value = initial_value if t == 0 else sigma2[t - 1] sigma2[t] += parameters[2] * lagged_value data[t] = e[t] * np.sqrt(sigma2[t]) data = data[500:] sigma2 = sigma2[500:] assert_almost_equal(data - sim_data[0] + 1.0, np.ones_like(data)) assert_almost_equal(sigma2 / sim_data[1], np.ones_like(sigma2)) assert_equal(garch.p, 0) assert_equal(garch.o, 1) assert_equal(garch.q, 1) assert_equal(garch.num_params, 3) assert_equal(garch.name, 'GJR-GARCH')
def test_garch_many_lags(self): garch = GARCH(p=1, o=2, q=3) assert_equal(garch.num_params, 7) assert_equal(garch.name, 'GJR-GARCH') names = garch.parameter_names() names_target = ['omega', 'alpha[1]', 'gamma[1]', 'gamma[2]', 'beta[1]', 'beta[2]', 'beta[3]'] assert_equal(names, names_target)
def test_warnings(self): garch = GARCH() parameters = np.array([0.1, 0.2, 0.8, 4.0]) studt = StudentsT() with warnings.catch_warnings(record=True) as w: garch.simulate(parameters, 1000, studt.simulate([4.0])) assert_equal(len(w), 1) harch = HARCH(lags=[1, 5, 22]) parameters = np.array([0.1, 0.2, 0.4, 0.5]) with warnings.catch_warnings(record=True) as w: harch.simulate(parameters, 1000, studt.simulate([4.0])) assert_equal(len(w), 1)
def test_garch_power(self): garch = GARCH(power=1.0) assert_equal(garch.num_params, 3) assert_equal(garch.name, 'AVGARCH') assert_equal(garch.power, 1.0) sv = garch.starting_values(self.resids) assert_equal(sv.shape[0], garch.num_params) bounds = garch.bounds(self.resids) assert_equal(bounds[0], (0.0, 10.0 * np.mean(np.abs(self.resids)))) assert_equal(bounds[1], (0.0, 1.0)) assert_equal(bounds[2], (0.0, 1.0)) var_bounds = garch.variance_bounds(self.resids) backcast = garch.backcast(self.resids) w = 0.94 ** np.arange(75) assert_almost_equal(backcast, np.sum(np.abs(self.resids[:75]) * (w / w.sum()))) parameters = np.array([.1, .1, .8]) garch.compute_variance(parameters, self.resids, self.sigma2, backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) rec.garch_recursion(parameters, np.abs(self.resids), np.sign(self.resids), cond_var_direct, 1, 0, 1, self.T, backcast, var_bounds) cond_var_direct **= 2.0 # Square since recursion does not apply power assert_allclose(self.sigma2, cond_var_direct) A, b = garch.constraints() A_target = np.vstack((np.eye(3), np.array([[0, -1.0, -1.0]]))) b_target = np.array([0.0, 0.0, 0.0, -1.0]) assert_array_equal(A, A_target) assert_array_equal(b, b_target) state = np.random.get_state() rng = Normal() sim_data = garch.simulate(parameters, self.T, rng.simulate([])) np.random.set_state(state) e = np.random.standard_normal(self.T + 500) initial_value = 1.0 sigma = np.zeros(self.T + 500) data = np.zeros(self.T + 500) for t in range(self.T + 500): sigma[t] = parameters[0] shock = initial_value if t == 0 else np.abs(data[t - 1]) sigma[t] += parameters[1] * shock lagged_value = initial_value if t == 0 else sigma[t - 1] sigma[t] += parameters[2] * lagged_value data[t] = e[t] * sigma[t] data = data[500:] sigma2 = sigma[500:] ** 2.0 assert_almost_equal(data - sim_data[0] + 1.0, np.ones_like(data)) assert_almost_equal(sigma2 / sim_data[1], np.ones_like(sigma2))
def test_model_names(self): garch = GARCH(2, 0, 0) assert_equal(garch.name, 'ARCH') garch = GARCH(2, 0, 2) assert_equal(garch.name, 'GARCH') garch = GARCH(2, 2, 2) assert_equal(garch.name, 'GJR-GARCH') garch = GARCH(1, 0, 0, power=1.0) assert_equal(garch.name, 'AVARCH') garch = GARCH(1, 0, 1, power=1.0) assert_equal(garch.name, 'AVGARCH') garch = GARCH(1, 1, 1, power=1.0) assert_equal(garch.name, 'TARCH/ZARCH') garch = GARCH(3, 0, 0, power=1.5) assert_equal(garch.name, 'Power ARCH (power: 1.5)') assert_true('Power' in garch.__str__()) garch = GARCH(1, 2, 1, power=1.5) assert_equal(garch.name, 'Asym. Power GARCH (power: 1.5)') garch = GARCH(2, 0, 2, power=1.5) assert_equal(garch.name, 'Power GARCH (power: 1.5)')
def test_garch(self): garch = GARCH() sv = garch.starting_values(self.resids) assert_equal(sv.shape[0], garch.num_params) bounds = garch.bounds(self.resids) assert_equal(bounds[0], (0.0, 10.0 * np.mean(self.resids ** 2.0))) assert_equal(bounds[1], (0.0, 1.0)) assert_equal(bounds[2], (0.0, 1.0)) backcast = garch.backcast(self.resids) w = 0.94 ** np.arange(75) assert_almost_equal(backcast, np.sum((self.resids[:75] ** 2) * (w / w.sum()))) var_bounds = garch.variance_bounds(self.resids) parameters = np.array([.1, .1, .8]) garch.compute_variance(parameters, self.resids, self.sigma2, backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) rec.garch_recursion(parameters, self.resids ** 2.0, np.sign(self.resids), cond_var_direct, 1, 0, 1, self.T, backcast, var_bounds) assert_allclose(self.sigma2, cond_var_direct) A, b = garch.constraints() A_target = np.vstack((np.eye(3), np.array([[0, -1.0, -1.0]]))) b_target = np.array([0.0, 0.0, 0.0, -1.0]) assert_array_equal(A, A_target) assert_array_equal(b, b_target) state = np.random.get_state() rng = Normal() sim_data = garch.simulate(parameters, self.T, rng.simulate([])) np.random.set_state(state) e = np.random.standard_normal(self.T + 500) initial_value = 1.0 sigma2 = np.zeros(self.T + 500) data = np.zeros(self.T + 500) for t in range(self.T + 500): sigma2[t] = parameters[0] shock = initial_value if t == 0 else data[t - 1] ** 2.0 sigma2[t] += parameters[1] * shock lagged_value = initial_value if t == 0 else sigma2[t - 1] sigma2[t] += parameters[2] * lagged_value data[t] = e[t] * np.sqrt(sigma2[t]) data = data[500:] sigma2 = sigma2[500:] assert_almost_equal(data / sim_data[0], np.ones_like(data)) assert_almost_equal(sigma2 / sim_data[1], np.ones_like(sigma2)) names = garch.parameter_names() names_target = ['omega', 'alpha[1]', 'beta[1]'] assert_equal(names, names_target) assert_true(isinstance(garch.__str__(), str)) repr = garch.__repr__() assert_true(str(hex(id(garch))) in repr) assert_equal(garch.name, 'GARCH') assert_equal(garch.num_params, 3) assert_equal(garch.power, 2.0) assert_equal(garch.p, 1) assert_equal(garch.o, 0) assert_equal(garch.q, 1)
def test_exog_smoke(x): gim = ARCHInMean(SP500, constant=False, volatility=GARCH(), x=x) res = gim.fit(disp="off") x_shape = 1 if isinstance(x, pd.Series) else x.shape[1] assert res.params.shape[0] == 4 + x_shape
def test_no_constant(): gim = ARCHInMean(SP500, constant=False, volatility=GARCH()) res = gim.fit(disp=False) assert res.params.shape[0] == 4
def test_garch(self): garch = GARCH() sv = garch.starting_values(self.resids) assert_equal(sv.shape[0], garch.num_params) bounds = garch.bounds(self.resids) assert_equal(bounds[0], (0.0, 10.0 * np.mean(self.resids**2.0))) assert_equal(bounds[1], (0.0, 1.0)) assert_equal(bounds[2], (0.0, 1.0)) backcast = garch.backcast(self.resids) w = 0.94**np.arange(75) assert_almost_equal(backcast, np.sum((self.resids[:75]**2) * (w / w.sum()))) var_bounds = garch.variance_bounds(self.resids) parameters = np.array([.1, .1, .8]) garch.compute_variance(parameters, self.resids, self.sigma2, backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) rec.garch_recursion(parameters, self.resids**2.0, np.sign(self.resids), cond_var_direct, 1, 0, 1, self.T, backcast, var_bounds) assert_allclose(self.sigma2, cond_var_direct) a, b = garch.constraints() a_target = np.vstack((np.eye(3), np.array([[0, -1.0, -1.0]]))) b_target = np.array([0.0, 0.0, 0.0, -1.0]) assert_array_equal(a, a_target) assert_array_equal(b, b_target) state = np.random.get_state() rng = Normal() sim_data = garch.simulate(parameters, self.T, rng.simulate([])) np.random.set_state(state) e = np.random.standard_normal(self.T + 500) initial_value = 1.0 sigma2 = np.zeros(self.T + 500) data = np.zeros(self.T + 500) for t in range(self.T + 500): sigma2[t] = parameters[0] shock = initial_value if t == 0 else data[t - 1]**2.0 sigma2[t] += parameters[1] * shock lagged_value = initial_value if t == 0 else sigma2[t - 1] sigma2[t] += parameters[2] * lagged_value data[t] = e[t] * np.sqrt(sigma2[t]) data = data[500:] sigma2 = sigma2[500:] assert_almost_equal(data / sim_data[0], np.ones_like(data)) assert_almost_equal(sigma2 / sim_data[1], np.ones_like(sigma2)) names = garch.parameter_names() names_target = ['omega', 'alpha[1]', 'beta[1]'] assert_equal(names, names_target) assert isinstance(garch.__str__(), str) txt = garch.__repr__() assert str(hex(id(garch))) in txt assert_equal(garch.name, 'GARCH') assert_equal(garch.num_params, 3) assert_equal(garch.power, 2.0) assert_equal(garch.p, 1) assert_equal(garch.o, 0) assert_equal(garch.q, 1)
def simulated_data(request): rs = np.random.RandomState(1) zm = ZeroMean(volatility=GARCH(), distribution=Normal(rs)) sim_data = zm.simulate(np.array([0.1, 0.1, 0.88]), 1000) return np.asarray(sim_data.data) if request.param else sim_data.data
def test_ar(self): ar = ARX(self.y, lags=3) params = np.array([1.0, 0.4, 0.3, 0.2, 1.0]) data = ar.simulate(params, self.T) assert len(data) == self.T assert_equal(self.y, ar.y) bounds = ar.bounds() for b in bounds: assert_equal(b[0], -np.inf) assert_equal(b[1], np.inf) assert_equal(len(bounds), 4) assert_equal(ar.num_params, 4) assert ar.constant a, b = ar.constraints() assert_equal(a, np.empty((0, 4))) assert_equal(b, np.empty(0)) res = ar.fit(disp=DISPLAY) nobs = 1000 - 3 rhs = np.ones((nobs, 4)) y = self.y lhs = y[3:1000] for i in range(3, 1000): rhs[i - 3, 1] = y[i - 1] rhs[i - 3, 2] = y[i - 2] rhs[i - 3, 3] = y[i - 3] params = np.linalg.pinv(rhs).dot(lhs) assert_almost_equal(params, res.params[:-1]) forecasts = res.forecast(horizon=5) direct = pd.DataFrame( index=np.arange(y.shape[0]), columns=["h." + str(i + 1) for i in range(5)], dtype="float64", ) params = res.params.iloc[:-1] for i in range(2, y.shape[0]): fcast = np.zeros(y.shape[0] + 5) fcast[:y.shape[0]] = y.copy() for h in range(1, 6): reg = np.array([ 1.0, fcast[i + h - 1], fcast[i + h - 2], fcast[i + h - 3] ]) fcast[i + h] = reg.dot(params) direct.iloc[i, :] = fcast[i + 1:i + 6] assert isinstance(forecasts, ARCHModelForecast) # TODO # assert_frame_equal(direct, forecasts) assert ar.hold_back is None assert_equal(ar.lags, np.array([[0, 1, 2], [1, 2, 3]])) assert_equal(ar.name, "AR") assert_equal(ar.use_rotated, False) ar.__repr__() ar._repr_html_() ar = ARX(self.y_df, lags=5) ar.__repr__() ar = ARX(self.y_series, lags=5) ar.__repr__() res = ar.fit(disp=DISPLAY) assert isinstance(res.resid, pd.Series) assert isinstance(res.conditional_volatility, pd.Series) std_resid = res.resid / res.conditional_volatility std_resid.name = "std_resid" assert_series_equal(res.std_resid, std_resid) # Smoke bootstrap summ = ar.fit(disp=DISPLAY).summary() assert "Constant Variance" in str(summ) ar = ARX(self.y, lags=1, volatility=GARCH(), distribution=StudentsT()) res = ar.fit(disp=DISPLAY, update_freq=5, cov_type="mle") assert isinstance(res.param_cov, pd.DataFrame) sims = res.forecast(horizon=5, method="simulation") assert isinstance(sims.simulations.residual_variances, np.ndarray) assert isinstance(sims.simulations.residuals, np.ndarray) assert isinstance(sims.simulations.values, np.ndarray) assert isinstance(sims.simulations.variances, np.ndarray)
def simulated_data(): rs = np.random.RandomState(1) zm = ZeroMean(volatility=GARCH(), distribution=Normal(rs)) sim_data = zm.simulate(np.array([0.1, 0.1, 0.88]), 1000) return sim_data.data
def test_false_reindex(): res = ConstantMean(SP500, volatility=GARCH()).fit(disp="off") fcast = res.forecast(start=0, reindex=True) assert fcast.mean.shape[0] == SP500.shape[0] assert_series_equal(pd.Series(fcast.mean.index), pd.Series(SP500.index))
def arch_model(y, x=None, mean='Constant', lags=0, vol='Garch', p=1, o=0, q=1, power=2.0, dist='Normal', hold_back=None): """ Convenience function to simplify initialization of ARCH models Parameters ---------- y : {ndarray, Series, None} The dependent variable x : {np.array, DataFrame}, optional Exogenous regressors. Ignored if model does not permit exogenous regressors. mean : str, optional Name of the mean model. Currently supported options are: 'Constant', 'Zero', 'ARX' and 'HARX' lags : int or list (int), optional Either a scalar integer value indicating lag length or a list of integers specifying lag locations. vol : str, optional Name of the volatility model. Currently supported options are: 'GARCH' (default), "EGARCH', 'ARCH' and 'HARCH' p : int, optional Lag order of the symmetric innovation o : int, optional Lag order of the asymmetric innovation q : int, optional Lag order of lagged volatility or equivalent power : float, optional Power to use with GARCH and related models dist : int, optional Name of the error distribution. Currently supported options are: * Normal: 'normal', 'gaussian' (default) * Students's t: 't', 'studentst' * Skewed Student's t: 'skewstudent', 'skewt' * Generalized Error Distribution: 'ged', 'generalized error" hold_back : int Number of observations at the start of the sample to exclude when estimating model parameters. Used when comparing models with different lag lengths to estimate on the common sample. Returns ------- model : ARCHModel Configured ARCH model Examples -------- >>> import datetime as dt >>> import pandas_datareader.data as web >>> djia = web.get_data_fred('DJIA') >>> returns = 100 * djia['DJIA'].pct_change().dropna() A basic GARCH(1,1) with a constant mean can be constructed using only the return data >>> from arch.univariate import arch_model >>> am = arch_model(returns) Alternative mean and volatility processes can be directly specified >>> am = arch_model(returns, mean='AR', lags=2, vol='harch', p=[1, 5, 22]) This example demonstrates the construction of a zero mean process with a TARCH volatility process and Student t error distribution >>> am = arch_model(returns, mean='zero', p=1, o=1, q=1, ... power=1.0, dist='StudentsT') Notes ----- Input that are not relevant for a particular specification, such as `lags` when `mean='zero'`, are silently ignored. """ known_mean = ('zero', 'constant', 'harx', 'har', 'ar', 'arx', 'ls') known_vol = ('arch', 'garch', 'harch', 'constant', 'egarch') known_dist = ('normal', 'gaussian', 'studentst', 't', 'skewstudent', 'skewt', 'ged', 'generalized error') mean = mean.lower() vol = vol.lower() dist = dist.lower() if mean not in known_mean: raise ValueError('Unknown model type in mean') if vol.lower() not in known_vol: raise ValueError('Unknown model type in vol') if dist.lower() not in known_dist: raise ValueError('Unknown model type in dist') if mean == 'zero': am = ZeroMean(y, hold_back=hold_back) elif mean == 'constant': am = ConstantMean(y, hold_back=hold_back) elif mean == 'harx': am = HARX(y, x, lags, hold_back=hold_back) elif mean == 'har': am = HARX(y, None, lags, hold_back=hold_back) elif mean == 'arx': am = ARX(y, x, lags, hold_back=hold_back) elif mean == 'ar': am = ARX(y, None, lags, hold_back=hold_back) else: am = LS(y, x, hold_back=hold_back) if vol == 'constant': v = ConstantVariance() elif vol == 'arch': v = ARCH(p=p) elif vol == 'garch': v = GARCH(p=p, o=o, q=q, power=power) elif vol == 'egarch': v = EGARCH(p=p, o=o, q=q) else: # vol == 'harch' v = HARCH(lags=p) if dist in ('skewstudent', 'skewt'): d = SkewStudent() elif dist in ('studentst', 't'): d = StudentsT() elif dist in ('ged', 'generalized error'): d = GeneralizedError() else: # ('gaussian', 'normal') d = Normal() am.volatility = v am.distribution = d return am
def test_model_names(self): garch = GARCH(2, 0, 0) assert_equal(garch.name, 'ARCH') garch = GARCH(2, 0, 2) assert_equal(garch.name, 'GARCH') garch = GARCH(2, 2, 2) assert_equal(garch.name, 'GJR-GARCH') garch = GARCH(1, 0, 0, power=1.0) assert_equal(garch.name, 'AVARCH') garch = GARCH(1, 0, 1, power=1.0) assert_equal(garch.name, 'AVGARCH') garch = GARCH(1, 1, 1, power=1.0) assert_equal(garch.name, 'TARCH/ZARCH') garch = GARCH(3, 0, 0, power=1.5) assert_equal(garch.name, 'Power ARCH (power: 1.5)') assert 'Power' in garch.__str__() garch = GARCH(1, 2, 1, power=1.5) assert_equal(garch.name, 'Asym. Power GARCH (power: 1.5)') garch = GARCH(2, 0, 2, power=1.5) assert_equal(garch.name, 'Power GARCH (power: 1.5)')
def test_garch_no_symmetric(self): garch = GARCH(p=0, o=1, q=1) sv = garch.starting_values(self.resids) assert_equal(sv.shape[0], garch.num_params) bounds = garch.bounds(self.resids) assert_equal(bounds[0], (0.0, 10.0 * np.mean(self.resids**2.0))) assert_equal(bounds[1], (0.0, 2.0)) assert_equal(bounds[2], (0.0, 1.0)) var_bounds = garch.variance_bounds(self.resids) backcast = garch.backcast(self.resids) parameters = np.array([.1, .1, .8]) names = garch.parameter_names() names_target = ['omega', 'gamma[1]', 'beta[1]'] assert_equal(names, names_target) garch.compute_variance(parameters, self.resids, self.sigma2, backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) rec.garch_recursion(parameters, self.resids**2.0, np.sign(self.resids), cond_var_direct, 0, 1, 1, self.T, backcast, var_bounds) assert_allclose(self.sigma2, cond_var_direct) a, b = garch.constraints() a_target = np.vstack((np.eye(3), np.array([[0, -0.5, -1.0]]))) b_target = np.array([0.0, 0.0, 0.0, -1.0]) assert_array_equal(a, a_target) assert_array_equal(b, b_target) state = np.random.get_state() rng = Normal() sim_data = garch.simulate(parameters, self.T, rng.simulate([])) np.random.set_state(state) e = np.random.standard_normal(self.T + 500) initial_value = 1.0 sigma2 = np.zeros(self.T + 500) data = np.zeros(self.T + 500) for t in range(self.T + 500): sigma2[t] = parameters[0] shock = 0.5 * initial_value if t == 0 else \ data[t - 1] ** 2.0 * (data[t - 1] < 0) sigma2[t] += parameters[1] * shock lagged_value = initial_value if t == 0 else sigma2[t - 1] sigma2[t] += parameters[2] * lagged_value data[t] = e[t] * np.sqrt(sigma2[t]) data = data[500:] sigma2 = sigma2[500:] assert_almost_equal(data - sim_data[0] + 1.0, np.ones_like(data)) assert_almost_equal(sigma2 / sim_data[1], np.ones_like(sigma2)) assert_equal(garch.p, 0) assert_equal(garch.o, 1) assert_equal(garch.q, 1) assert_equal(garch.num_params, 3) assert_equal(garch.name, 'GJR-GARCH')
def test_example_smoke(): rets = SP500 gim = ARCHInMean(rets, lags=[1, 2], volatility=GARCH()) res = gim.fit(disp=False) assert res.params.shape[0] == 7
def arch_model( y: Optional[ArrayLike], x: Optional[ArrayLike] = None, mean: str = "Constant", lags: Optional[Union[int, List[int], NDArray]] = 0, vol: str = "Garch", p: Union[int, List[int]] = 1, o: int = 0, q: int = 1, power: float = 2.0, dist: str = "Normal", hold_back: Optional[int] = None, rescale: Optional[bool] = None, ) -> HARX: """ Initialization of common ARCH model specifications Parameters ---------- y : {ndarray, Series, None} The dependent variable x : {np.array, DataFrame}, optional Exogenous regressors. Ignored if model does not permit exogenous regressors. mean : str, optional Name of the mean model. Currently supported options are: 'Constant', 'Zero', 'LS', 'AR', 'ARX', 'HAR' and 'HARX' lags : int or list (int), optional Either a scalar integer value indicating lag length or a list of integers specifying lag locations. vol : str, optional Name of the volatility model. Currently supported options are: 'GARCH' (default), 'ARCH', 'EGARCH', 'FIARCH' and 'HARCH' p : int, optional Lag order of the symmetric innovation o : int, optional Lag order of the asymmetric innovation q : int, optional Lag order of lagged volatility or equivalent power : float, optional Power to use with GARCH and related models dist : int, optional Name of the error distribution. Currently supported options are: * Normal: 'normal', 'gaussian' (default) * Students's t: 't', 'studentst' * Skewed Student's t: 'skewstudent', 'skewt' * Generalized Error Distribution: 'ged', 'generalized error" hold_back : int Number of observations at the start of the sample to exclude when estimating model parameters. Used when comparing models with different lag lengths to estimate on the common sample. rescale : bool Flag indicating whether to automatically rescale data if the scale of the data is likely to produce convergence issues when estimating model parameters. If False, the model is estimated on the data without transformation. If True, than y is rescaled and the new scale is reported in the estimation results. Returns ------- model : ARCHModel Configured ARCH model Examples -------- >>> import datetime as dt >>> import pandas_datareader.data as web >>> djia = web.get_data_fred('DJIA') >>> returns = 100 * djia['DJIA'].pct_change().dropna() A basic GARCH(1,1) with a constant mean can be constructed using only the return data >>> from arch.univariate import arch_model >>> am = arch_model(returns) Alternative mean and volatility processes can be directly specified >>> am = arch_model(returns, mean='AR', lags=2, vol='harch', p=[1, 5, 22]) This example demonstrates the construction of a zero mean process with a TARCH volatility process and Student t error distribution >>> am = arch_model(returns, mean='zero', p=1, o=1, q=1, ... power=1.0, dist='StudentsT') Notes ----- Input that are not relevant for a particular specification, such as `lags` when `mean='zero'`, are silently ignored. """ known_mean = ("zero", "constant", "harx", "har", "ar", "arx", "ls") known_vol = ("arch", "figarch", "garch", "harch", "constant", "egarch") known_dist = ( "normal", "gaussian", "studentst", "t", "skewstudent", "skewt", "ged", "generalized error", ) mean = mean.lower() vol = vol.lower() dist = dist.lower() if mean not in known_mean: raise ValueError("Unknown model type in mean") if vol.lower() not in known_vol: raise ValueError("Unknown model type in vol") if dist.lower() not in known_dist: raise ValueError("Unknown model type in dist") if mean == "harx": am = HARX(y, x, lags, hold_back=hold_back, rescale=rescale) elif mean == "har": am = HARX(y, None, lags, hold_back=hold_back, rescale=rescale) elif mean == "arx": am = ARX(y, x, lags, hold_back=hold_back, rescale=rescale) elif mean == "ar": am = ARX(y, None, lags, hold_back=hold_back, rescale=rescale) elif mean == "ls": am = LS(y, x, hold_back=hold_back, rescale=rescale) elif mean == "constant": am = ConstantMean(y, hold_back=hold_back, rescale=rescale) else: # mean == "zero" am = ZeroMean(y, hold_back=hold_back, rescale=rescale) if vol in ("arch", "garch", "figarch", "egarch") and not isinstance(p, int): raise TypeError( "p must be a scalar int for all volatility processes except HARCH." ) if vol == "constant": v: VolatilityProcess = ConstantVariance() elif vol == "arch": assert isinstance(p, int) v = ARCH(p=p) elif vol == "figarch": assert isinstance(p, int) v = FIGARCH(p=p, q=q) elif vol == "garch": assert isinstance(p, int) v = GARCH(p=p, o=o, q=q, power=power) elif vol == "egarch": assert isinstance(p, int) v = EGARCH(p=p, o=o, q=q) else: # vol == 'harch' v = HARCH(lags=p) if dist in ("skewstudent", "skewt"): d: Distribution = SkewStudent() elif dist in ("studentst", "t"): d = StudentsT() elif dist in ("ged", "generalized error"): d = GeneralizedError() else: # ('gaussian', 'normal') d = Normal() am.volatility = v am.distribution = d return am