From 3d80b3d4f447cf8f18a78ac2ac9d9bfc741bde56 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 9 Jul 2017 11:03:00 +0300 Subject: [PATCH 01/92] print start --- arch.pyproj | 110 ++++++++++++++++++++++++++++++++++ arch/univariate/volatility.py | 2 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 arch.pyproj diff --git a/arch.pyproj b/arch.pyproj new file mode 100644 index 0000000000..c94c0fd34d --- /dev/null +++ b/arch.pyproj @@ -0,0 +1,110 @@ + + + + Debug + 2.0 + {407f4449-6194-4c82-b89a-45f9cf6f148f} + + arch\univariate\volatility.py + + . + . + {888888a0-9f3d-457c-b088-3a5042f75d52} + Standard Python launcher + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 873cdfb202..3110375b9c 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -4,7 +4,7 @@ same inputs. """ from __future__ import absolute_import, division - +print("start") import itertools import numpy as np From 7be31f6ed81264e6f5e8294656b8b4523c5d5ed4 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 9 Jul 2017 11:17:48 +0300 Subject: [PATCH 02/92] added recursion and cgarch process --- arch/univariate/recursions_python.py | 32 ++++++++++- arch/univariate/volatility.py | 83 +++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index 6313a5958f..68c5bb67d1 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -11,7 +11,7 @@ import numpy as np __all__ = ['harch_recursion', 'arch_recursion', 'garch_recursion', - 'egarch_recursion'] + 'egarch_recursion', "cgarch_recursion"] def harch_recursion_python(parameters, resids, sigma2, lags, nobs, backcast, @@ -240,3 +240,33 @@ def egarch_recursion_python(parameters, resids, sigma2, p, o, q, nobs, egarch_recursion = jit(egarch_recursion_python) + +def cgarch_recursion_python(parameters, fresids, sigma2, nobs, + backcast, var_bounds): + sqrd_resids = fresids + alpha, beta, omega, raw, phi = parameters + + initial_sigma2 = backcast + initial_q2 = 0.05 + initial_g2 = 0.005 - initial_q2 + + # g is short term variance and q is the long term one + g2, q2 = ndarray(nobs*2).reshape(2,nobs) + g2[0] = initial_g2 + q2[0] = initial_q2 + sigma2[0] = initial_sigma2 + + for t in range(1,nobs): + g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * g2[t-1] + q2[t] = omega + raw * q2[t-1] + phi * (sqrd_resids[t-1] - sigma2[t-1]) + sigma2[t] = g2[t] + q2[t] + if sigma2[t] var_bounds[t, 1]: + if not isinf(sigma2[t]): + sigma2[t] = var_bounds[t, 1] + \ + log(sigma2[t] / var_bounds[t, 1]) + else: + sigma2[t] = var_bounds[t, 1] + 1000 + return sigma2 +cgarch_recursion = jit(cgarch_recursion_python) \ No newline at end of file diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 3110375b9c..454c0f1b4c 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -4,7 +4,6 @@ same inputs. """ from __future__ import absolute_import, division -print("start") import itertools import numpy as np @@ -16,10 +15,10 @@ from arch.utility.array import ensure1d, DocStringInheritor try: - from arch.univariate.recursions import garch_recursion, harch_recursion, egarch_recursion + from arch.univariate.recursions import garch_recursion, harch_recursion, egarch_recursion, cgarch_recursion except ImportError: # pragma: no cover from arch.univariate.recursions_python import (garch_recursion, harch_recursion, - egarch_recursion) + egarch_recursion, cgarch_recursion) __all__ = ['GARCH', 'ARCH', 'HARCH', 'ConstantVariance', 'EWMAVariance', 'RiskMetrics2006', 'EGARCH', 'FixedVariance'] @@ -1982,3 +1981,81 @@ def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, shocks.fill(np.nan) return VarianceForecast(forecasts, forecast_paths, shocks) + +class CGARCH(VolatilityProcess): + def __init__(self): + super().__init__() + self.num_params = 5 + self.name = "ComponentGarch" + + def variance_bounds(self, resids, power=2.0): + return super().variance_bounds(resids) + + def constraints(self): + # alpha>0 + # beta-phi>0 + # phi-alpha-beta>0 + # alpha-beta<1 written as 1-alpha-beta >0 + + a = np.array([1,0,0,0,0]) + other_cons = np.array([[0,1,0,0,-1],[-1,-1,0,1,0],[-1,-1,0,0,0]]) + a = np.vstack((a,other_cons)) + b = np.array([0,0,0,-1]) + return a, b + + def backcast(self, resids): + return super().backcast(resids) + + def bounds(self, resids): + return [(0,1), (0,1), (-1, 1), (-1, 1), (0, 1)] + + def starting_values(self, resids): + return np.array([np.var(resids)/5, 0.1, 0.002, 0.3, 0.5]) + + def compute_variance(self, parameters, resids, sigma2, backcast, + var_bounds): + nobs = len(resids) + fresids = resids**2 + + cgarch_recursion(parameters, fresids, sigma2, nobs, + backcast, var_bounds) + + return sigma2 + + def parameter_names(self): + names = ["alpha", "beta", "omega", "rho", "phi"] + return names + + def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): + T = nobs + burn + errors = rng(T) + sigma2 = zeros(T) + data = zeros(T) + + # short_term component + g2 = zeros(T) + # long_ term + q2 = zeros(T) + + if initial_value is None: + alpha, beta, omega, rho, phi = parameters + # Cgarch can be represented as a restricted garch(2,2) with: + a0 = omega*(1-alpha-beta) + a1 = phi +alpha + a2 = phi*(alpha + beta) + alpha*rho + b1 = rho + beta - phi + b2 = phi*(alpha + beta) - rho*beta + # the unconditional var of this garch(2,2) form is used as initial value + initial_value = a0/(1-(a1+a2+b1+b2)) + + sigma2[0] = initial_value + q2[0] = initial_value * 0.65 + g2[0] = initial_value - g2[0] + data[0] = sqrt(sigma2[0]) * errors[0] + + for i in range(1, T): + g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] + q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) + sigma2[i] = g2[i] + q2[i] + data[i] = errors[i] * (np.sqrt(sigma2[i])) ** 2 + return data[burn:], sigma2[burn:] From bf63a26432ce60297bdc157d1f2e11120f4ad54a Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 9 Jul 2017 12:01:23 +0300 Subject: [PATCH 03/92] included cgarch in init --- .gitignore | 3 ++- arch/univariate/__init__.py | 6 +++--- arch/univariate/recursions_python.py | 2 +- arch/univariate/volatility.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 1a48374a43..dfcd55ead3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ build/ dist .benchmarks/ .cache/ -README.rst \ No newline at end of file +README.rst +*.suo diff --git a/arch/univariate/__init__.py b/arch/univariate/__init__.py index 6935786b63..0eae4f6aeb 100644 --- a/arch/univariate/__init__.py +++ b/arch/univariate/__init__.py @@ -1,12 +1,12 @@ from __future__ import absolute_import from arch.univariate.mean import HARX, ConstantMean, ZeroMean, ARX, arch_model, LS -from arch.univariate.volatility import (GARCH, ARCH, HARCH, ConstantVariance, EWMAVariance, +from arch.univariate.volatility import (GARCH, ARCH, HARCH, CGARCH, ConstantVariance, EWMAVariance, RiskMetrics2006, EGARCH, FixedVariance) from arch.univariate.distribution import Distribution, Normal, StudentsT, SkewStudent -__all__ = ['HARX', 'ConstantMean', 'ZeroMean', 'ARX', 'arch_model', 'LS', - 'GARCH', 'ARCH', 'HARCH', 'ConstantVariance', +__all__ = ['HARX', 'ConstantMean', 'ZeroMean', 'ARX', 'arch_model', 'LS', + 'GARCH', 'ARCH', 'HARCH', 'ConstantVariance', 'CGARCH', 'EWMAVariance', 'RiskMetrics2006', 'EGARCH', 'Distribution', 'Normal', 'StudentsT', 'SkewStudent', 'FixedVariance'] diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index 68c5bb67d1..e3347206db 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -11,7 +11,7 @@ import numpy as np __all__ = ['harch_recursion', 'arch_recursion', 'garch_recursion', - 'egarch_recursion', "cgarch_recursion"] + 'egarch_recursion', 'cgarch_recursion'] def harch_recursion_python(parameters, resids, sigma2, lags, nobs, backcast, diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 454c0f1b4c..6269856c0d 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -21,7 +21,7 @@ egarch_recursion, cgarch_recursion) __all__ = ['GARCH', 'ARCH', 'HARCH', 'ConstantVariance', 'EWMAVariance', 'RiskMetrics2006', - 'EGARCH', 'FixedVariance'] + 'EGARCH', 'FixedVariance', 'CGARCH'] class BootstrapRng(object): From a9bc455b6ac7f7ba8987cb2f772909be6d84e9fd Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 10 Jul 2017 22:21:54 +0300 Subject: [PATCH 04/92] Add .suo to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1a48374a43..2fe9125aad 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ build/ dist .benchmarks/ .cache/ -README.rst \ No newline at end of file +README.rst +/.vs/arch/v14/.suo From 0a27e12e4e8b03d1fbc9e2e6c598d507e20442fc Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 13 Jul 2017 20:46:38 +0300 Subject: [PATCH 05/92] Created empty forecast methods --- arch/univariate/volatility.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 6269856c0d..13522f8c9f 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2059,3 +2059,8 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): sigma2[i] = g2[i] + q2[i] data[i] = errors[i] * (np.sqrt(sigma2[i])) ** 2 return data[burn:], sigma2[burn:] + def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): + + return + def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, horizon, simulations, rng): + return \ No newline at end of file From 3ec5f3bb8710a92edb87c91c37049e964889c190 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 22 Jul 2017 08:22:38 +0300 Subject: [PATCH 06/92] Add pyproj to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2fe9125aad..f48329be86 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist .cache/ README.rst /.vs/arch/v14/.suo +*.pyproj From fb2164956d378a44d98815ad5b99fe1749d25100 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 24 Jul 2017 07:16:29 +0300 Subject: [PATCH 07/92] Add CGARCH forecast --- arch/univariate/volatility.py | 136 +++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 11 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 13522f8c9f..47a21f0734 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -3,7 +3,7 @@ inherit from :class:`VolatilityProcess` and provide the same methods with the same inputs. """ -from __future__ import absolute_import, division +from future import absolute_import, division import itertools import numpy as np @@ -1982,9 +1982,27 @@ def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, return VarianceForecast(forecasts, forecast_paths, shocks) -class CGARCH(VolatilityProcess): +class CGARCH(GARCH): + r""" + Component GARCH model. A restricted version of GARCH(2,2) + + Notes + ----- + In this class of processes, the variance dynamics are + + .. math:: + + \sigma_{t}=q_{t}+g_{t} + g_{t}=\omega + \rho + + \sum_{i=1}^{p}\alpha_{i}\left|\epsilon_{t-i}\right|^{\lambda} + +\sum_{j=1}^{o}\gamma_{j}\left|\epsilon_{t-j}\right|^{\lambda} + I\left[\epsilon_{t-j}<0\right]+\sum_{k=1}^{q}\beta_{k}\sigma_{t-k}^{\lambda} + """ + def __init__(self): super().__init__() + self.p = 2 + self.q = 2 self.num_params = 5 self.name = "ComponentGarch" @@ -2026,6 +2044,16 @@ def parameter_names(self): names = ["alpha", "beta", "omega", "rho", "phi"] return names + def _covertparams(self, parameters): + # this will convert the cgarch params into restricted GARCH(2,2) parameters + alpha, beta, omega, rho, phi = parameters + a0 = omega*(1-alpha-beta) + a1 = phi +alpha + a2 = phi*(alpha + beta) + alpha*rho + b1 = rho + beta - phi + b2 = phi*(alpha + beta) - rho*beta + return [a0, a1, a2, b1, b2] + def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): T = nobs + burn errors = rng(T) @@ -2038,13 +2066,8 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): q2 = zeros(T) if initial_value is None: - alpha, beta, omega, rho, phi = parameters # Cgarch can be represented as a restricted garch(2,2) with: - a0 = omega*(1-alpha-beta) - a1 = phi +alpha - a2 = phi*(alpha + beta) + alpha*rho - b1 = rho + beta - phi - b2 = phi*(alpha + beta) - rho*beta + a0, a1, a2, b1, b2 = self._covertparams(parameters) # the unconditional var of this garch(2,2) form is used as initial value initial_value = a0/(1-(a1+a2+b1+b2)) @@ -2059,8 +2082,99 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): sigma2[i] = g2[i] + q2[i] data[i] = errors[i] * (np.sqrt(sigma2[i])) ** 2 return data[burn:], sigma2[burn:] + def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): - - return + sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, + var_bounds, horizon) + if horizon == 1: + forecasts[:start] = np.nan + return VarianceForecast(forecasts) + parameters = self._covertparams(parameters) + t = resids.shape[0] + p, o, q = self.p, self.o, self.q + omega = parameters[0] + alpha = parameters[1:p + 1] + gamma = parameters[p + 1: p + o + 1] + beta = parameters[p + o + 1:] + + m = np.max([p, o, q]) + _resids = np.zeros(m + horizon) + _asym_resids = np.zeros(m + horizon) + _sigma2 = np.zeros(m + horizon) + + for i in range(start, t): + if i - m + 1 >= 0: + _resids[:m] = resids[i - m + 1:i + 1] + _asym_resids[:m] = _resids[:m] * (_resids[:m] < 0) + _sigma2[:m] = sigma2[i - m + 1:i + 1] + else: # Back-casting needed + _resids[:m - i - 1] = np.sqrt(backcast) + _resids[m - i - 1: m] = resids[0:i + 1] + _asym_resids = _resids * (_resids < 0) + _asym_resids[:m - i - 1] = np.sqrt(0.5 * backcast) + _sigma2[:m] = backcast + _sigma2[m - i - 1: m] = sigma2[0:i + 1] + + for h in range(0, horizon): + forecasts[i, h] = omega + start_loc = h + m - 1 + + for j in range(p): + forecasts[i, h] += alpha[j] * _resids[start_loc - j] ** 2 + + for j in range(o): + forecasts[i, h] += gamma[j] * _asym_resids[start_loc - j] ** 2 + + for j in range(q): + forecasts[i, h] += beta[j] * _sigma2[start_loc - j] + + _resids[h + m] = np.sqrt(forecasts[i, h]) + _asym_resids[h + m] = np.sqrt(0.5 * forecasts[i, h]) + _sigma2[h + m] = forecasts[i, h] + + forecasts[:start] = np.nan + return VarianceForecast(forecasts) + + def _simulate_paths(self, m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock): + parameters = self._covertparams(parameters) + return super()._simulate_paths(m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock) + def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, horizon, simulations, rng): - return \ No newline at end of file + sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, + var_bounds, horizon) + #Everything is similar to GARCH class vut parameters have to be converted + parameters = self._covertparams(parameters) + t = resids.shape[0] + paths = np.zeros((t, simulations, horizon)) + shocks = np.zeros((t, simulations, horizon)) + + power = self.power + m = np.max([self.p, self.o, self.q]) + scaled_forecast_paths = zeros((simulations, m + horizon)) + scaled_shock = zeros((simulations, m + horizon)) + asym_scaled_shock = zeros((simulations, m + horizon)) + for i in range(start, t): + std_shocks = rng((simulations, horizon)) + if i - m < 0: + scaled_forecast_paths[:, :m] = backcast ** (power / 2.0) + scaled_shock[:, :m] = backcast ** (power / 2.0) + asym_scaled_shock[:, :m] = (0.5 * backcast) ** (power / 2.0) + + count = i + 1 + scaled_forecast_paths[:, m - count:m] = sigma2[:count] ** (power / 2.0) + scaled_shock[:, m - count:m] = np.abs(resids[:count]) ** power + asym = np.abs(resids[:count]) ** power * (resids[:count] < 0) + asym_scaled_shock[:, m - count:m] = asym + else: + scaled_forecast_paths[:, :m] = sigma2[i - m + 1:i + 1] ** (power / 2.0) + scaled_shock[:, :m] = np.abs(resids[i - m + 1:i + 1]) ** power + asym_scaled_shock[:, :m] = scaled_shock[:, :m] * (resids[i - m + 1:i + 1] < 0) + + f, p, s = self._simulate_paths(m, parameters, horizon, std_shocks, + scaled_forecast_paths, scaled_shock, asym_scaled_shock) + forecasts[i, :], paths[i], shocks[i] = f, p, s + + paths[:start] = np.nan + shocks[:start] = np.nan + forecasts[:start] = np.nan + return VarianceForecast(forecasts, paths, shocks) \ No newline at end of file From 53d1ea3e09d607f8239feb3f2d9f24471300cee2 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 24 Jul 2017 08:08:47 +0300 Subject: [PATCH 08/92] Add CGARCH docs --- arch/univariate/volatility.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 47a21f0734..5a371f63ac 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -1984,7 +1984,16 @@ def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, class CGARCH(GARCH): r""" - Component GARCH model. A restricted version of GARCH(2,2) + Component GARCH model. A restricted version of GARCH(2,2) by Engle and Lee + + Parameters + ---------- + All parameters are estimated + + Attributes + ---------- + num_params : int + The number of parameters in the model Notes ----- @@ -1992,11 +2001,10 @@ class CGARCH(GARCH): .. math:: - \sigma_{t}=q_{t}+g_{t} - g_{t}=\omega + \rho - + \sum_{i=1}^{p}\alpha_{i}\left|\epsilon_{t-i}\right|^{\lambda} - +\sum_{j=1}^{o}\gamma_{j}\left|\epsilon_{t-j}\right|^{\lambda} - I\left[\epsilon_{t-j}<0\right]+\sum_{k=1}^{q}\beta_{k}\sigma_{t-k}^{\lambda} + \sigma^{2}_{t}=q_{t}+g_{t} + q_{t}=\omega + \rho q_{t-1} + \phi(r^{2}_{t-1}-\sigma^{2}_{t-1}) + g_{t} = \alpha(r^{2}_{t-1}-q_{t-1})+\beta g_{t-1} + """ def __init__(self): From edb2aa3456d6a2599240d889c6d8a00d6bb137c4 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 24 Jul 2017 08:35:36 +0300 Subject: [PATCH 09/92] Add .sln to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f48329be86..6d88fd956d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ dist README.rst /.vs/arch/v14/.suo *.pyproj +*.sln From 2e06bc3652bdf6151f60b5595210bae94ea813a0 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Tue, 25 Jul 2017 15:19:41 +0300 Subject: [PATCH 10/92] Correct import future statement --- .gitignore | 4 ++++ arch.pyproj | 9 ++++++++- arch/univariate/volatility.py | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index dfcd55ead3..53fd24e49f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ dist .cache/ README.rst *.suo +/arch.sln +/totestimports.py +*.user +/.vs/config/applicationhost.config diff --git a/arch.pyproj b/arch.pyproj index c94c0fd34d..a398de9671 100644 --- a/arch.pyproj +++ b/arch.pyproj @@ -3,7 +3,7 @@ Debug 2.0 - {407f4449-6194-4c82-b89a-45f9cf6f148f} + {7b371827-037d-47aa-b84e-1363caa159ad} arch\univariate\volatility.py @@ -21,6 +21,7 @@ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets + @@ -61,6 +62,9 @@ + + Code + @@ -84,6 +88,9 @@ + + Code + diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 5a371f63ac..039886187a 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -3,7 +3,7 @@ inherit from :class:`VolatilityProcess` and provide the same methods with the same inputs. """ -from future import absolute_import, division +from __future__ import absolute_import, division import itertools import numpy as np From 6ed9a23dc8775e387ea9c622f746685dc3488379 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Tue, 25 Jul 2017 16:28:16 +0300 Subject: [PATCH 11/92] Ignore ipynb checkpoints --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 53fd24e49f..4b50067e8e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ README.rst /totestimports.py *.user /.vs/config/applicationhost.config +/examples/.ipynb_checkpoints/univariate_volatility_modeling-checkpoint.ipynb From 5125121737f0bc9b9eca8e6748d04cf49b9cbd13 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 28 Jul 2017 13:57:38 +0300 Subject: [PATCH 12/92] Correct recursion problem --- arch.pyproj | 2 +- arch/univariate/recursions_python.py | 13 ++++++------- arch/univariate/volatility.py | 8 ++++---- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/arch.pyproj b/arch.pyproj index a398de9671..622c75bc98 100644 --- a/arch.pyproj +++ b/arch.pyproj @@ -5,7 +5,7 @@ 2.0 {7b371827-037d-47aa-b84e-1363caa159ad} - arch\univariate\volatility.py + totestimports.py . . diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index e3347206db..c030046640 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -241,17 +241,17 @@ def egarch_recursion_python(parameters, resids, sigma2, p, o, q, nobs, egarch_recursion = jit(egarch_recursion_python) -def cgarch_recursion_python(parameters, fresids, sigma2, nobs, - backcast, var_bounds): +def cgarch_recursion_python(parameters, fresids, sigma2, + backcast, var_bounds, g2, q2): sqrd_resids = fresids + nobs = len(sqrd_resids) alpha, beta, omega, raw, phi = parameters initial_sigma2 = backcast initial_q2 = 0.05 - initial_g2 = 0.005 - initial_q2 + initial_g2 = initial_sigma2 - initial_q2 # g is short term variance and q is the long term one - g2, q2 = ndarray(nobs*2).reshape(2,nobs) g2[0] = initial_g2 q2[0] = initial_q2 sigma2[0] = initial_sigma2 @@ -263,9 +263,8 @@ def cgarch_recursion_python(parameters, fresids, sigma2, nobs, if sigma2[t] var_bounds[t, 1]: - if not isinf(sigma2[t]): - sigma2[t] = var_bounds[t, 1] + \ - log(sigma2[t] / var_bounds[t, 1]) + if not np.isinf(sigma2[t]): + sigma2[t] = var_bounds[t, 1] + log(sigma2[t] / var_bounds[t, 1]) else: sigma2[t] = var_bounds[t, 1] + 1000 return sigma2 diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 039886187a..61cedb181f 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2040,11 +2040,11 @@ def starting_values(self, resids): def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): - nobs = len(resids) fresids = resids**2 - - cgarch_recursion(parameters, fresids, sigma2, nobs, - backcast, var_bounds) + nobs = len(fresids) + g2, q2 = np.ndarray(nobs*2).reshape(2,nobs) + cgarch_recursion(parameters, fresids, sigma2, + backcast, var_bounds, g2=g2, q2=q2) return sigma2 From 134a2858490e1e9ae49102d2ec334b992ac9ed1f Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 29 Jul 2017 22:39:09 +0300 Subject: [PATCH 13/92] Change cgarch constraints --- arch/univariate/volatility.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 61cedb181f..7bb4f60ede 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2018,15 +2018,12 @@ def variance_bounds(self, resids, power=2.0): return super().variance_bounds(resids) def constraints(self): - # alpha>0 # beta-phi>0 - # phi-alpha-beta>0 - # alpha-beta<1 written as 1-alpha-beta >0 + # rho-alpha-beta>0 + # rho<1 - a = np.array([1,0,0,0,0]) - other_cons = np.array([[0,1,0,0,-1],[-1,-1,0,1,0],[-1,-1,0,0,0]]) - a = np.vstack((a,other_cons)) - b = np.array([0,0,0,-1]) + a = np.array([[0,1,0,0,-1],[-1,-1,0,1,0],[0,0,0,-1,0]]) + b = np.array([0,0,-1]) return a, b def backcast(self, resids): From 0df9e5743594a0f39dd52367267ecd95a0eb3232 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 31 Jul 2017 18:03:47 +0300 Subject: [PATCH 14/92] Add local files to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6d88fd956d..0336660eee 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ README.rst /.vs/arch/v14/.suo *.pyproj *.sln +/totestimports.py +/.vs/config/applicationhost.config From 0ec4f80f2156ec927b472b34ac2b7588df8a72d5 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 31 Jul 2017 18:13:55 +0300 Subject: [PATCH 15/92] Change starting values --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 7bb4f60ede..52a6714e8d 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2033,7 +2033,7 @@ def bounds(self, resids): return [(0,1), (0,1), (-1, 1), (-1, 1), (0, 1)] def starting_values(self, resids): - return np.array([np.var(resids)/5, 0.1, 0.002, 0.3, 0.5]) + return np.array([0.1, 0.4, np.var(resids)/2, 0.8, 0.2]) def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): From 120d2593359a4a3e58a4386db88c32a951568fe9 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 31 Jul 2017 19:49:30 +0300 Subject: [PATCH 16/92] Change parameter bounds --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 52a6714e8d..f4b1dbfd2d 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2030,7 +2030,7 @@ def backcast(self, resids): return super().backcast(resids) def bounds(self, resids): - return [(0,1), (0,1), (-1, 1), (-1, 1), (0, 1)] + return [(0,1), (0,1), (-1, 1), (0, 1), (0, 1)] def starting_values(self, resids): return np.array([0.1, 0.4, np.var(resids)/2, 0.8, 0.2]) From 529d2a040d99ca5e36e718e2a866878902bac4c5 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Mon, 31 Jul 2017 21:28:40 +0300 Subject: [PATCH 17/92] Correct recursion problem --- arch/univariate/recursions_python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index c030046640..ffcabae8ce 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -257,7 +257,7 @@ def cgarch_recursion_python(parameters, fresids, sigma2, sigma2[0] = initial_sigma2 for t in range(1,nobs): - g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * g2[t-1] + g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * (sigma2[t-1]-q2[t-1]) q2[t] = omega + raw * q2[t-1] + phi * (sqrd_resids[t-1] - sigma2[t-1]) sigma2[t] = g2[t] + q2[t] if sigma2[t] Date: Mon, 31 Jul 2017 21:32:21 +0300 Subject: [PATCH 18/92] Correct recursion --- arch/univariate/recursions_python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index ffcabae8ce..c030046640 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -257,7 +257,7 @@ def cgarch_recursion_python(parameters, fresids, sigma2, sigma2[0] = initial_sigma2 for t in range(1,nobs): - g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * (sigma2[t-1]-q2[t-1]) + g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * g2[t-1] q2[t] = omega + raw * q2[t-1] + phi * (sqrd_resids[t-1] - sigma2[t-1]) sigma2[t] = g2[t] + q2[t] if sigma2[t] Date: Tue, 1 Aug 2017 08:37:17 +0300 Subject: [PATCH 19/92] Add cgarch recursion test --- arch/univariate/tests/test_recursions.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index 31e75123fd..eba84b432e 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -338,6 +338,24 @@ def test_egarch(self): lnsigma2[t] += parameters[3] * lnsigma2[t - 1] sigma2[t] = np.exp(lnsigma2[t]) assert_almost_equal(sigma2_python, sigma2) + + def test_cgarch(self): + T, resids, = self.T, self.resids + sigma2, backcast = self.sigma2, self.backcast + + parameters = np.array([0.1,0.4,0.75, 0.8,0.2]) + fresids = resids ** 2.0 + sresids = np.sign(resids) + q2 = np.ndarray(T) + g2 = np.ndarray(T) + recpy.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) + sigma2_numba = sigma2.copy() + recpy.cgarch_recursion_python(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) + sigma2_python = sigma2.copy() + rec.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) + + assert_almost_equal(sigma2_numba, sigma2) + assert_almost_equal(sigma2_python, sigma2) @pytest.mark.skipif(missing_numba or missing_extension, reason='numba not installed') def test_garch_performance(self): From 5b301743837206edb837f98c65dfdfcc7266869c Mon Sep 17 00:00:00 2001 From: Richard MM Date: Tue, 1 Aug 2017 08:46:37 +0300 Subject: [PATCH 20/92] Files change --- arch.pyproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch.pyproj b/arch.pyproj index 622c75bc98..f8a6f68a59 100644 --- a/arch.pyproj +++ b/arch.pyproj @@ -5,7 +5,7 @@ 2.0 {7b371827-037d-47aa-b84e-1363caa159ad} - totestimports.py + arch\univariate\tests\test_recursions.py . . From f1d40ae0138c2b9a58fa3f48ee43bec95c38ffd6 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Tue, 1 Aug 2017 09:04:32 +0300 Subject: [PATCH 21/92] Add pylint suggestions --- arch/univariate/tests/test_recursions.py | 14 ++++++++------ arch/univariate/volatility.py | 11 +++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index eba84b432e..524b0608f3 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -338,21 +338,23 @@ def test_egarch(self): lnsigma2[t] += parameters[3] * lnsigma2[t - 1] sigma2[t] = np.exp(lnsigma2[t]) assert_almost_equal(sigma2_python, sigma2) - + def test_cgarch(self): T, resids, = self.T, self.resids sigma2, backcast = self.sigma2, self.backcast - parameters = np.array([0.1,0.4,0.75, 0.8,0.2]) + parameters = np.array([0.1, 0.4, 0.75, 0.8, 0.2]) fresids = resids ** 2.0 - sresids = np.sign(resids) q2 = np.ndarray(T) g2 = np.ndarray(T) - recpy.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) + recpy.cgarch_recursion(parameters, fresids, sigma2, backcast, + self.var_bounds, g2, q2) sigma2_numba = sigma2.copy() - recpy.cgarch_recursion_python(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) + recpy.cgarch_recursion_python(parameters, fresids, sigma2, + backcast, self.var_bounds, g2, q2) sigma2_python = sigma2.copy() - rec.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) + rec.cgarch_recursion(parameters, fresids, sigma2, backcast, + self.var_bounds, g2, q2) assert_almost_equal(sigma2_numba, sigma2) assert_almost_equal(sigma2_python, sigma2) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index f4b1dbfd2d..f9111239fe 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2022,27 +2022,26 @@ def constraints(self): # rho-alpha-beta>0 # rho<1 - a = np.array([[0,1,0,0,-1],[-1,-1,0,1,0],[0,0,0,-1,0]]) - b = np.array([0,0,-1]) + a = np.array([[0, 1, 0, 0, -1],[-1, -1, 0, 1, 0],[0, 0, 0, -1, 0]]) + b = np.array([0, 0, -1]) return a, b def backcast(self, resids): return super().backcast(resids) def bounds(self, resids): - return [(0,1), (0,1), (-1, 1), (0, 1), (0, 1)] + return [(0, 1), (0, 1), (-1, 1), (0, 1), (0, 1)] def starting_values(self, resids): return np.array([0.1, 0.4, np.var(resids)/2, 0.8, 0.2]) - + def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): fresids = resids**2 nobs = len(fresids) - g2, q2 = np.ndarray(nobs*2).reshape(2,nobs) + g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) cgarch_recursion(parameters, fresids, sigma2, backcast, var_bounds, g2=g2, q2=q2) - return sigma2 def parameter_names(self): From 9727ec13a528813795649154009fd07d115e6011 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Tue, 1 Aug 2017 22:57:32 +0300 Subject: [PATCH 22/92] Add cgarch class tests to tests file Also correct error in cgarch simulation and add str method in volatility file --- arch/univariate/tests/test_volatility.py | 70 +++++++++++++++++++++++- arch/univariate/volatility.py | 7 ++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index a1b9a4c89f..1f8958a874 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -11,7 +11,7 @@ except: from arch.univariate import recursions_python as rec from arch.univariate.volatility import GARCH, ARCH, HARCH, ConstantVariance, \ - EWMAVariance, RiskMetrics2006, EGARCH, FixedVariance + EWMAVariance, RiskMetrics2006, EGARCH, FixedVariance, CGARCH from arch.univariate.distribution import Normal, StudentsT, SkewStudent from arch.compat.python import range @@ -92,6 +92,74 @@ def test_garch(self): assert_equal(garch.o, 0) assert_equal(garch.q, 1) + def test_cgarch(self): + cgarch = CGARCH() + sv = cgarch.starting_values(self.resids) + assert_equal(sv.shape[0], cgarch.num_params) + + bounds = cgarch.bounds(self.resids) + assert_equal(bounds[0], (0, 1)) + assert_equal(bounds[1], (-1, 1)) + assert_equal(bounds[2], (0, 1)) + backcast = cgarch.backcast(self.resids) + w = 0.94 ** np.arange(75) + assert_almost_equal(backcast, + np.sum((self.resids[:75] ** 2) * (w / w.sum()))) + var_bounds = cgarch.variance_bounds(self.resids) + parameters = np.array([0.1, 0.4, 0.75, 0.8, 0.2]) + cgarch.compute_variance(parameters, self.resids, self.sigma2, + backcast, var_bounds) + cond_var_direct = np.zeros_like(self.sigma2) + g2 = np.ndarray(self.T) + q2 = g2.copy() + rec.cgarch_recursion(parameters, + self.resids ** 2.0, + cond_var_direct, + backcast, var_bounds, g2, q2) + assert_allclose(self.sigma2, cond_var_direct) + + a, b = cgarch.constraints() + a_target = np.array([[0, 1, 0, 0, -1],[-1, -1, 0, 1, 0],[0, 0, 0, -1, 0]]) + b_target = np.array([0, 0, -1]) + assert_array_equal(a, a_target) + assert_array_equal(b, b_target) + state = np.random.get_state() + rng = Normal() + sim_data = cgarch.simulate(parameters, self.T, rng.simulate([])) + np.random.set_state(state) + e = np.random.standard_normal(self.T + 500) + converted_params = cgarch._covertparams(parameters) + initial_value = converted_params[0]/(1-(np.sum(converted_params[1:]))) + sigma2 = np.zeros(self.T + 500) + sigma2[0] = initial_value + g2 = np.ndarray(self.T + 500) + q2 = q2.copy() + g2[0] = initial_value - q2[0] + data = np.zeros(self.T + 500) + data[0] = e[0] * np.sqrt(sigma2[0]) + alpha, beta, omega, rho, phi = parameters + for i in range(1, self.T + 500): + g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] + q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) + sigma2[i] = g2[i] + q2[i] + data[i] = errors[i] * (np.sqrt(sigma2[i])) ** 2 + + 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 = cgarch.parameter_names() + names_target = ["alpha", "beta", "omega", "rho", "phi"] + assert_equal(names, names_target) + + assert isinstance(cgarch.__str__(), str) + + assert_equal(cgarch.name, 'ComponentGARCH') + assert_equal(cgarch.num_params, 5) + assert_equal(cgarch.p, 2) + assert_equal(cgarch.q, 2) + def test_garch_power(self): garch = GARCH(power=1.0) assert_equal(garch.num_params, 3) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index f9111239fe..e38e5beb91 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2012,7 +2012,10 @@ def __init__(self): self.p = 2 self.q = 2 self.num_params = 5 - self.name = "ComponentGarch" + self.name = "ComponentGARCH" + + def __str__(self): + return self.name def variance_bounds(self, resids, power=2.0): return super().variance_bounds(resids) @@ -2077,7 +2080,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): sigma2[0] = initial_value q2[0] = initial_value * 0.65 - g2[0] = initial_value - g2[0] + g2[0] = initial_value - q2[0] data[0] = sqrt(sigma2[0]) * errors[0] for i in range(1, T): From 8b24df00603b973c9f14fd169ff25afbada596f9 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Tue, 1 Aug 2017 23:05:18 +0300 Subject: [PATCH 23/92] Change recursion used --- arch.pyproj | 2 +- arch/univariate/tests/test_volatility.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch.pyproj b/arch.pyproj index f8a6f68a59..0b91c6e6a8 100644 --- a/arch.pyproj +++ b/arch.pyproj @@ -5,7 +5,7 @@ 2.0 {7b371827-037d-47aa-b84e-1363caa159ad} - arch\univariate\tests\test_recursions.py + arch\univariate\tests\test_volatility.py . . diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 1f8958a874..9d814f38c2 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -112,7 +112,8 @@ def test_cgarch(self): cond_var_direct = np.zeros_like(self.sigma2) g2 = np.ndarray(self.T) q2 = g2.copy() - rec.cgarch_recursion(parameters, + from arch.univariate import recursions_python as recpy + recpy.cgarch_recursion(parameters, self.resids ** 2.0, cond_var_direct, backcast, var_bounds, g2, q2) From 18a572c053e075e4e8c2605be4909331294ff207 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 12:45:01 +0300 Subject: [PATCH 24/92] Remove test for cython cgarch recursion --- arch/univariate/tests/test_recursions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index 524b0608f3..6f07d69317 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -353,6 +353,7 @@ def test_cgarch(self): recpy.cgarch_recursion_python(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) sigma2_python = sigma2.copy() + rec = recpy # change this after implementing cythonised recursion rec.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) From 7232806e1b1c8ac09de791b9b24131fdac4d380c Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 12:58:10 +0300 Subject: [PATCH 25/92] Modify super to work in python 2 --- arch/univariate/volatility.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index e38e5beb91..8428b3f19a 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2008,7 +2008,7 @@ class CGARCH(GARCH): """ def __init__(self): - super().__init__() + super(CGARCH, self).__init__() self.p = 2 self.q = 2 self.num_params = 5 @@ -2018,7 +2018,7 @@ def __str__(self): return self.name def variance_bounds(self, resids, power=2.0): - return super().variance_bounds(resids) + return super(CGARCH, self).variance_bounds(resids) def constraints(self): # beta-phi>0 From d318b7b218ca21e86419fa34fe6b71c3902b8e23 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 13:03:27 +0300 Subject: [PATCH 26/92] Correct failed tests --- arch/univariate/tests/test_volatility.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 9d814f38c2..3c6c516fc3 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -99,8 +99,10 @@ def test_cgarch(self): bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) - assert_equal(bounds[1], (-1, 1)) - assert_equal(bounds[2], (0, 1)) + assert_equal(bounds[1], (0, 1)) + assert_equal(bounds[2], (-1, 1)) + assert_equal(bounds[3], (0, 1)) + assert_equal(bounds[4], (0, 1)) backcast = cgarch.backcast(self.resids) w = 0.94 ** np.arange(75) assert_almost_equal(backcast, From d15ea6977d2875205497274eba00fc363b8c27f9 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 13:27:18 +0300 Subject: [PATCH 27/92] Change super to support python 2 --- arch/univariate/volatility.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 8428b3f19a..9b468f8df6 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2030,7 +2030,7 @@ def constraints(self): return a, b def backcast(self, resids): - return super().backcast(resids) + return super(CGARCH, self).backcast(resids) def bounds(self, resids): return [(0, 1), (0, 1), (-1, 1), (0, 1), (0, 1)] @@ -2144,7 +2144,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho def _simulate_paths(self, m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock): parameters = self._covertparams(parameters) - return super()._simulate_paths(m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock) + return super(CGARCH, self)._simulate_paths(m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock) def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, horizon, simulations, rng): sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, From f40ff77d23bb86c00a79700301e492288fc3fa74 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 13:42:02 +0300 Subject: [PATCH 28/92] correct undefined name --- arch/univariate/tests/test_volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 3c6c516fc3..fba567c359 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -145,7 +145,7 @@ def test_cgarch(self): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) sigma2[i] = g2[i] + q2[i] - data[i] = errors[i] * (np.sqrt(sigma2[i])) ** 2 + data[i] = e[i] * (np.sqrt(sigma2[i])) ** 2 data = data[500:] sigma2 = sigma2[500:] From d92cb72918cb7d46405f209f0e3970eb587065f1 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 17:09:05 +0300 Subject: [PATCH 29/92] Corrrect bug in simulate method in cgarch --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 9b468f8df6..bf72630a88 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2082,7 +2082,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): q2[0] = initial_value * 0.65 g2[0] = initial_value - q2[0] data[0] = sqrt(sigma2[0]) * errors[0] - + alpha, beta, omega, rho, phi = parameters for i in range(1, T): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) From 81053370c7ab8b6f8cfafb3f17990a1302348bb2 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 17:18:17 +0300 Subject: [PATCH 30/92] Add pylint suggestions --- arch/univariate/tests/test_volatility.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index fba567c359..34018428d7 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -109,20 +109,21 @@ def test_cgarch(self): np.sum((self.resids[:75] ** 2) * (w / w.sum()))) var_bounds = cgarch.variance_bounds(self.resids) parameters = np.array([0.1, 0.4, 0.75, 0.8, 0.2]) - cgarch.compute_variance(parameters, self.resids, self.sigma2, - backcast, var_bounds) + cgarch.compute_variance(parameters, self.resids, self.sigma2, \ + backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) g2 = np.ndarray(self.T) q2 = g2.copy() from arch.univariate import recursions_python as recpy - recpy.cgarch_recursion(parameters, - self.resids ** 2.0, - cond_var_direct, - backcast, var_bounds, g2, q2) + recpy.cgarch_recursion(parameters, + self.resids ** 2.0, + cond_var_direct, + backcast, + var_bounds, g2, q2) assert_allclose(self.sigma2, cond_var_direct) a, b = cgarch.constraints() - a_target = np.array([[0, 1, 0, 0, -1],[-1, -1, 0, 1, 0],[0, 0, 0, -1, 0]]) + a_target = np.array([[0, 1, 0, 0, -1], [-1, -1, 0, 1, 0], [0, 0, 0, -1, 0]]) b_target = np.array([0, 0, -1]) assert_array_equal(a, a_target) assert_array_equal(b, b_target) @@ -146,7 +147,7 @@ def test_cgarch(self): q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) sigma2[i] = g2[i] + q2[i] data[i] = e[i] * (np.sqrt(sigma2[i])) ** 2 - + data = data[500:] sigma2 = sigma2[500:] assert_almost_equal(data / sim_data[0], np.ones_like(data)) @@ -162,7 +163,7 @@ def test_cgarch(self): assert_equal(cgarch.num_params, 5) assert_equal(cgarch.p, 2) assert_equal(cgarch.q, 2) - + def test_garch_power(self): garch = GARCH(power=1.0) assert_equal(garch.num_params, 3) From cfef02387fc40377c4be114e7e0cde284846f989 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 17:31:21 +0300 Subject: [PATCH 31/92] Fix index error bug --- arch/univariate/tests/test_volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 34018428d7..ca96870b4a 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -137,7 +137,7 @@ def test_cgarch(self): sigma2 = np.zeros(self.T + 500) sigma2[0] = initial_value g2 = np.ndarray(self.T + 500) - q2 = q2.copy() + q2 = g2.copy() g2[0] = initial_value - q2[0] data = np.zeros(self.T + 500) data[0] = e[0] * np.sqrt(sigma2[0]) From b7b4c995943dad542f253de2f91dae95e97b43ab Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 18:17:43 +0300 Subject: [PATCH 32/92] Fix simulation bug --- arch/univariate/tests/test_volatility.py | 11 +++++++++-- arch/univariate/volatility.py | 7 ++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index ca96870b4a..f435da130e 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -127,21 +127,28 @@ def test_cgarch(self): b_target = np.array([0, 0, -1]) assert_array_equal(a, a_target) assert_array_equal(b, b_target) + #test simulated data state = np.random.get_state() rng = Normal() sim_data = cgarch.simulate(parameters, self.T, rng.simulate([])) np.random.set_state(state) e = np.random.standard_normal(self.T + 500) + alpha, beta, omega, rho, phi = parameters converted_params = cgarch._covertparams(parameters) - initial_value = converted_params[0]/(1-(np.sum(converted_params[1:]))) + fromgarch = converted_params[0]/(1-(np.sum(converted_params[1:]))) + if fromgarch > 0: + initial_value = fromgarch + else: + initial_value = omega/(1-rho) sigma2 = np.zeros(self.T + 500) sigma2[0] = initial_value g2 = np.ndarray(self.T + 500) q2 = g2.copy() + q2[0] = initial_value * 0.65 g2[0] = initial_value - q2[0] data = np.zeros(self.T + 500) data[0] = e[0] * np.sqrt(sigma2[0]) - alpha, beta, omega, rho, phi = parameters + for i in range(1, self.T + 500): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index bf72630a88..c362ccb299 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2071,18 +2071,19 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): g2 = zeros(T) # long_ term q2 = zeros(T) - + alpha, beta, omega, rho, phi = parameters if initial_value is None: # Cgarch can be represented as a restricted garch(2,2) with: a0, a1, a2, b1, b2 = self._covertparams(parameters) # the unconditional var of this garch(2,2) form is used as initial value - initial_value = a0/(1-(a1+a2+b1+b2)) + fromgarch = a0/(1-(a1+a2+b1+b2)) + initial_value = fromgarch if fromgarch > 0 else omega/(1-rho) sigma2[0] = initial_value q2[0] = initial_value * 0.65 g2[0] = initial_value - q2[0] data[0] = sqrt(sigma2[0]) * errors[0] - alpha, beta, omega, rho, phi = parameters + for i in range(1, T): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) From 453f712905ae835952798730b7778574f6c8c81e Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 18:45:12 +0300 Subject: [PATCH 33/92] Fix simulation bug --- arch/univariate/tests/test_volatility.py | 9 ++++++--- arch/univariate/volatility.py | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index f435da130e..b4ef80feca 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -108,7 +108,7 @@ def test_cgarch(self): assert_almost_equal(backcast, np.sum((self.resids[:75] ** 2) * (w / w.sum()))) var_bounds = cgarch.variance_bounds(self.resids) - parameters = np.array([0.1, 0.4, 0.75, 0.8, 0.2]) + cgarch.compute_variance(parameters, self.resids, self.sigma2, \ backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) @@ -136,9 +136,12 @@ def test_cgarch(self): alpha, beta, omega, rho, phi = parameters converted_params = cgarch._covertparams(parameters) fromgarch = converted_params[0]/(1-(np.sum(converted_params[1:]))) - if fromgarch > 0: - initial_value = fromgarch + fromcg = omega/(1-rho) + aver = (fromcg + fromgarch)/2 + if aver > 0: + initial_value = aver else: + initial_value = 0.5 initial_value = omega/(1-rho) sigma2 = np.zeros(self.T + 500) sigma2[0] = initial_value diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index c362ccb299..83ce1865b9 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2077,7 +2077,9 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): a0, a1, a2, b1, b2 = self._covertparams(parameters) # the unconditional var of this garch(2,2) form is used as initial value fromgarch = a0/(1-(a1+a2+b1+b2)) - initial_value = fromgarch if fromgarch > 0 else omega/(1-rho) + fromcg = omega/(1-rho) + aver = (fromcg + fromgarch)/2 + initial_value = aver if aver > 0 else 0.5 sigma2[0] = initial_value q2[0] = initial_value * 0.65 From 5e5f7c5795df79853768a039ff0e2c649edbb834 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 19:57:08 +0300 Subject: [PATCH 34/92] Fix simulation bug --- arch/univariate/tests/test_volatility.py | 6 +++--- arch/univariate/volatility.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index b4ef80feca..7283d92ea5 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -96,7 +96,7 @@ def test_cgarch(self): cgarch = CGARCH() sv = cgarch.starting_values(self.resids) assert_equal(sv.shape[0], cgarch.num_params) - + parameters = np.array([0.1, 0.4, 0.75, 0.8, 0.2]) bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) assert_equal(bounds[1], (0, 1)) @@ -138,10 +138,10 @@ def test_cgarch(self): fromgarch = converted_params[0]/(1-(np.sum(converted_params[1:]))) fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 - if aver > 0: + if aver > 0 & aver < 0.2: initial_value = aver else: - initial_value = 0.5 + initial_value = 0.1 initial_value = omega/(1-rho) sigma2 = np.zeros(self.T + 500) sigma2[0] = initial_value diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 83ce1865b9..1d9a644d20 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2079,7 +2079,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): fromgarch = a0/(1-(a1+a2+b1+b2)) fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 - initial_value = aver if aver > 0 else 0.5 + initial_value = aver if aver > 0 & aver < 0.2 else 0.1 sigma2[0] = initial_value q2[0] = initial_value * 0.65 From cc158dfff5cd5a18e48342ff66250b189069742f Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 20:21:40 +0300 Subject: [PATCH 35/92] Fix cgarch simulation bug --- arch/univariate/tests/test_volatility.py | 2 +- arch/univariate/volatility.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 7283d92ea5..4dad6ea572 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -138,7 +138,7 @@ def test_cgarch(self): fromgarch = converted_params[0]/(1-(np.sum(converted_params[1:]))) fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 - if aver > 0 & aver < 0.2: + if aver > 0.0 & aver < 0.2: initial_value = aver else: initial_value = 0.1 diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 1d9a644d20..b4740823a4 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2079,7 +2079,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): fromgarch = a0/(1-(a1+a2+b1+b2)) fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 - initial_value = aver if aver > 0 & aver < 0.2 else 0.1 + initial_value = aver if aver > 0.0 & aver < 0.2 else 0.1 sigma2[0] = initial_value q2[0] = initial_value * 0.65 From 3cae18b06c688a538595cbb296b09264bb798944 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 20:36:41 +0300 Subject: [PATCH 36/92] Fix simulation bug --- arch/univariate/tests/test_volatility.py | 2 +- arch/univariate/volatility.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 4dad6ea572..5a933c913c 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -138,7 +138,7 @@ def test_cgarch(self): fromgarch = converted_params[0]/(1-(np.sum(converted_params[1:]))) fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 - if aver > 0.0 & aver < 0.2: + if (aver > 0.0) and (aver < 0.2): initial_value = aver else: initial_value = 0.1 diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index b4740823a4..0b97b44879 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2079,7 +2079,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): fromgarch = a0/(1-(a1+a2+b1+b2)) fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 - initial_value = aver if aver > 0.0 & aver < 0.2 else 0.1 + initial_value = aver if (aver > 0.0) and (aver < 0.2) else 0.1 sigma2[0] = initial_value q2[0] = initial_value * 0.65 From 137ae8b6f64173fec60aae498e9608ab5469812c Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 20:58:45 +0300 Subject: [PATCH 37/92] Fix simulation bug --- arch/univariate/tests/test_volatility.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 5a933c913c..af6d16705b 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -96,7 +96,7 @@ def test_cgarch(self): cgarch = CGARCH() sv = cgarch.starting_values(self.resids) assert_equal(sv.shape[0], cgarch.num_params) - parameters = np.array([0.1, 0.4, 0.75, 0.8, 0.2]) + parameters = np.array([0.1, 0.4, 0.06, 0.8, 0.2]) bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) assert_equal(bounds[1], (0, 1)) @@ -142,7 +142,6 @@ def test_cgarch(self): initial_value = aver else: initial_value = 0.1 - initial_value = omega/(1-rho) sigma2 = np.zeros(self.T + 500) sigma2[0] = initial_value g2 = np.ndarray(self.T + 500) From e5cc6061933b402af01df4a114aa35c247481d45 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 21:47:41 +0300 Subject: [PATCH 38/92] Add travis flake8 suggestions --- arch/univariate/__init__.py | 4 ++-- arch/univariate/recursions_python.py | 26 ++++++++++++++------------ arch/univariate/volatility.py | 14 ++++++++------ 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/arch/univariate/__init__.py b/arch/univariate/__init__.py index 0eae4f6aeb..3991cfa934 100644 --- a/arch/univariate/__init__.py +++ b/arch/univariate/__init__.py @@ -5,8 +5,8 @@ RiskMetrics2006, EGARCH, FixedVariance) from arch.univariate.distribution import Distribution, Normal, StudentsT, SkewStudent -__all__ = ['HARX', 'ConstantMean', 'ZeroMean', 'ARX', 'arch_model', 'LS', - 'GARCH', 'ARCH', 'HARCH', 'ConstantVariance', 'CGARCH', +__all__ = ['HARX', 'ConstantMean', 'ZeroMean', 'ARX', 'arch_model', 'LS', + 'GARCH', 'ARCH', 'HARCH', 'ConstantVariance', 'CGARCH', 'EWMAVariance', 'RiskMetrics2006', 'EGARCH', 'Distribution', 'Normal', 'StudentsT', 'SkewStudent', 'FixedVariance'] diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index c030046640..45c62b5a6f 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -241,31 +241,33 @@ def egarch_recursion_python(parameters, resids, sigma2, p, o, q, nobs, egarch_recursion = jit(egarch_recursion_python) -def cgarch_recursion_python(parameters, fresids, sigma2, - backcast, var_bounds, g2, q2): + +def cgarch_recursion_python(parameters, fresids, sigma2, + backcast, var_bounds, g2, q2): sqrd_resids = fresids nobs = len(sqrd_resids) alpha, beta, omega, raw, phi = parameters - initial_sigma2 = backcast initial_q2 = 0.05 - initial_g2 = initial_sigma2 - initial_q2 - + initial_g2 = initial_sigma2 - initial_q2 + # g is short term variance and q is the long term one g2[0] = initial_g2 q2[0] = initial_q2 sigma2[0] = initial_sigma2 - - for t in range(1,nobs): + + for t in range(1, nobs): g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * g2[t-1] q2[t] = omega + raw * q2[t-1] + phi * (sqrd_resids[t-1] - sigma2[t-1]) sigma2[t] = g2[t] + q2[t] - if sigma2[t] var_bounds[t, 1]: if not np.isinf(sigma2[t]): sigma2[t] = var_bounds[t, 1] + log(sigma2[t] / var_bounds[t, 1]) else: - sigma2[t] = var_bounds[t, 1] + 1000 - return sigma2 -cgarch_recursion = jit(cgarch_recursion_python) \ No newline at end of file + sigma2[t] = var_bounds[t, 1] + 1000 + return sigma2 + + +cgarch_recursion = jit(cgarch_recursion_python) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 0b97b44879..029f7848b4 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -15,7 +15,8 @@ from arch.utility.array import ensure1d, DocStringInheritor try: - from arch.univariate.recursions import garch_recursion, harch_recursion, egarch_recursion, cgarch_recursion + from arch.univariate.recursions import (garch_recursion, harch_recursion, + egarch_recursion, cgarch_recursion) except ImportError: # pragma: no cover from arch.univariate.recursions_python import (garch_recursion, harch_recursion, egarch_recursion, cgarch_recursion) @@ -1982,6 +1983,7 @@ def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, return VarianceForecast(forecasts, forecast_paths, shocks) + class CGARCH(GARCH): r""" Component GARCH model. A restricted version of GARCH(2,2) by Engle and Lee @@ -1993,8 +1995,8 @@ class CGARCH(GARCH): Attributes ---------- num_params : int - The number of parameters in the model - + The number of parameters in the model + Notes ----- In this class of processes, the variance dynamics are @@ -2016,7 +2018,7 @@ def __init__(self): def __str__(self): return self.name - + def variance_bounds(self, resids, power=2.0): return super(CGARCH, self).variance_bounds(resids) @@ -2028,7 +2030,7 @@ def constraints(self): a = np.array([[0, 1, 0, 0, -1],[-1, -1, 0, 1, 0],[0, 0, 0, -1, 0]]) b = np.array([0, 0, -1]) return a, b - + def backcast(self, resids): return super(CGARCH, self).backcast(resids) @@ -2042,7 +2044,7 @@ def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): fresids = resids**2 nobs = len(fresids) - g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) + g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) cgarch_recursion(parameters, fresids, sigma2, backcast, var_bounds, g2=g2, q2=q2) return sigma2 From 56d6bea89b587f7856dee53808c30f262e841d4f Mon Sep 17 00:00:00 2001 From: Richard MM Date: Wed, 2 Aug 2017 22:05:19 +0300 Subject: [PATCH 39/92] Add pylint guidelines --- arch/univariate/volatility.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 029f7848b4..f6e2c6dddb 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2056,11 +2056,11 @@ def parameter_names(self): def _covertparams(self, parameters): # this will convert the cgarch params into restricted GARCH(2,2) parameters alpha, beta, omega, rho, phi = parameters - a0 = omega*(1-alpha-beta) - a1 = phi +alpha - a2 = phi*(alpha + beta) + alpha*rho + a0 = omega * (1 - alpha - beta) + a1 = phi + alpha + a2 = phi * (alpha + beta) + alpha * rho b1 = rho + beta - phi - b2 = phi*(alpha + beta) - rho*beta + b2 = phi * (alpha + beta) - rho*beta return [a0, a1, a2, b1, b2] def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): @@ -2076,7 +2076,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): alpha, beta, omega, rho, phi = parameters if initial_value is None: # Cgarch can be represented as a restricted garch(2,2) with: - a0, a1, a2, b1, b2 = self._covertparams(parameters) + a0, a1, a2, b1, b2 = self._covertparams(parameters) # the unconditional var of this garch(2,2) form is used as initial value fromgarch = a0/(1-(a1+a2+b1+b2)) fromcg = omega/(1-rho) @@ -2087,7 +2087,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): q2[0] = initial_value * 0.65 g2[0] = initial_value - q2[0] data[0] = sqrt(sigma2[0]) * errors[0] - + for i in range(1, T): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) @@ -2147,14 +2147,20 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho forecasts[:start] = np.nan return VarianceForecast(forecasts) - def _simulate_paths(self, m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock): + def _simulate_paths(self, m, parameters, horizon, std_shocks, + scaled_forecast_paths, scaled_shock, + asym_scaled_shock): parameters = self._covertparams(parameters) - return super(CGARCH, self)._simulate_paths(m, parameters, horizon, std_shocks, scaled_forecast_paths, scaled_shock, asym_scaled_shock) + return super(CGARCH, self)._simulate_paths(m, parameters, + horizon, std_shocks, + scaled_forecast_paths, + scaled_shock, asym_scaled_shock) - def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, horizon, simulations, rng): + def _simulation_forecast(self, parameters, resids, backcast, var_bounds, + start, horizon, simulations, rng): sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, var_bounds, horizon) - #Everything is similar to GARCH class vut parameters have to be converted + # Everything is similar to GARCH class vut parameters have to be converted parameters = self._covertparams(parameters) t = resids.shape[0] paths = np.zeros((t, simulations, horizon)) @@ -2189,4 +2195,4 @@ def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, paths[:start] = np.nan shocks[:start] = np.nan forecasts[:start] = np.nan - return VarianceForecast(forecasts, paths, shocks) \ No newline at end of file + return VarianceForecast(forecasts, paths, shocks) From 6b49db1d053c7e42a670d7ba357aa678e5514ce2 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 07:13:33 +0300 Subject: [PATCH 40/92] Add pylint suggestions --- arch/univariate/recursions_python.py | 1 - arch/univariate/tests/test_recursions.py | 10 +++++----- arch/univariate/tests/test_volatility.py | 5 ++--- arch/univariate/volatility.py | 10 +++++----- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/arch/univariate/recursions_python.py b/arch/univariate/recursions_python.py index 45c62b5a6f..4ad62907d9 100644 --- a/arch/univariate/recursions_python.py +++ b/arch/univariate/recursions_python.py @@ -250,7 +250,6 @@ def cgarch_recursion_python(parameters, fresids, sigma2, initial_sigma2 = backcast initial_q2 = 0.05 initial_g2 = initial_sigma2 - initial_q2 - # g is short term variance and q is the long term one g2[0] = initial_g2 q2[0] = initial_q2 diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index 6f07d69317..4f92c0a9e1 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -347,15 +347,15 @@ def test_cgarch(self): fresids = resids ** 2.0 q2 = np.ndarray(T) g2 = np.ndarray(T) - recpy.cgarch_recursion(parameters, fresids, sigma2, backcast, + recpy.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) sigma2_numba = sigma2.copy() - recpy.cgarch_recursion_python(parameters, fresids, sigma2, - backcast, self.var_bounds, g2, q2) + recpy.cgarch_recursion_python(parameters, fresids, sigma2, + backcast, self.var_bounds, g2, q2) sigma2_python = sigma2.copy() rec = recpy # change this after implementing cythonised recursion - rec.cgarch_recursion(parameters, fresids, sigma2, backcast, - self.var_bounds, g2, q2) + rec.cgarch_recursion(parameters, fresids, sigma2, backcast, + self.var_bounds, g2, q2) assert_almost_equal(sigma2_numba, sigma2) assert_almost_equal(sigma2_python, sigma2) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index af6d16705b..f121a9c3b7 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -108,17 +108,16 @@ def test_cgarch(self): assert_almost_equal(backcast, np.sum((self.resids[:75] ** 2) * (w / w.sum()))) var_bounds = cgarch.variance_bounds(self.resids) - cgarch.compute_variance(parameters, self.resids, self.sigma2, \ backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) g2 = np.ndarray(self.T) q2 = g2.copy() from arch.univariate import recursions_python as recpy - recpy.cgarch_recursion(parameters, + recpy.cgarch_recursion(parameters, self.resids ** 2.0, cond_var_direct, - backcast, + backcast, var_bounds, g2, q2) assert_allclose(self.sigma2, cond_var_direct) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index f6e2c6dddb..739801b891 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -721,7 +721,7 @@ def variance_bounds(self, resids, power=2.0): return super(GARCH, self).variance_bounds(resids, self.power) def _name(self): - p, o, q, power = self.p, self.o, self.q, self.power # noqa: F841 + o, q, power = self.o, self.q, self.power # noqa: F841 if power == 2.0: if o == 0 and q == 0: return 'ARCH' @@ -1836,7 +1836,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, horizon, simulations, rng): - sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, var_bounds, + sigma2, _ = self._one_step_forecast(parameters, resids, backcast, var_bounds, horizon) t = resids.shape[0] p, o, q = self.p, self.o, self.q @@ -2021,7 +2021,7 @@ def __str__(self): def variance_bounds(self, resids, power=2.0): return super(CGARCH, self).variance_bounds(resids) - + def constraints(self): # beta-phi>0 # rho-alpha-beta>0 @@ -2045,8 +2045,8 @@ def compute_variance(self, parameters, resids, sigma2, backcast, fresids = resids**2 nobs = len(fresids) g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) - cgarch_recursion(parameters, fresids, sigma2, - backcast, var_bounds, g2=g2, q2=q2) + cgarch_recursion(parameters, fresids, sigma2, + backcast, var_bounds, g2=g2, q2=q2) return sigma2 def parameter_names(self): From 04f916bc719192ff3aa76ccf69363580cec807c3 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 07:28:02 +0300 Subject: [PATCH 41/92] Add pylint suggestions --- arch/univariate/tests/test_recursions.py | 2 +- arch/univariate/tests/test_volatility.py | 8 ++++---- arch/univariate/volatility.py | 9 ++++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index 4f92c0a9e1..44ef0e0690 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -353,7 +353,7 @@ def test_cgarch(self): recpy.cgarch_recursion_python(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) sigma2_python = sigma2.copy() - rec = recpy # change this after implementing cythonised recursion + rec = recpy # change this after implementing cythonised recursion rec.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index f121a9c3b7..9e42913a83 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -108,7 +108,7 @@ def test_cgarch(self): assert_almost_equal(backcast, np.sum((self.resids[:75] ** 2) * (w / w.sum()))) var_bounds = cgarch.variance_bounds(self.resids) - cgarch.compute_variance(parameters, self.resids, self.sigma2, \ + cgarch.compute_variance(parameters, self.resids, self.sigma2, backcast, var_bounds) cond_var_direct = np.zeros_like(self.sigma2) g2 = np.ndarray(self.T) @@ -126,7 +126,7 @@ def test_cgarch(self): b_target = np.array([0, 0, -1]) assert_array_equal(a, a_target) assert_array_equal(b, b_target) - #test simulated data + # test simulated data state = np.random.get_state() rng = Normal() sim_data = cgarch.simulate(parameters, self.T, rng.simulate([])) @@ -135,7 +135,7 @@ def test_cgarch(self): alpha, beta, omega, rho, phi = parameters converted_params = cgarch._covertparams(parameters) fromgarch = converted_params[0]/(1-(np.sum(converted_params[1:]))) - fromcg = omega/(1-rho) + fromcg = omega/(1-rho) aver = (fromcg + fromgarch)/2 if (aver > 0.0) and (aver < 0.2): initial_value = aver @@ -149,7 +149,7 @@ def test_cgarch(self): g2[0] = initial_value - q2[0] data = np.zeros(self.T + 500) data[0] = e[0] * np.sqrt(sigma2[0]) - + for i in range(1, self.T + 500): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 739801b891..2d3f0e9d44 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -1837,7 +1837,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, horizon, simulations, rng): sigma2, _ = self._one_step_forecast(parameters, resids, backcast, var_bounds, - horizon) + horizon) t = resids.shape[0] p, o, q = self.p, self.o, self.q m = np.max([p, o, q]) @@ -2026,17 +2026,16 @@ def constraints(self): # beta-phi>0 # rho-alpha-beta>0 # rho<1 - - a = np.array([[0, 1, 0, 0, -1],[-1, -1, 0, 1, 0],[0, 0, 0, -1, 0]]) + a = np.array([[0, 1, 0, 0, -1], [-1, -1, 0, 1, 0], [0, 0, 0, -1, 0]]) b = np.array([0, 0, -1]) return a, b def backcast(self, resids): return super(CGARCH, self).backcast(resids) - + def bounds(self, resids): return [(0, 1), (0, 1), (-1, 1), (0, 1), (0, 1)] - + def starting_values(self, resids): return np.array([0.1, 0.4, np.var(resids)/2, 0.8, 0.2]) From 659d8c1bc0a2c578ceb23c8d2295940d9b202539 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 07:37:05 +0300 Subject: [PATCH 42/92] Add pylint suggestions --- arch.pyproj | 2 +- arch/univariate/tests/test_volatility.py | 2 +- arch/univariate/volatility.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch.pyproj b/arch.pyproj index 0b91c6e6a8..622c75bc98 100644 --- a/arch.pyproj +++ b/arch.pyproj @@ -5,7 +5,7 @@ 2.0 {7b371827-037d-47aa-b84e-1363caa159ad} - arch\univariate\tests\test_volatility.py + totestimports.py . . diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 9e42913a83..f0ae66612f 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -149,7 +149,7 @@ def test_cgarch(self): g2[0] = initial_value - q2[0] data = np.zeros(self.T + 500) data[0] = e[0] * np.sqrt(sigma2[0]) - + for i in range(1, self.T + 500): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 2d3f0e9d44..b3e0fddc5c 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2035,7 +2035,7 @@ def backcast(self, resids): def bounds(self, resids): return [(0, 1), (0, 1), (-1, 1), (0, 1), (0, 1)] - + def starting_values(self, resids): return np.array([0.1, 0.4, np.var(resids)/2, 0.8, 0.2]) From 2a8f58d15960cdb7278483bbbf1052f1c4d4bc04 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 10:15:13 +0300 Subject: [PATCH 43/92] Add cython cgarch recursion --- .gitignore | 1 + arch.pyproj | 3 +++ arch/univariate/recursions.pyx | 42 +++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4b50067e8e..e8c60c10a5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ README.rst *.user /.vs/config/applicationhost.config /examples/.ipynb_checkpoints/univariate_volatility_modeling-checkpoint.ipynb +/local_cythonrecursion.py diff --git a/arch.pyproj b/arch.pyproj index 622c75bc98..43cf44bc6c 100644 --- a/arch.pyproj +++ b/arch.pyproj @@ -87,6 +87,9 @@ + + Code + Code diff --git a/arch/univariate/recursions.pyx b/arch/univariate/recursions.pyx index af0d3e6146..55fd9eaf25 100644 --- a/arch/univariate/recursions.pyx +++ b/arch/univariate/recursions.pyx @@ -3,7 +3,7 @@ cimport numpy as np cimport cython __all__ = ['harch_recursion','arch_recursion','garch_recursion', - 'egarch_recursion'] + 'egarch_recursion', 'cgarch_recursion'] cdef extern from 'math.h': double log(double x) @@ -277,3 +277,43 @@ def egarch_recursion(double[:] parameters, abs_std_resids[t] = fabs(std_resids[t]) return sigma2 + +@cython.boundscheck(False) +@cython.wraparound(False) +@cython.cdivision(True) +def cgarch_recursion(double[:] parameters, + double[:] fresids, + double[:] sigma2, + double backcast, + double[:, :] var_bounds, + double[:] g2, + double[:] q2): + cdef double[:] sqrd_resids + cdef int nobs + cdef double alpha, beta, omega, raw, phi, initial_sigma2, initial_q2 + cdef double initial_g2 + cdef Py_ssize_t t + + sqrd_resids = fresids + nobs = len(sqrd_resids) + alpha, beta, omega, raw, phi = parameters + initial_sigma2 = backcast + initial_q2 = 0.05 + initial_g2 = initial_sigma2 - initial_q2 + # g is short term variance and q is the long term one + g2[0] = initial_g2 + q2[0] = initial_q2 + sigma2[0] = initial_sigma2 + + for t in range(1, nobs): + g2[t] = alpha * (sqrd_resids[t-1] - q2[t-1]) + beta * g2[t-1] + q2[t] = omega + raw * q2[t-1] + phi * (sqrd_resids[t-1] - sigma2[t-1]) + sigma2[t] = g2[t] + q2[t] + if sigma2[t] < var_bounds[t, 0]: + sigma2[t] = var_bounds[t, 0] + elif sigma2[t] > var_bounds[t, 1]: + if sigma2[t] > DBL_MAX: + sigma2[t] = var_bounds[t, 1] + 1000 + else: + sigma2[t] = var_bounds[t, 1] + log(sigma2[t] / var_bounds[t, 1]) + return sigma2 From e03dffaf8e61c43577226b6148e4a0f6a62c62be Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 10:20:04 +0300 Subject: [PATCH 44/92] Add test for cython cgarch recursion --- arch/univariate/tests/test_recursions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index 44ef0e0690..f4f2cbd850 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -353,7 +353,7 @@ def test_cgarch(self): recpy.cgarch_recursion_python(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) sigma2_python = sigma2.copy() - rec = recpy # change this after implementing cythonised recursion + # rec = recpy # change this after implementing cythonised recursion rec.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) From 0028d7e9117dac1f7246fb990bc24ca0b89643cd Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 10:35:46 +0300 Subject: [PATCH 45/92] Add cython recursion test for cgarch --- arch/univariate/tests/test_volatility.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index f0ae66612f..228d29a7ee 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -113,8 +113,7 @@ def test_cgarch(self): cond_var_direct = np.zeros_like(self.sigma2) g2 = np.ndarray(self.T) q2 = g2.copy() - from arch.univariate import recursions_python as recpy - recpy.cgarch_recursion(parameters, + rec.cgarch_recursion(parameters, self.resids ** 2.0, cond_var_direct, backcast, From 8e4bef6355a40c94d66e126946559537fcd50c64 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 10:44:03 +0300 Subject: [PATCH 46/92] Add pylint suggestions --- arch/univariate/tests/test_volatility.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/univariate/tests/test_volatility.py b/arch/univariate/tests/test_volatility.py index 228d29a7ee..03c1bbd6af 100644 --- a/arch/univariate/tests/test_volatility.py +++ b/arch/univariate/tests/test_volatility.py @@ -114,10 +114,10 @@ def test_cgarch(self): g2 = np.ndarray(self.T) q2 = g2.copy() rec.cgarch_recursion(parameters, - self.resids ** 2.0, - cond_var_direct, - backcast, - var_bounds, g2, q2) + self.resids ** 2.0, + cond_var_direct, + backcast, + var_bounds, g2, q2) assert_allclose(self.sigma2, cond_var_direct) a, b = cgarch.constraints() From b8548f82f37ab7ee21fd16a4f4ee8721edfdbf3b Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 12:07:01 +0300 Subject: [PATCH 47/92] Add CGARCH to archmodel function --- arch/univariate/mean.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/univariate/mean.py b/arch/univariate/mean.py index d69b3e3940..ed4f38620c 100644 --- a/arch/univariate/mean.py +++ b/arch/univariate/mean.py @@ -15,7 +15,7 @@ from arch.univariate.base import ARCHModel, implicit_constant, ARCHModelResult, ARCHModelForecast from arch.univariate.distribution import Normal, StudentsT, SkewStudent -from arch.univariate.volatility import ARCH, GARCH, HARCH, ConstantVariance, EGARCH +from arch.univariate.volatility import ARCH, GARCH, HARCH, ConstantVariance, EGARCH, CGARCH from arch.compat.python import range, iteritems from arch.utility.array import ensure1d, parse_dataframe, cutoff_to_index @@ -1141,7 +1141,7 @@ def arch_model(y, x=None, mean='Constant', lags=0, vol='Garch', p=1, o=0, q=1, when `mean='zero'`, are silently ignored. """ known_mean = ('zero', 'constant', 'harx', 'har', 'ar', 'arx', 'ls') - known_vol = ('arch', 'garch', 'harch', 'constant', 'egarch') + known_vol = ('arch', 'garch', 'harch', 'constant', 'egarch', 'cgarch') known_dist = ('normal', 'gaussian', 'studentst', 't', 'skewstudent', 'skewt') mean = mean.lower() @@ -1173,6 +1173,8 @@ def arch_model(y, x=None, mean='Constant', lags=0, vol='Garch', p=1, o=0, q=1, v = ConstantVariance() elif vol == 'arch': v = ARCH(p=p) + elif vol == 'cgarch': + v = CGARCH() elif vol == 'garch': v = GARCH(p=p, o=o, q=q, power=power) elif vol == 'egarch': From fc0ef5a8a25102f6c51ea981734175f2ec63f3c7 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 14:57:02 +0300 Subject: [PATCH 48/92] correct forecast method --- arch/univariate/volatility.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index b3e0fddc5c..0ceb79f4c5 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2097,9 +2097,18 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, var_bounds, horizon) + t = resids.shape[0] + _sigma2 = np.ndarray(t) + self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) + _q2 = np.zeros_like(_sigma2) # find a way to get real q2 array + alpha, beta, omega, rho, phi = parameters if horizon == 1: forecasts[:start] = np.nan return VarianceForecast(forecasts) + _g2 = + for h in range(1, horizon): + q2_forecast = (rho**h)*_q2 + omega * (1 -rho **h)/(1 - rho) + forecast = q2_forecast + (alpha + beta) ** h * ( ) parameters = self._covertparams(parameters) t = resids.shape[0] p, o, q = self.p, self.o, self.q From e1264fbef4954cc2705987978cf38d16f90a8d6a Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 16:30:53 +0300 Subject: [PATCH 49/92] Remove pyproj file --- arch.pyproj | 120 ---------------------------------------------------- 1 file changed, 120 deletions(-) delete mode 100644 arch.pyproj diff --git a/arch.pyproj b/arch.pyproj deleted file mode 100644 index 43cf44bc6c..0000000000 --- a/arch.pyproj +++ /dev/null @@ -1,120 +0,0 @@ - - - - Debug - 2.0 - {7b371827-037d-47aa-b84e-1363caa159ad} - - totestimports.py - - . - . - {888888a0-9f3d-457c-b088-3a5042f75d52} - Standard Python launcher - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - - Code - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 24357052a7924928ffd8076a97b52d6471d7d99c Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 17:05:28 +0300 Subject: [PATCH 50/92] Add analytic forcast for CGARCH --- arch/univariate/volatility.py | 55 +++++------------------------------ 1 file changed, 8 insertions(+), 47 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 0ceb79f4c5..91ce6b5a72 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -188,7 +188,7 @@ def _one_step_forecast(self, parameters, resids, backcast, var_bounds, horizon): ------- sigma2 : array t element array containing the one-step ahead forecasts - forecsts : array + forecasts : array t by horizon array containing the one-step ahead forecasts in the first location """ t = resids.shape[0] @@ -2101,58 +2101,19 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho _sigma2 = np.ndarray(t) self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) _q2 = np.zeros_like(_sigma2) # find a way to get real q2 array + _q2.fill(0.02) alpha, beta, omega, rho, phi = parameters if horizon == 1: forecasts[:start] = np.nan return VarianceForecast(forecasts) - _g2 = + + _g2 = _sigma2 - _g2 + for h in range(1, horizon): q2_forecast = (rho**h)*_q2 + omega * (1 -rho **h)/(1 - rho) - forecast = q2_forecast + (alpha + beta) ** h * ( ) - parameters = self._covertparams(parameters) - t = resids.shape[0] - p, o, q = self.p, self.o, self.q - omega = parameters[0] - alpha = parameters[1:p + 1] - gamma = parameters[p + 1: p + o + 1] - beta = parameters[p + o + 1:] - - m = np.max([p, o, q]) - _resids = np.zeros(m + horizon) - _asym_resids = np.zeros(m + horizon) - _sigma2 = np.zeros(m + horizon) - - for i in range(start, t): - if i - m + 1 >= 0: - _resids[:m] = resids[i - m + 1:i + 1] - _asym_resids[:m] = _resids[:m] * (_resids[:m] < 0) - _sigma2[:m] = sigma2[i - m + 1:i + 1] - else: # Back-casting needed - _resids[:m - i - 1] = np.sqrt(backcast) - _resids[m - i - 1: m] = resids[0:i + 1] - _asym_resids = _resids * (_resids < 0) - _asym_resids[:m - i - 1] = np.sqrt(0.5 * backcast) - _sigma2[:m] = backcast - _sigma2[m - i - 1: m] = sigma2[0:i + 1] - - for h in range(0, horizon): - forecasts[i, h] = omega - start_loc = h + m - 1 - - for j in range(p): - forecasts[i, h] += alpha[j] * _resids[start_loc - j] ** 2 - - for j in range(o): - forecasts[i, h] += gamma[j] * _asym_resids[start_loc - j] ** 2 - - for j in range(q): - forecasts[i, h] += beta[j] * _sigma2[start_loc - j] - - _resids[h + m] = np.sqrt(forecasts[i, h]) - _asym_resids[h + m] = np.sqrt(0.5 * forecasts[i, h]) - _sigma2[h + m] = forecasts[i, h] - - forecasts[:start] = np.nan + sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 + forecasts[:, h] = sigma2_forecasts + forecasts[:start] = np.nan return VarianceForecast(forecasts) def _simulate_paths(self, m, parameters, horizon, std_shocks, From 71b0734f5bebb897ed466d4d196807882e9cd876 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 17:41:51 +0300 Subject: [PATCH 51/92] Add pylint suggestions --- arch/univariate/volatility.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 91ce6b5a72..17a9f3ecce 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2105,14 +2105,12 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho alpha, beta, omega, rho, phi = parameters if horizon == 1: forecasts[:start] = np.nan - return VarianceForecast(forecasts) - - _g2 = _sigma2 - _g2 - + return VarianceForecast(forecasts) + _g2 = _sigma2 - _q2 for h in range(1, horizon): - q2_forecast = (rho**h)*_q2 + omega * (1 -rho **h)/(1 - rho) - sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 - forecasts[:, h] = sigma2_forecasts + q2_forecast = (rho**h)*_q2 + omega * (1 -rho **h)/(1 - rho) + sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 + forecasts[:, h] = sigma2_forecasts forecasts[:start] = np.nan return VarianceForecast(forecasts) From 484a8b75203209b88d8640e6c319a015e45312e1 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 19:00:05 +0300 Subject: [PATCH 52/92] Fix forecast bug --- arch/univariate/volatility.py | 71 ++++++++--------------------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 17a9f3ecce..ccd3039822 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2047,7 +2047,15 @@ def compute_variance(self, parameters, resids, sigma2, backcast, cgarch_recursion(parameters, fresids, sigma2, backcast, var_bounds, g2=g2, q2=q2) return sigma2 - + + def _compute_q(self, parameters, resids, sigma2, backcast, var_bounds): + # is same as compute variance but allows us to get q2 back + fresids = resids**2 + nobs = len(fresids) + g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) + cgarch_recursion(parameters, fresids, sigma2, + backcast, var_bounds, g2=g2, q2=q2) + return q2 def parameter_names(self): names = ["alpha", "beta", "omega", "rho", "phi"] return names @@ -2099,67 +2107,20 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho var_bounds, horizon) t = resids.shape[0] _sigma2 = np.ndarray(t) - self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) - _q2 = np.zeros_like(_sigma2) # find a way to get real q2 array - _q2.fill(0.02) + _q2 = self._compute_q(parameters, resids, _sigma2, backcast, var_bounds) alpha, beta, omega, rho, phi = parameters if horizon == 1: forecasts[:start] = np.nan return VarianceForecast(forecasts) _g2 = _sigma2 - _q2 - for h in range(1, horizon): + for h in range(2, horizon): q2_forecast = (rho**h)*_q2 + omega * (1 -rho **h)/(1 - rho) sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 - forecasts[:, h] = sigma2_forecasts + forecasts[:, h-1] = sigma2_forecasts forecasts[:start] = np.nan return VarianceForecast(forecasts) - def _simulate_paths(self, m, parameters, horizon, std_shocks, - scaled_forecast_paths, scaled_shock, - asym_scaled_shock): - parameters = self._covertparams(parameters) - return super(CGARCH, self)._simulate_paths(m, parameters, - horizon, std_shocks, - scaled_forecast_paths, - scaled_shock, asym_scaled_shock) - - def _simulation_forecast(self, parameters, resids, backcast, var_bounds, - start, horizon, simulations, rng): - sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, - var_bounds, horizon) - # Everything is similar to GARCH class vut parameters have to be converted - parameters = self._covertparams(parameters) - t = resids.shape[0] - paths = np.zeros((t, simulations, horizon)) - shocks = np.zeros((t, simulations, horizon)) - - power = self.power - m = np.max([self.p, self.o, self.q]) - scaled_forecast_paths = zeros((simulations, m + horizon)) - scaled_shock = zeros((simulations, m + horizon)) - asym_scaled_shock = zeros((simulations, m + horizon)) - for i in range(start, t): - std_shocks = rng((simulations, horizon)) - if i - m < 0: - scaled_forecast_paths[:, :m] = backcast ** (power / 2.0) - scaled_shock[:, :m] = backcast ** (power / 2.0) - asym_scaled_shock[:, :m] = (0.5 * backcast) ** (power / 2.0) - - count = i + 1 - scaled_forecast_paths[:, m - count:m] = sigma2[:count] ** (power / 2.0) - scaled_shock[:, m - count:m] = np.abs(resids[:count]) ** power - asym = np.abs(resids[:count]) ** power * (resids[:count] < 0) - asym_scaled_shock[:, m - count:m] = asym - else: - scaled_forecast_paths[:, :m] = sigma2[i - m + 1:i + 1] ** (power / 2.0) - scaled_shock[:, :m] = np.abs(resids[i - m + 1:i + 1]) ** power - asym_scaled_shock[:, :m] = scaled_shock[:, :m] * (resids[i - m + 1:i + 1] < 0) - - f, p, s = self._simulate_paths(m, parameters, horizon, std_shocks, - scaled_forecast_paths, scaled_shock, asym_scaled_shock) - forecasts[i, :], paths[i], shocks[i] = f, p, s - - paths[:start] = np.nan - shocks[:start] = np.nan - forecasts[:start] = np.nan - return VarianceForecast(forecasts, paths, shocks) + def _check_forecasting_method(self, method, horizon): + if method == "simulation" or method == "bootstrap": + raise NotImplementedError("Only analytic method is supported for CGARCH ") + return From bdd84b38956e8a8fe2910af489db1bd76e665105 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 19:19:33 +0300 Subject: [PATCH 53/92] Add pylint suggestions --- arch/univariate/volatility.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index ccd3039822..23553aa5eb 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2047,7 +2047,7 @@ def compute_variance(self, parameters, resids, sigma2, backcast, cgarch_recursion(parameters, fresids, sigma2, backcast, var_bounds, g2=g2, q2=q2) return sigma2 - + def _compute_q(self, parameters, resids, sigma2, backcast, var_bounds): # is same as compute variance but allows us to get q2 back fresids = resids**2 @@ -2056,6 +2056,7 @@ def _compute_q(self, parameters, resids, sigma2, backcast, var_bounds): cgarch_recursion(parameters, fresids, sigma2, backcast, var_bounds, g2=g2, q2=q2) return q2 + def parameter_names(self): names = ["alpha", "beta", "omega", "rho", "phi"] return names @@ -2111,10 +2112,10 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho alpha, beta, omega, rho, phi = parameters if horizon == 1: forecasts[:start] = np.nan - return VarianceForecast(forecasts) + return VarianceForecast(forecasts) _g2 = _sigma2 - _q2 for h in range(2, horizon): - q2_forecast = (rho**h)*_q2 + omega * (1 -rho **h)/(1 - rho) + q2_forecast = (rho ** h) * _q2 + omega * (1 -rho ** h)/(1 - rho) sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 forecasts[:, h-1] = sigma2_forecasts forecasts[:start] = np.nan From 17f7e479eb85be3808beb2ff4b6853a4d2fb2fda Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 19:39:07 +0300 Subject: [PATCH 54/92] Add pylint suggestions --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 23553aa5eb..b20f49a23a 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2115,7 +2115,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho return VarianceForecast(forecasts) _g2 = _sigma2 - _q2 for h in range(2, horizon): - q2_forecast = (rho ** h) * _q2 + omega * (1 -rho ** h)/(1 - rho) + q2_forecast = (rho ** h) * _q2 + omega * (1 -rho ** h) / (1 - rho) sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 forecasts[:, h-1] = sigma2_forecasts forecasts[:start] = np.nan From d2dcf9460be312ebabf0a6fd4f59e0814e518c71 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 21:05:29 +0300 Subject: [PATCH 55/92] Add pylint suggestion --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index b20f49a23a..2d4510bc3b 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2115,7 +2115,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho return VarianceForecast(forecasts) _g2 = _sigma2 - _q2 for h in range(2, horizon): - q2_forecast = (rho ** h) * _q2 + omega * (1 -rho ** h) / (1 - rho) + q2_forecast = (rho ** h) * _q2 + omega * (1 - rho ** h) / (1 - rho) sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 forecasts[:, h-1] = sigma2_forecasts forecasts[:start] = np.nan From 1380e05ebf2e2ad53498169bb825ded1e2add793 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 22:20:32 +0300 Subject: [PATCH 56/92] Modify compute variance to return 2 arrays --- arch/univariate/base.py | 8 ++++++-- arch/univariate/volatility.py | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index ad7c49671a..d6faed88d1 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -273,8 +273,12 @@ def _loglikelihood(self, parameters, sigma2, backcast, var_bounds, resids = self.resids(mp) # 2. Compute sigma2 using VolatilityModel - sigma2 = self.volatility.compute_variance(vp, resids, sigma2, backcast, - var_bounds) + sig = self.volatility.compute_variance(vp, resids, sigma2, backcast, + var_bounds) + if isinstance(sig, tuple): + sigma2 = sig[0] + else: + sigma2 = sig # 3. Compute log likelihood using Distribution llf = self.distribution.loglikelihoood(dp, resids, sigma2, individual) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 2d4510bc3b..4a6fcb770f 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2041,12 +2041,13 @@ def starting_values(self, resids): def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): + # this returns both sigma and long term variance fresids = resids**2 nobs = len(fresids) g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) cgarch_recursion(parameters, fresids, sigma2, backcast, var_bounds, g2=g2, q2=q2) - return sigma2 + return sigma2, q2 def _compute_q(self, parameters, resids, sigma2, backcast, var_bounds): # is same as compute variance but allows us to get q2 back From 9bf03fdcf9715e203933ed50d8aca7c33f05cb05 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 22:31:30 +0300 Subject: [PATCH 57/92] Remove unused method --- arch/univariate/volatility.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 4a6fcb770f..1d952d8336 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2049,15 +2049,6 @@ def compute_variance(self, parameters, resids, sigma2, backcast, backcast, var_bounds, g2=g2, q2=q2) return sigma2, q2 - def _compute_q(self, parameters, resids, sigma2, backcast, var_bounds): - # is same as compute variance but allows us to get q2 back - fresids = resids**2 - nobs = len(fresids) - g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) - cgarch_recursion(parameters, fresids, sigma2, - backcast, var_bounds, g2=g2, q2=q2) - return q2 - def parameter_names(self): names = ["alpha", "beta", "omega", "rho", "phi"] return names @@ -2105,11 +2096,11 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): return data[burn:], sigma2[burn:] def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): - sigma2, forecasts = self._one_step_forecast(parameters, resids, backcast, + _, forecasts = self._one_step_forecast(parameters, resids, backcast, var_bounds, horizon) t = resids.shape[0] _sigma2 = np.ndarray(t) - _q2 = self._compute_q(parameters, resids, _sigma2, backcast, var_bounds) + _sigma2, _q2 = self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) alpha, beta, omega, rho, phi = parameters if horizon == 1: forecasts[:start] = np.nan From bdded031c8f5f34b6879cffb25af006a1840d286 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 23:33:00 +0300 Subject: [PATCH 58/92] Add longterm var attribute --- arch/univariate/base.py | 73 +++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index d6faed88d1..a7e4f12519 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -161,7 +161,8 @@ def __init__(self, y=None, volatility=None, distribution=None, self._distribution = None self._backcast = None self._var_bounds = None - + # used when two arrays are returned in compute_variance + self.tuple_variance = False if volatility is not None: self.volatility = volatility else: @@ -273,12 +274,12 @@ def _loglikelihood(self, parameters, sigma2, backcast, var_bounds, resids = self.resids(mp) # 2. Compute sigma2 using VolatilityModel - sig = self.volatility.compute_variance(vp, resids, sigma2, backcast, + sigma2 = self.volatility.compute_variance(vp, resids, sigma2, backcast, var_bounds) if isinstance(sig, tuple): - sigma2 = sig[0] - else: - sigma2 = sig + self.tuple_variance = True + sigma2 = sigma2[0] + # 3. Compute log likelihood using Distribution llf = self.distribution.loglikelihoood(dp, resids, sigma2, individual) @@ -343,11 +344,16 @@ def fix(self, params, first_obs=None, last_obs=None): resids = self.resids(mp) vol = np.zeros_like(resids) - self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) + vol = self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) + if isinstance(vol, tuple): + self.tuple_variance = True + vol = vol[0] + long_var = vol[1] vol = np.sqrt(vol) names = self._all_parameter_names() # Reshape resids and vol + # this part is too repetitive first_obs, last_obs = self._fit_indices resids_final = np.empty_like(self._y, dtype=np.float64) resids_final.fill(np.nan) @@ -355,9 +361,14 @@ def fix(self, params, first_obs=None, last_obs=None): vol_final = np.empty_like(self._y, dtype=np.float64) vol_final.fill(np.nan) vol_final[first_obs:last_obs] = vol + long_var_final = np.empty_like(self._y, dtype=np.float64) + long_var_final.fill(np.nan) + if self.tuple_variance: + long_var_final[first_obs:last_obs] = long_var model_copy = deepcopy(self) - return ARCHModelFixedResult(params, resids, vol, self._y_series, names, + return ARCHModelFixedResult(params, resids, vol, long_var_final, + self._y_series, names, loglikelihood, self._is_pandas, model_copy) def _adjust_sample(self, first_obs, last_obs): @@ -528,7 +539,10 @@ def fit(self, update_freq=1, disp='final', starting_values=None, resids = self.resids(mp) vol = np.zeros_like(resids) - self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) + vol = self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) + if isinstance(vol, tuple): + vol = vol[0] + long_var = vol[1] vol = np.sqrt(vol) try: @@ -538,6 +552,7 @@ def fit(self, update_freq=1, disp='final', starting_values=None, names = self._all_parameter_names() # Reshape resids and vol + # this part is too repetitive come back to this when done first_obs, last_obs = self._fit_indices resids_final = np.empty_like(self._y, dtype=np.float64) resids_final.fill(np.nan) @@ -545,12 +560,16 @@ def fit(self, update_freq=1, disp='final', starting_values=None, vol_final = np.empty_like(self._y, dtype=np.float64) vol_final.fill(np.nan) vol_final[first_obs:last_obs] = vol + long_var_final = np.empty_like(self._y, dtype=np.float64) + long_var_final.fill(np.nan) + long_var_final[first_obs:last_obs] = long_var fit_start, fit_stop = self._fit_indices model_copy = deepcopy(self) return ARCHModelResult(params, None, r2, resids_final, vol_final, - cov_type, self._y_series, names, loglikelihood, - self._is_pandas, xopt, fit_start, fit_stop, model_copy) + long_var_final,cov_type, self._y_series, names, + loglikelihood, self._is_pandas, + xopt, fit_start, fit_stop, model_copy) def parameter_names(self): """List of parameters names @@ -739,6 +758,8 @@ class ARCHModelFixedResult(object): contain nan-values in locations not used in estimation volatility : array Conditional volatility from model + longterm_var : array + Long term variance from model dep_var: Series Dependent variable names: list (str) @@ -784,8 +805,10 @@ class ARCHModelFixedResult(object): Model instance used to produce the fit """ - def __init__(self, params, resid, volatility, dep_var, names, - loglikelihood, is_pandas, model): + def __init__(self, params, resid, volatility, + longterm_var, + dep_var, names, loglikelihood, + is_pandas, model): self._params = params self._resid = resid self._is_pandas = is_pandas @@ -799,6 +822,7 @@ def __init__(self, params, resid, volatility, dep_var, names, self._nobs = self.model._fit_y.shape[0] self._index = dep_var.index self._volatility = volatility + self._longterm_var = longterm_var def summary(self): """ @@ -948,6 +972,18 @@ def conditional_volatility(self): else: return self._volatility + @cache_readonly + def longterm_variance(self): + """ + Estimated conditional volatility + """ + if self._is_pandas: + return pd.Series(self._longterm_var, + name='Longterm variance', + index=self._index) + else: + return self._longterm_var + @cache_readonly def nobs(self): """ @@ -1219,6 +1255,8 @@ class ARCHModelResult(ARCHModelFixedResult): contain nan-values in locations not used in estimation volatility : array Conditional volatility from model + longterm_var : array + Longterm variance from model cov_type : str String describing the covariance estimator used dep_var: Series @@ -1259,6 +1297,7 @@ class ARCHModelResult(ARCHModelFixedResult): of conditional variance). The values are aligned with the input data so that the value in the t-th position is the variance of t-th error, which is computed using time-(t-1) information. + params : Series Estimated parameters param_cov : DataFrame @@ -1283,12 +1322,12 @@ class ARCHModelResult(ARCHModelFixedResult): Model instance used to produce the fit """ - def __init__(self, params, param_cov, r2, resid, volatility, cov_type, - dep_var, names, loglikelihood, is_pandas, optim_output, - fit_start, fit_stop, model): + def __init__(self, params, param_cov, r2, resid, volatility, longterm_var, + cov_type,dep_var, names, loglikelihood, is_pandas, + optim_output,fit_start, fit_stop, model): super(ARCHModelResult, self).__init__(params, resid, volatility, - dep_var, names, loglikelihood, - is_pandas, model) + longterm_var, dep_var, names, + loglikelihood, is_pandas, model) self._fit_indices = (fit_start, fit_stop) self._param_cov = param_cov From 9e7c159261d9ace48a6014a0d6e62a04a8782ceb Mon Sep 17 00:00:00 2001 From: Richard MM Date: Thu, 3 Aug 2017 23:57:00 +0300 Subject: [PATCH 59/92] Fix missing argument bug --- arch/univariate/mean.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/univariate/mean.py b/arch/univariate/mean.py index ed4f38620c..797dc691f3 100644 --- a/arch/univariate/mean.py +++ b/arch/univariate/mean.py @@ -567,7 +567,7 @@ def _fit_no_arch_normal_errors(self, cov_type='robust'): 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, + return ARCHModelResult(params, param_cov, 0.0, y, vol, None, cov_type, self._y_series, names, loglikelihood, self._is_pandas, _xopt, fit_start, fit_stop, copy.deepcopy(self)) @@ -614,7 +614,7 @@ def _fit_no_arch_normal_errors(self, cov_type='robust'): 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, + return ARCHModelResult(params, param_cov, r2, resids, vol, None, cov_type, self._y_series, names, loglikelihood, self._is_pandas, _xopt, fit_start, fit_stop, copy.deepcopy(self)) From b10bae278cd569f61e32a9026744f815c2b82872 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 00:03:00 +0300 Subject: [PATCH 60/92] Fix optimization bug --- arch/univariate/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index a7e4f12519..4b1867b31c 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -276,7 +276,7 @@ def _loglikelihood(self, parameters, sigma2, backcast, var_bounds, # 2. Compute sigma2 using VolatilityModel sigma2 = self.volatility.compute_variance(vp, resids, sigma2, backcast, var_bounds) - if isinstance(sig, tuple): + if isinstance(sigma2, tuple): self.tuple_variance = True sigma2 = sigma2[0] From 352a19618b55cca8ef566d77e8548527973b4fc7 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 00:06:51 +0300 Subject: [PATCH 61/92] Fix assignment error --- arch/univariate/base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 4b1867b31c..832a65e4c7 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -541,6 +541,7 @@ def fit(self, update_freq=1, disp='final', starting_values=None, vol = np.zeros_like(resids) vol = self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) if isinstance(vol, tuple): + self.tuple_variance = True vol = vol[0] long_var = vol[1] vol = np.sqrt(vol) @@ -562,7 +563,8 @@ def fit(self, update_freq=1, disp='final', starting_values=None, vol_final[first_obs:last_obs] = vol long_var_final = np.empty_like(self._y, dtype=np.float64) long_var_final.fill(np.nan) - long_var_final[first_obs:last_obs] = long_var + if self.tuple_variance = True: + long_var_final[first_obs:last_obs] = long_var fit_start, fit_stop = self._fit_indices model_copy = deepcopy(self) From 6ba62d71d13cc9bf842ff02f48b49980ad9f03cf Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 00:08:07 +0300 Subject: [PATCH 62/92] Fix assignment bug --- arch/univariate/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 832a65e4c7..2abfe07eed 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -563,7 +563,7 @@ def fit(self, update_freq=1, disp='final', starting_values=None, vol_final[first_obs:last_obs] = vol long_var_final = np.empty_like(self._y, dtype=np.float64) long_var_final.fill(np.nan) - if self.tuple_variance = True: + if self.tuple_variance == True: long_var_final[first_obs:last_obs] = long_var fit_start, fit_stop = self._fit_indices From 6bae5807254dc954c5896fcc105524211529fc42 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 09:23:03 +0300 Subject: [PATCH 63/92] Modify doc for longterm_variance The method doc was referring to conditional volatility --- arch/univariate/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 2abfe07eed..f130ee260c 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -977,7 +977,7 @@ def conditional_volatility(self): @cache_readonly def longterm_variance(self): """ - Estimated conditional volatility + Estimated Longterm variance """ if self._is_pandas: return pd.Series(self._longterm_var, From e7826511eb6da2a2291a82cd6c3e3e7215869e0c Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 09:31:36 +0300 Subject: [PATCH 64/92] Add longterm forecast property to VarianceForecast class This will be helpful when the volatility Process outputs a long erm component in addition to the conditional volatility. --- arch/univariate/volatility.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 1d952d8336..0fc474889a 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -88,15 +88,24 @@ class VarianceForecast(object): _forecasts = None _forecast_paths = None - def __init__(self, forecasts, forecast_paths=None, shocks=None): + def __init__(self, forecasts, forecast_paths=None, shocks=None, + longterm_forecasts=None): self._forecasts = forecasts self._forecast_paths = forecast_paths self._shocks = shocks + self._longterm_forecasts = None @property def forecasts(self): return self._forecasts + @property + def longterm_forecasts(self): + """ + Used if volatility process outputs a long term component + """ + return self._longterm_forecasts + @property def forecast_paths(self): return self._forecast_paths From 6693e42f72d77391cbfb1c9e769580abbe1db022 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 10:00:01 +0300 Subject: [PATCH 65/92] Modify _one_step_forecast to cater for cgarch The method is moified for the base Volatility process to allow for a volatility process with a component to have its longterm forecasts returned --- arch/univariate/volatility.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 0fc474889a..8a1fe33a54 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -175,7 +175,8 @@ def _check_forecasting_method(self, method, horizon): """ raise NotImplementedError('Must be overridden') # pragma: no cover - def _one_step_forecast(self, parameters, resids, backcast, var_bounds, horizon): + def _one_step_forecast(self, parameters, resids, backcast, var_bounds, + horizon, lterm_component=False): """ One-step ahead forecast @@ -204,11 +205,19 @@ def _one_step_forecast(self, parameters, resids, backcast, var_bounds, horizon): _resids = np.concatenate((resids, [0])) _var_bounds = np.concatenate((var_bounds, [[0, np.inf]])) sigma2 = np.zeros(t + 1) - self.compute_variance(parameters, _resids, sigma2, backcast, _var_bounds) + sigma2 = self.compute_variance(parameters, _resids, sigma2, backcast, + _var_bounds) + if lterm_component: + sigma2 = sigma2[0] + component = sigma2[1] + component_forecasts = np.ndarray((t, horizon)) + component_forecasts[:, 0] = component[1:] + forecasts = np.zeros((t, horizon)) forecasts[:, 0] = sigma2[1:] sigma2 = sigma2[:-1] - + if lterm_component: + return sigma2, forecasts, component_forecasts return sigma2, forecasts def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): From 3bda0f76ae2653f2b14a48944bb5f62f374296bf Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 10:08:49 +0300 Subject: [PATCH 66/92] Modify CGARCH forecast methods CGARCH process can now also produce forecasts for its long term component. This builds on functionality added to _one_step_forecast and VarianceForecast. --- arch/univariate/volatility.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 8a1fe33a54..1cbda1e54a 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2114,8 +2114,9 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): return data[burn:], sigma2[burn:] def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): - _, forecasts = self._one_step_forecast(parameters, resids, backcast, - var_bounds, horizon) + _, forecasts, q2_forecast= self._one_step_forecast(parameters, resids, backcast, + var_bounds, horizon, + lterm_component=True) t = resids.shape[0] _sigma2 = np.ndarray(t) _sigma2, _q2 = self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) @@ -2125,11 +2126,13 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho return VarianceForecast(forecasts) _g2 = _sigma2 - _q2 for h in range(2, horizon): - q2_forecast = (rho ** h) * _q2 + omega * (1 - rho ** h) / (1 - rho) - sigma2_forecasts = q2_forecast + (alpha + beta) ** h * _g2 + _q2_forecast = (rho ** h) * _q2 + omega * (1 - rho ** h) / (1 - rho) + sigma2_forecasts = _q2_forecast + (alpha + beta) ** h * _g2 forecasts[:, h-1] = sigma2_forecasts - forecasts[:start] = np.nan - return VarianceForecast(forecasts) + q2_forecast[:, h-1] = _q2_forecast + + forecasts[:start] = q2_forecast[:start] = np.nan + return VarianceForecast(forecasts, longterm_forecasts=q2_forecast) def _check_forecasting_method(self, method, horizon): if method == "simulation" or method == "bootstrap": From 8f56e9ac1f5bc75ce3d382347bb2212a7ef537c3 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 10:11:57 +0300 Subject: [PATCH 67/92] Fix assignment bug in VarianceForecast The longterm forecasts attribute was returning None due to erroneous assignment --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 1cbda1e54a..960a5342ae 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -93,7 +93,7 @@ def __init__(self, forecasts, forecast_paths=None, shocks=None, self._forecasts = forecasts self._forecast_paths = forecast_paths self._shocks = shocks - self._longterm_forecasts = None + self._longterm_forecasts = longterm_forecasts @property def forecasts(self): From 74a0d5688f059a2cdb5447b3c830c06b9a47bbca Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 11:06:31 +0300 Subject: [PATCH 68/92] Modify ARCHModelForecast to handle component forecasts The class now has a default property for longterm component forecasts --- arch/univariate/base.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index f130ee260c..4424443200 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -1560,6 +1560,8 @@ def _align_forecast(f, align): def _format_forecasts(values, index): + if isinstance(values, type(None)): + return None horizon = values.shape[1] format_str = '{0:>0' + str(int(np.ceil(np.log10(horizon + 0.5)))) + '}' columns = ['h.' + format_str.format(h + 1) for h in range(horizon)] @@ -1624,6 +1626,7 @@ class ARCHModelForecast(object): mean : array variance : array residual_variance : array + lterm_residual_variance : array simulated_paths : array, optional simulated_variances : array, optional simulated_residual_variances : array, optional @@ -1638,10 +1641,13 @@ class ARCHModelForecast(object): Forecast values for the conditional variance of the process residual_variance : DataFrame Forecast values for the conditional variance of the residuals + longterm_component : DataFrame + Forecast values for the conditional variance of the residuals simulations : ARCHModelForecastSimulation Object containing detailed simulation results if using a simulation-based method """ def __init__(self, index, mean, variance, residual_variance, + lterm_residual_variance=None, simulated_paths=None, simulated_variances=None, simulated_residual_variances=None, simulated_residuals=None, align='origin'): @@ -1649,11 +1655,13 @@ def __init__(self, index, mean, variance, residual_variance, mean = _format_forecasts(mean, index) variance = _format_forecasts(variance, index) residual_variance = _format_forecasts(residual_variance, index) + lterm_residual_variance = _format_forecasts(lterm_residual_variance, index) self._mean = _align_forecast(mean, align=align) self._variance = _align_forecast(variance, align=align) self._residual_variance = _align_forecast(residual_variance, align=align) - + self._lterm_residual_variance = _align_forecast(lterm_residual_variance, + align=align) self._sim = ARCHModelForecastSimulation(simulated_paths, simulated_residuals, simulated_variances, @@ -1671,6 +1679,10 @@ def variance(self): def residual_variance(self): return self._residual_variance + @property + def longterm_component(self): + return self._lterm_residual_variance + @property def simulations(self): return self._sim From c32ac8d96c55c34d713e46626c5b771875eaf5a3 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 11:12:14 +0300 Subject: [PATCH 69/92] Modify HARX model to cater for component volatility processes Now forecasts will include the component part --- arch/univariate/mean.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/univariate/mean.py b/arch/univariate/mean.py index 797dc691f3..884d54ea00 100644 --- a/arch/univariate/mean.py +++ b/arch/univariate/mean.py @@ -28,6 +28,8 @@ def _forecast_pad(count, forecasts): + if isinstance(forecasts, type(None)): + return None shape = list(forecasts.shape) shape[0] = count fill = np.empty(tuple(shape)) @@ -652,7 +654,9 @@ def forecast(self, parameters, horizon=1, start=None, align='origin', horizon=horizon, method=method, simulations=simulations, rng=rng) var_fcasts = vfcast.forecasts + long_component = vfcast.longterm_forecasts var_fcasts = _forecast_pad(earliest, var_fcasts) + long_component = _forecast_pad(earliest, long_component) arp = self._har_to_ar(mp) constant = arp[0] if self.constant else 0.0 @@ -691,7 +695,8 @@ def forecast(self, parameters, horizon=1, start=None, align='origin', index = self._y_series.index return ARCHModelForecast(index, mean_fcast, longrun_var_fcasts, - var_fcasts, align=align, + var_fcasts, long_component + align=align, simulated_paths=mean_paths, simulated_residuals=shocks, simulated_variances=long_run_variance_paths, From 9b7e68007e725fd41f6bcaabc9fd17e147563b63 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 11:22:06 +0300 Subject: [PATCH 70/92] Fix bug in HARX model forecast return ARCHModelForecast args were not input correctly --- arch/univariate/mean.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/mean.py b/arch/univariate/mean.py index 884d54ea00..054fb40f65 100644 --- a/arch/univariate/mean.py +++ b/arch/univariate/mean.py @@ -695,7 +695,7 @@ def forecast(self, parameters, horizon=1, start=None, align='origin', index = self._y_series.index return ARCHModelForecast(index, mean_fcast, longrun_var_fcasts, - var_fcasts, long_component + var_fcasts, long_component, align=align, simulated_paths=mean_paths, simulated_residuals=shocks, From 82b5b7f5dd1d25747d02b85e60c6ccb8e8bc52c0 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 11:43:27 +0300 Subject: [PATCH 71/92] Fix bug in cgarch forecasts --- arch/univariate/volatility.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 960a5342ae..77493b08f6 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -176,7 +176,7 @@ def _check_forecasting_method(self, method, horizon): raise NotImplementedError('Must be overridden') # pragma: no cover def _one_step_forecast(self, parameters, resids, backcast, var_bounds, - horizon, lterm_component=False): + horizon): """ One-step ahead forecast @@ -207,7 +207,7 @@ def _one_step_forecast(self, parameters, resids, backcast, var_bounds, sigma2 = np.zeros(t + 1) sigma2 = self.compute_variance(parameters, _resids, sigma2, backcast, _var_bounds) - if lterm_component: + if isinstance(sigma2, tuple): sigma2 = sigma2[0] component = sigma2[1] component_forecasts = np.ndarray((t, horizon)) @@ -2115,8 +2115,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): _, forecasts, q2_forecast= self._one_step_forecast(parameters, resids, backcast, - var_bounds, horizon, - lterm_component=True) + var_bounds, horizon) t = resids.shape[0] _sigma2 = np.ndarray(t) _sigma2, _q2 = self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) @@ -2132,7 +2131,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho q2_forecast[:, h-1] = _q2_forecast forecasts[:start] = q2_forecast[:start] = np.nan - return VarianceForecast(forecasts, longterm_forecasts=q2_forecast) + return VarianceForecast(forecasts) def _check_forecasting_method(self, method, horizon): if method == "simulation" or method == "bootstrap": From b4f3719aa2599b1e08eb21ef7da19166d891f7c7 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 11:53:49 +0300 Subject: [PATCH 72/92] Fix bug in handling tuple return Previously tuple return from compute_variance was unpacked poorly leading to the last item being overwritten by the first --- arch/univariate/base.py | 4 ++-- arch/univariate/volatility.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 4424443200..0c51f1e86c 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -347,8 +347,8 @@ def fix(self, params, first_obs=None, last_obs=None): vol = self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) if isinstance(vol, tuple): self.tuple_variance = True - vol = vol[0] long_var = vol[1] + vol = vol[0] vol = np.sqrt(vol) names = self._all_parameter_names() @@ -542,8 +542,8 @@ def fit(self, update_freq=1, disp='final', starting_values=None, vol = self.volatility.compute_variance(vp, resids, vol, backcast, var_bounds) if isinstance(vol, tuple): self.tuple_variance = True - vol = vol[0] long_var = vol[1] + vol = vol[0] vol = np.sqrt(vol) try: diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 77493b08f6..6c7bc9e029 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -201,6 +201,7 @@ def _one_step_forecast(self, parameters, resids, backcast, var_bounds, forecasts : array t by horizon array containing the one-step ahead forecasts in the first location """ + lterm_component = False t = resids.shape[0] _resids = np.concatenate((resids, [0])) _var_bounds = np.concatenate((var_bounds, [[0, np.inf]])) @@ -208,8 +209,8 @@ def _one_step_forecast(self, parameters, resids, backcast, var_bounds, sigma2 = self.compute_variance(parameters, _resids, sigma2, backcast, _var_bounds) if isinstance(sigma2, tuple): - sigma2 = sigma2[0] - component = sigma2[1] + lterm_component = True + sigma2, component = sigma2 component_forecasts = np.ndarray((t, horizon)) component_forecasts[:, 0] = component[1:] From edba0ce6792e3119026373d2d7ef965235364ade Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 12:13:47 +0300 Subject: [PATCH 73/92] Fix bug in cgarch forecasts The Variance forecast method did not have the longterm component argument. --- arch/univariate/volatility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 6c7bc9e029..b5cbd2facb 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2132,7 +2132,7 @@ def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, ho q2_forecast[:, h-1] = _q2_forecast forecasts[:start] = q2_forecast[:start] = np.nan - return VarianceForecast(forecasts) + return VarianceForecast(forecasts, longterm_forecasts=q2_forecast) def _check_forecasting_method(self, method, horizon): if method == "simulation" or method == "bootstrap": From d30c929e3f0cd62abef2341b8aab0c396f1d9e7e Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 12:41:28 +0300 Subject: [PATCH 74/92] Format to conform to pylint --- arch/univariate/base.py | 14 +++++++------- arch/univariate/volatility.py | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 0c51f1e86c..bf41801d1d 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -275,7 +275,7 @@ def _loglikelihood(self, parameters, sigma2, backcast, var_bounds, # 2. Compute sigma2 using VolatilityModel sigma2 = self.volatility.compute_variance(vp, resids, sigma2, backcast, - var_bounds) + var_bounds) if isinstance(sigma2, tuple): self.tuple_variance = True sigma2 = sigma2[0] @@ -348,7 +348,7 @@ def fix(self, params, first_obs=None, last_obs=None): if isinstance(vol, tuple): self.tuple_variance = True long_var = vol[1] - vol = vol[0] + vol = vol[0] vol = np.sqrt(vol) names = self._all_parameter_names() @@ -563,13 +563,13 @@ def fit(self, update_freq=1, disp='final', starting_values=None, vol_final[first_obs:last_obs] = vol long_var_final = np.empty_like(self._y, dtype=np.float64) long_var_final.fill(np.nan) - if self.tuple_variance == True: + if self.tuple_variance: long_var_final[first_obs:last_obs] = long_var fit_start, fit_stop = self._fit_indices model_copy = deepcopy(self) return ARCHModelResult(params, None, r2, resids_final, vol_final, - long_var_final,cov_type, self._y_series, names, + long_var_final, cov_type, self._y_series, names, loglikelihood, self._is_pandas, xopt, fit_start, fit_stop, model_copy) @@ -1299,7 +1299,7 @@ class ARCHModelResult(ARCHModelFixedResult): of conditional variance). The values are aligned with the input data so that the value in the t-th position is the variance of t-th error, which is computed using time-(t-1) information. - + params : Series Estimated parameters param_cov : DataFrame @@ -1325,8 +1325,8 @@ class ARCHModelResult(ARCHModelFixedResult): """ def __init__(self, params, param_cov, r2, resid, volatility, longterm_var, - cov_type,dep_var, names, loglikelihood, is_pandas, - optim_output,fit_start, fit_stop, model): + cov_type, dep_var, names, loglikelihood, is_pandas, + optim_output, fit_start, fit_stop, model): super(ARCHModelResult, self).__init__(params, resid, volatility, longterm_var, dep_var, names, loglikelihood, is_pandas, model) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index b5cbd2facb..9ee3a9a9f0 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2115,8 +2115,8 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): return data[burn:], sigma2[burn:] def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon): - _, forecasts, q2_forecast= self._one_step_forecast(parameters, resids, backcast, - var_bounds, horizon) + _, forecasts, q2_forecast = self._one_step_forecast(parameters, resids, backcast, + var_bounds, horizon) t = resids.shape[0] _sigma2 = np.ndarray(t) _sigma2, _q2 = self.compute_variance(parameters, resids, _sigma2, backcast, var_bounds) From ae6273178e73c318fc2220722d618c161a26375f Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 14:13:57 +0300 Subject: [PATCH 75/92] Improve docs --- arch/univariate/base.py | 9 ++++++++- arch/univariate/tests/test_recursions.py | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index bf41801d1d..f6c4fd6025 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -795,6 +795,10 @@ class ARCHModelFixedResult(object): of conditional variance). The values are aligned with the input data so that the value in the t-th position is the variance of t-th error, which is computed using time-(t-1) information. + longterm_variance : array + nobs array containing the Long-term variance from model.Is aligned + with the input data. + Is only present if the volatility process outputs it. params : Series Estimated parameters nobs : int @@ -1299,7 +1303,10 @@ class ARCHModelResult(ARCHModelFixedResult): of conditional variance). The values are aligned with the input data so that the value in the t-th position is the variance of t-th error, which is computed using time-(t-1) information. - + longterm_var : array + nobs array containing the Long-term variance from model.Is aligned + with the input data. + Is only present if the volatility process outputs it else it returns None. params : Series Estimated parameters param_cov : DataFrame diff --git a/arch/univariate/tests/test_recursions.py b/arch/univariate/tests/test_recursions.py index f4f2cbd850..7f55983888 100644 --- a/arch/univariate/tests/test_recursions.py +++ b/arch/univariate/tests/test_recursions.py @@ -353,7 +353,6 @@ def test_cgarch(self): recpy.cgarch_recursion_python(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) sigma2_python = sigma2.copy() - # rec = recpy # change this after implementing cythonised recursion rec.cgarch_recursion(parameters, fresids, sigma2, backcast, self.var_bounds, g2, q2) From 4611fea254c259fe794a70b6af837c15f232635b Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 15:04:58 +0300 Subject: [PATCH 76/92] Add some unneeded files --- .gitignore | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index b48258345d..3fa11eb843 100644 --- a/.gitignore +++ b/.gitignore @@ -8,18 +8,15 @@ dist .benchmarks/ .cache/ README.rst -<<<<<<< HEAD *.suo -/arch.sln + /totestimports.py *.user /.vs/config/applicationhost.config /examples/.ipynb_checkpoints/univariate_volatility_modeling-checkpoint.ipynb /local_cythonrecursion.py -======= /.vs/arch/v14/.suo *.pyproj *.sln -/totestimports.py + /.vs/config/applicationhost.config ->>>>>>> 1b901cc286d0184f1366da122f7c03bc4536aea7 From 5d3c5d24b573d4b2483f82e5a265b8671123c8c7 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Fri, 4 Aug 2017 16:38:40 +0300 Subject: [PATCH 77/92] Modify docs The docs now show presence of cgarch process and longterm variance attribute --- arch/univariate/base.py | 2 +- arch/univariate/volatility.py | 8 +++++++- doc/source/univariate/forecasting.rst | 5 ++++- doc/source/univariate/volatility.rst | 6 ++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index f4f28a2404..9f02d484fa 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -1262,7 +1262,7 @@ class ARCHModelResult(ARCHModelFixedResult): volatility : array Conditional volatility from model longterm_var : array - Longterm variance from model + Longterm variance from model if the volatility process outputs it cov_type : str String describing the covariance estimator used dep_var: Series diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 725ceaf7b7..3226db009d 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2006,7 +2006,8 @@ def _simulation_forecast(self, parameters, resids, backcast, var_bounds, start, class CGARCH(GARCH): r""" - Component GARCH model. A restricted version of GARCH(2,2) by Engle and Lee + Component GARCH model. A restricted version of GARCH(2,2) by Engle and Lee. + Decomposes volatility into its long term and short term components. Parameters ---------- @@ -2017,6 +2018,11 @@ class CGARCH(GARCH): num_params : int The number of parameters in the model + Examples + -------- + >>> from arch.univariate import CGARCH + >>> cgarch = CGARCH() + Notes ----- In this class of processes, the variance dynamics are diff --git a/doc/source/univariate/forecasting.rst b/doc/source/univariate/forecasting.rst index d4ab1f7379..01164337bd 100644 --- a/doc/source/univariate/forecasting.rst +++ b/doc/source/univariate/forecasting.rst @@ -178,13 +178,16 @@ Any call to :py:meth:`~arch.univariate.base.ARCHModelResult.forecast` returns a attributes and 1 which may be useful when using simulation- or bootstrap-based forecasts. -The three core attributes are +The four core attributes are * ``mean`` - The forecast conditional mean. * ``variance`` - The forecast conditional variance. * ``residual_variance`` - The forecast conditional variance of residuals. This will differ from ``variance`` whenever the model has dynamics (e.g. an AR model) for horizons larger than 1. +* ``longterm_component`` - The forecast longterm conditional variance of residuals. + This is present only if the volatility process supports integer + (e.g. ``CGARCH process``) Each attribute contains a ``DataFrame`` with a common structure. diff --git a/doc/source/univariate/volatility.rst b/doc/source/univariate/volatility.rst index 2ed91a9584..a9e91a64df 100644 --- a/doc/source/univariate/volatility.rst +++ b/doc/source/univariate/volatility.rst @@ -36,6 +36,12 @@ ARCH .. autoclass:: ARCH :members: starting_values, backcast, compute_variance, bounds, constraints, simulate +CGARCH +------ + +.. autoclass:: CGARCH + :members: starting_values, backcast, compute_variance, bounds, constraints, simulate + Parameterless Variance Processes -------------------------------- Some volatility processes use fixed parameters and so have no parameters that From 870bcb8ef86739580fe477f70edfdc39b7286123 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 00:26:45 +0300 Subject: [PATCH 78/92] Tweak starting values CGARCH starting values search space was too small.rho now includes 0.65 --- arch/univariate/volatility.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 3226db009d..c5efa497fa 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2063,7 +2063,20 @@ def bounds(self, resids): return [(0, 1), (0, 1), (-1, 1), (0, 1), (0, 1)] def starting_values(self, resids): - return np.array([0.1, 0.4, np.var(resids)/2, 0.8, 0.2]) + alphas = [0.07, 0.1] + betas = [0.5, 0.6, 0.4] + omegas = [np.var(resids) * 5, 0.05] + rhos = [0.65, 0.8, 0.9] + phis = [0.1, 0.05, 0.2, 0.3] + combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) + llfs = np.ndarray(len(combos)) + + for i, values in enumerate(combos): + llfs[i] = self._gaussian_loglikelihood(np.array(values), resids, + self.backcast(resids), + self.variance_bounds(resids)) + + return combos[np.argmax(llfs)] def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): From 0e4edca9fabd48afe710099cbf951f3a12cdc4b6 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 13:45:27 +0300 Subject: [PATCH 79/92] Modify starting values --- .gitignore | 1 + arch/tests/univariate/test_volatility.py | 4 ++-- arch/univariate/volatility.py | 14 +++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 3fa11eb843..5b79ab0c83 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ README.rst *.sln /.vs/config/applicationhost.config +.vscode/settings.json diff --git a/arch/tests/univariate/test_volatility.py b/arch/tests/univariate/test_volatility.py index 03c1bbd6af..1c1aa6c7ec 100644 --- a/arch/tests/univariate/test_volatility.py +++ b/arch/tests/univariate/test_volatility.py @@ -100,8 +100,8 @@ def test_cgarch(self): bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) assert_equal(bounds[1], (0, 1)) - assert_equal(bounds[2], (-1, 1)) - assert_equal(bounds[3], (0, 1)) + assert_equal(bounds[2], (0, 0.4)) + assert_equal(bounds[3], (0.98, 1)) assert_equal(bounds[4], (0, 1)) backcast = cgarch.backcast(self.resids) w = 0.94 ** np.arange(75) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index c5efa497fa..f5656dfef1 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2060,14 +2060,14 @@ def backcast(self, resids): return super(CGARCH, self).backcast(resids) def bounds(self, resids): - return [(0, 1), (0, 1), (-1, 1), (0, 1), (0, 1)] + return [(0, 1), (0, 1), (0, 0.4), (0.98, 1), (0, 1)] def starting_values(self, resids): - alphas = [0.07, 0.1] - betas = [0.5, 0.6, 0.4] - omegas = [np.var(resids) * 5, 0.05] - rhos = [0.65, 0.8, 0.9] - phis = [0.1, 0.05, 0.2, 0.3] + alphas = [0.08, 0.3] + betas = [0.6, 0.7] + omegas = [np.var(resids) * 5] + rhos = [0.991] + phis = [ 0.1, 0.2] combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) llfs = np.ndarray(len(combos)) @@ -2076,7 +2076,7 @@ def starting_values(self, resids): self.backcast(resids), self.variance_bounds(resids)) - return combos[np.argmax(llfs)] + return np.array(combos[np.argmax(llfs)]) def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): From 3ab7a849ead1c7ab0b03bf7d21451ff7d97006bb Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 14:01:38 +0300 Subject: [PATCH 80/92] Modify starting values for cgarch --- .gitignore | 1 + arch/univariate/volatility.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5b79ab0c83..c1d8a5e503 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ README.rst /.vs/config/applicationhost.config .vscode/settings.json +.ipynb_checkpoints/Untitled-checkpoint.ipynb diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index f5656dfef1..76d8c66455 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2060,14 +2060,14 @@ def backcast(self, resids): return super(CGARCH, self).backcast(resids) def bounds(self, resids): - return [(0, 1), (0, 1), (0, 0.4), (0.98, 1), (0, 1)] + return [(0, 1), (0, 1), (0, 0.1), (0.98, 1), (0, 1)] def starting_values(self, resids): alphas = [0.08, 0.3] - betas = [0.6, 0.7] + betas = [0.6] omegas = [np.var(resids) * 5] rhos = [0.991] - phis = [ 0.1, 0.2] + phis = [0.01, 0.2] combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) llfs = np.ndarray(len(combos)) From 2c3e45711819af54f6dcdf5311564daf4d0e7395 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 14:58:58 +0300 Subject: [PATCH 81/92] Modify starting values --- arch/univariate/volatility.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 76d8c66455..45e0ab5829 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2060,12 +2060,12 @@ def backcast(self, resids): return super(CGARCH, self).backcast(resids) def bounds(self, resids): - return [(0, 1), (0, 1), (0, 0.1), (0.98, 1), (0, 1)] + return [(0, 1), (0, 1), (0, 0.05), (0.97, 1), (0, 1)] def starting_values(self, resids): - alphas = [0.08, 0.3] - betas = [0.6] - omegas = [np.var(resids) * 5] + alphas = [0.08, 0.2] + betas = [0.6, 0.4, 0.1] + omegas = [np.var(resids)/2, 0.00001] rhos = [0.991] phis = [0.01, 0.2] combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) From 0cd6f574e9dd8b57c3e0e11fb7a162564274ce35 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 15:06:37 +0300 Subject: [PATCH 82/92] Modify cgarch starting values and bounds --- arch/tests/univariate/test_volatility.py | 4 ++-- arch/univariate/volatility.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/tests/univariate/test_volatility.py b/arch/tests/univariate/test_volatility.py index 1c1aa6c7ec..90971dddf2 100644 --- a/arch/tests/univariate/test_volatility.py +++ b/arch/tests/univariate/test_volatility.py @@ -100,8 +100,8 @@ def test_cgarch(self): bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) assert_equal(bounds[1], (0, 1)) - assert_equal(bounds[2], (0, 0.4)) - assert_equal(bounds[3], (0.98, 1)) + assert_equal(bounds[2], (0, 0.05)) + assert_equal(bounds[3], (0.8, 1)) assert_equal(bounds[4], (0, 1)) backcast = cgarch.backcast(self.resids) w = 0.94 ** np.arange(75) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 45e0ab5829..086060d2a3 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2060,13 +2060,13 @@ def backcast(self, resids): return super(CGARCH, self).backcast(resids) def bounds(self, resids): - return [(0, 1), (0, 1), (0, 0.05), (0.97, 1), (0, 1)] + return [(0, 1), (0, 1), (0, 0.05), (0.8, 1), (0, 1)] def starting_values(self, resids): alphas = [0.08, 0.2] betas = [0.6, 0.4, 0.1] omegas = [np.var(resids)/2, 0.00001] - rhos = [0.991] + rhos = [0.98, 0.8] phis = [0.01, 0.2] combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) llfs = np.ndarray(len(combos)) From 101ecf3aa1c22c48bf46ae8715a03cde07099f81 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 21:37:24 +0300 Subject: [PATCH 83/92] Correct typo in docs --- arch/univariate/mean.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/mean.py b/arch/univariate/mean.py index 054fb40f65..a937b93a44 100644 --- a/arch/univariate/mean.py +++ b/arch/univariate/mean.py @@ -1054,7 +1054,7 @@ class LS(HARX): Notes ----- - The AR-X model is described by + The LS model is described by .. math:: From e13e29b79dba6e22c092878ca8085e83ff1800e7 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 22:26:49 +0300 Subject: [PATCH 84/92] Increase iterations for fit Convergence is difficult for garch models because of the samll values --- arch/univariate/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 9f02d484fa..dc8ac3338a 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -515,7 +515,7 @@ def fit(self, update_freq=1, disp='final', starting_values=None, f_ieqcons = constraint(a, b) xopt = fmin_slsqp(func, sv, f_ieqcons=f_ieqcons, bounds=bounds, - args=args, iter=100, acc=1e-06, iprint=1, + args=args, iter=200, acc=1e-06, iprint=1, full_output=True, epsilon=1.4901161193847656e-08, callback=_callback, disp=disp) From 27ff1a27f451fe4c389cdb59718a9e62ef0e4bd8 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sat, 5 Aug 2017 22:29:43 +0300 Subject: [PATCH 85/92] Modify starting values for cgarch --- arch/tests/univariate/test_volatility.py | 2 +- arch/univariate/volatility.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/tests/univariate/test_volatility.py b/arch/tests/univariate/test_volatility.py index 90971dddf2..64e2e4eaf2 100644 --- a/arch/tests/univariate/test_volatility.py +++ b/arch/tests/univariate/test_volatility.py @@ -100,7 +100,7 @@ def test_cgarch(self): bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) assert_equal(bounds[1], (0, 1)) - assert_equal(bounds[2], (0, 0.05)) + assert_equal(bounds[2], (0, 0.1)) assert_equal(bounds[3], (0.8, 1)) assert_equal(bounds[4], (0, 1)) backcast = cgarch.backcast(self.resids) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index 086060d2a3..d509c1ca65 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2060,13 +2060,13 @@ def backcast(self, resids): return super(CGARCH, self).backcast(resids) def bounds(self, resids): - return [(0, 1), (0, 1), (0, 0.05), (0.8, 1), (0, 1)] + return [(0, 1), (0, 1), (0, 0.1), (0.8, 1), (0, 1)] def starting_values(self, resids): alphas = [0.08, 0.2] - betas = [0.6, 0.4, 0.1] - omegas = [np.var(resids)/2, 0.00001] - rhos = [0.98, 0.8] + betas = [0.6, 0.3, 0.01] + omegas = [np.var(resids)*5, 0.005] + rhos = [0.98, 0.8, 0.7] phis = [0.01, 0.2] combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) llfs = np.ndarray(len(combos)) From 7f2c208b6006c87a4b5148c35036a2ad5d5c8b36 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 6 Aug 2017 06:44:12 +0300 Subject: [PATCH 86/92] Add CGarch example notebook --- .gitignore | 4 +- examples/CGARCH modelling.ipynb | 364 ++++++++++++++++++++++++++++++++ 2 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 examples/CGARCH modelling.ipynb diff --git a/.gitignore b/.gitignore index c1d8a5e503..d59493b76e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ README.rst /totestimports.py *.user /.vs/config/applicationhost.config -/examples/.ipynb_checkpoints/univariate_volatility_modeling-checkpoint.ipynb /local_cythonrecursion.py /.vs/arch/v14/.suo *.pyproj @@ -21,4 +20,5 @@ README.rst /.vs/config/applicationhost.config .vscode/settings.json -.ipynb_checkpoints/Untitled-checkpoint.ipynb +**/*.ipynb_checkpoints/ + diff --git a/examples/CGARCH modelling.ipynb b/examples/CGARCH modelling.ipynb new file mode 100644 index 0000000000..962b0f9cca --- /dev/null +++ b/examples/CGARCH modelling.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# CGARCH modelling" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The component GARCH by Engle and Lee can be specified by the following equations:\n", + "\n", + "$$\n", + "\\sigma^{2}_{t}=q_{t}+g_{t}\\\\\n", + "q_{t}=\\omega + \\rho q_{t-1} + \\phi(r^{2}_{t-1}-\\sigma^{2}_{t-1})\\\\\n", + "g_{t} = \\alpha(r^{2}_{t-1}-q_{t-1})+\\beta g_{t-1}\n", + "$$\n", + "where:\n", + "\n", + "$\\sigma^{2}_{t}$ is the total variance\n", + "\n", + "$q_{t}$ is the long term component and\n", + "\n", + "$g_{t}$ is the short term component\n", + "\n", + "Usually $\\rho$ is meant to be extremely close to one to make the long term component slow moving. The model is accessed in a similar manner to other models in the package but once it is fit, it will have the extra attribute of the longterm component and when forecast there will be an attribute of longterm variance.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get the necessary imports and data" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "from arch.univariate import CGARCH, arch_model\n", + "from pandas_datareader.data import DataReader\n", + "import datetime as dt\n", + "\n", + "\n", + "start = dt.datetime(2006, 2, 8)\n", + "end = dt.datetime(2017, 3, 20)\n", + "\n", + "df = DataReader(\"^DJI\", \"yahoo\", start, end)\n", + "returns = 100 * df[\"Adj Close\"].pct_change()[1:].fillna(value=0)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setup the mean model and fit it" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iteration: 5, Func. Count: 50, Neg. LLF: 3763.870472556907\n", + "Iteration: 10, Func. Count: 95, Neg. LLF: 3656.081158330028\n", + "Iteration: 15, Func. Count: 137, Neg. LLF: 3641.5291274878878\n", + "Iteration: 20, Func. Count: 177, Neg. LLF: 3641.4959764350515\n", + "Iteration: 25, Func. Count: 218, Neg. LLF: 3638.05236416545\n", + "Iteration: 30, Func. Count: 263, Neg. LLF: 3637.531650897108\n", + "Iteration: 35, Func. Count: 308, Neg. LLF: 3636.138624713658\n", + "Iteration: 40, Func. Count: 350, Neg. LLF: 3635.156314955804\n", + "Optimization terminated successfully. (Exit mode 0)\n", + " Current function value: 3635.120117565214\n", + " Iterations: 44\n", + " Function evaluations: 384\n", + " Gradient evaluations: 44\n" + ] + } + ], + "source": [ + "model = arch_model(y=returns, vol=\"cgarch\")\n", + "#alternatively you can specify volatility as model.volatility = CGARCH()\n", + "\n", + "fit_model = model.fit(update_freq=5)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "
Constant Mean - ComponentGARCH Model Results
Dep. Variable: Adj Close R-squared: -0.001
Mean Model: Constant Mean Adj. R-squared: -0.001
Vol Model: ComponentGARCH Log-Likelihood: -3635.12
Distribution: Normal AIC: 7282.24
Method: Maximum Likelihood BIC: 7317.86
No. Observations: 2796
Date: Sun, Aug 06 2017 Df Residuals: 2790
Time: 06:23:03 Df Model: 6
\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "
Mean Model
coef std err t P>|t| 95.0% Conf. Int.
mu 0.0710 1.431e-02 4.966 6.829e-07 [4.300e-02,9.908e-02]
\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "
Volatility Model
coef std err t P>|t| 95.0% Conf. Int.
alpha 0.0813 2.182e-02 3.725 1.951e-04 [3.853e-02, 0.124]
beta 0.8713 2.341e-02 37.220 3.251e-303 [ 0.825, 0.917]
omega 9.6364e-03 4.234e-03 2.276 2.286e-02 [1.337e-03,1.794e-02]
rho 0.9909 4.441e-03 223.141 0.000 [ 0.982, 1.000]
phi 0.0443 2.121e-02 2.089 3.669e-02 [2.741e-03,8.589e-02]
" + ], + "text/plain": [ + "\n", + "\"\"\"\n", + " Constant Mean - ComponentGARCH Model Results \n", + "==============================================================================\n", + "Dep. Variable: Adj Close R-squared: -0.001\n", + "Mean Model: Constant Mean Adj. R-squared: -0.001\n", + "Vol Model: ComponentGARCH Log-Likelihood: -3635.12\n", + "Distribution: Normal AIC: 7282.24\n", + "Method: Maximum Likelihood BIC: 7317.86\n", + " No. Observations: 2796\n", + "Date: Sun, Aug 06 2017 Df Residuals: 2790\n", + "Time: 06:23:03 Df Model: 6\n", + " Mean Model \n", + "============================================================================\n", + " coef std err t P>|t| 95.0% Conf. Int.\n", + "----------------------------------------------------------------------------\n", + "mu 0.0710 1.431e-02 4.966 6.829e-07 [4.300e-02,9.908e-02]\n", + " Volatility Model \n", + "============================================================================\n", + " coef std err t P>|t| 95.0% Conf. Int.\n", + "----------------------------------------------------------------------------\n", + "alpha 0.0813 2.182e-02 3.725 1.951e-04 [3.853e-02, 0.124]\n", + "beta 0.8713 2.341e-02 37.220 3.251e-303 [ 0.825, 0.917]\n", + "omega 9.6364e-03 4.234e-03 2.276 2.286e-02 [1.337e-03,1.794e-02]\n", + "rho 0.9909 4.441e-03 223.141 0.000 [ 0.982, 1.000]\n", + "phi 0.0443 2.121e-02 2.089 3.669e-02 [2.741e-03,8.589e-02]\n", + "============================================================================\n", + "\n", + "Covariance estimator: robust\n", + "\"\"\"" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fit_model.summary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### To view the conditional volatility" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Date\n", + "2006-02-09 0.521270\n", + "2006-02-10 0.489221\n", + "2006-02-13 0.466583\n", + "2006-02-14 0.451774\n", + "2006-02-15 0.595688\n", + "Name: cond_vol, dtype: float64" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "volatility = fit_model.conditional_volatility\n", + "volatility.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Long term component" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Date\n", + "2006-02-09 0.050000\n", + "2006-02-10 0.048228\n", + "2006-02-13 0.049746\n", + "2006-02-14 0.053703\n", + "2006-02-15 0.115318\n", + "Name: Longterm variance, dtype: float64" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "component = fit_model.longterm_variance\n", + "component.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The longterm component must be compared to the total variance not volatlity, therefore we square it." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "total_variance = volatility**2\n", + "total_variance.name = \"Total variance\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## View plots to compare movements of returns and variance" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nVd/5znfkeV5pv5hdjEojAAAAAADK2E//9y0tWN5Q0nNO2GWALj9+4nYf99JLL+muu+7S3LlzlUwm\nNX36dM2YMUNXX321Fi1alK1OSiQSevjhhzVgwACtXr1aBx98sD7/+c+3e97TTz9dM2fO1De/+U1J\n0n333aenn35a1dXV7Z5n4cKFuvPOO1VXV1dwvjvuuENDhgzRli1bVFdXp1NOOUX9+/fXxo0b9ZnP\nfEZXX321LrnkEt12222aOXOmvvvd7+qoo47SBRdcoGQyqS1btujNN9/UQw89pOeff16xWEznn3++\n7rnnHp111lnb/XXrKYRGAAAAAACgW8yZM0ennHKKqqurJUknnXSSnn32WR199NE5+znnNHPmTM2Z\nM0eRSERLlizR2rVr2+1ntP/++2vJkiVatWqVli5dqpEjR2qXXXZRa2tr0fNI0l577VU0MJKkX//6\n13rkkUckSUuXLtX777+vqVOnqrq6Wscee6wkab/99tOzzz4rSXrmmWd0zz33SJJisZgGDBig2bNn\na+7cudlrNDU1abfdduvMl6/bERoBKEuz5i7RQXsP1ajB/Xp6KAAAAECP2pGKoJ525513auPGjZo/\nf75isZhGjRq1zUfHn3rqqXrggQe0ePFinX766ds8T01NTdHzzJ49W//85z/14osvqrq6Woccckj2\nmIqKiux+0WhUyWQy+zr/SWXOOZ133nm68sort/8L0EvQ0whA2WlOpPSDB17X6Te/2NNDAQAAABBw\n6KGH6qGHHlJTU5MaGxv1l7/8RYceeqj69++f8+SyjRs3asSIEYrFYnriiSe0bNmybZ779NNP1z33\n3KMHHnhAp5566g6fZ+PGjRoyZIiqq6v11ltvae7cuds85rDDDss+/S2VSqmhoUFHHnmkZs2ala1s\nWrdunT7++ONtnqs3odIIQNla29jS00MAAAAAEDB9+nSdeeaZ2n///SVJ3/72tzVp0iRJ6elekyZN\n0uc+9zldcsklOv744zVp0iRNnz5dY8eO3ea5p0yZojVr1mjMmDEaMWKEJOnss8/e7vN87nOf0y23\n3KIJEybok5/8pA444IBtHnPjjTfqG9/4hm6++WbFYjHdfPPNmj59ui6//HIdeeSR8jxP8XhcN910\nk3bfffdtnq+3MOdcT4+hXXV1dW7evHk9PQwAIdOcSGncj/+mimhE7151bE8PBwAAAOh2b7/9tsaP\nH9/Tw0AvUOxnwcxecc4Vb+gUwPQ0AGUnM5XYqfeG4gAAAADQ2xEaASgLF93zL42e+VdJUqaAshcX\nUgIAAABAr0doBKAsPPzq8oJ1ZEYAAAAAsOMIjQCULY9SIwAAAADYYYRGAMoWmREAAAAA7DhCIwBl\nh7AIAAAAADqP0AhA6DU0J3p6CAAAAADy1NbWdun5f/Ob32jLli1deo1S+frXv64FCxb09DC2G6ER\ngNB7+YP12WXnnBwtsAEAAICytyOhUSqV6qLRbP2at956qyZMmNDt1+4sQiMAoWfWtuw5pqcBAAAA\nvdXixYt1+OGHa/LkyTriiCP08ccfS5LOPfdcXXjhhTrooIM0ZswY3X///ZIkz/P0ne98R+PGjdNR\nRx2l4447Tvfff7+uv/56LV++XIcddpgOO+wwSdI//vEPHXjggZo2bZpOO+00NTY2SpJGjx6t//iP\n/9C0adN03333acaMGbr44otVV1en8ePHa+7cufrCF76gsWPH6rLLLisY80033aR///d/z76+/fbb\ndcEFF0iSTjrpJO23336aOHGibrnlluw+tbW1+v73v68pU6bohRde0IwZMzRv3jxJ0re//W3V1dVp\n4sSJuvzyy7PHjB49WpdffrmmTZumSZMmaeHChZKkxsZGffWrX9WkSZM0efJkPfDAA1t9v6UUK/kZ\nAaCbBUOjRMrruYEAAAAAvdHjM6WVb5T2nCMnScdevd2Hfe9739M555yjc845R7fddpsuvPBCPfzw\nw5KkFStWaM6cOVq4cKFOOOEEnXrqqXrwwQe1ePFiLViwQKtXr9b48eN13nnn6cILL9S1116rp59+\nWsOGDdPatWv1s5/9TLNnz1ZNTY1+/vOf69prr9VPfvITSdLQoUM1f/58SekQqKKiQvPmzdN1112n\nE088Ua+88oqGDBmivfbaSxdffLGGDh2aHfMpp5yiAw88UL/85S8lSffee69+9KMfSZJuu+02DRky\nRE1NTdp///11yimnaOjQodq8ebMOOOAA/epXvyr4Glx11VUaMmSIUqmUjjjiCL3++uuaPHmyJGnY\nsGGaP3++fve73+maa67RrbfeqiuvvFIDBw7UG2+kv4cbNmzY5vstFUIjAKFngdQo5TE5DQAAAOit\nXnjhBT344IOSpLPPPls/+MEPsttOOukkRSIRTZgwQatWrZIkzZkzR6eddpoikYhGjhyZrSrK9+KL\n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\nA/g2/FSNu823HNPl8erip77W+ixn2sfosCB98LNh6hkbqt17crVmW4ZuXVCjS0ck6IGTjAL3rFFe\n+mo9XnCChiUE6orB4QrI+MY5gGrLVVKQrf/ujtWw6x7RhAGJ+npbgYqr6tQ7PrLxee7fJUy1hbu0\n23bVF7eepvmb8vSzCcc1vSBspUVb8/Xnd9crt6y2scvWt3+aosSDzFTW0VlrZa38+lzi6JBTWq2V\nu0oUHRakk/rG+6UPfINP1u/RTa+n6peT+ur1b3artNqluIhgFVe5FBMerNJql3p0DldGUfUhj69l\nrdXVLyzX0u3OOfG+C4fomvqwYlVGiUamxPq8zl9askP3frBRl41J0ZzUTN06dYBm1t/FbG8aphXe\n/2+YvylXN7zqvJ/+bEIf5ZXX6v012UqMDtOesho9dfVovbMyU2l5FZpz08lKiA712fa/vkzTw59t\n1fPXjdXUwQe5O+n1Sp46PfPFWj240Ck1P7lvvO69YLD6hRSraPd6/eTNbVpj+2lEj1i9+bMTWwwb\nM4qqdPULyxUVGqR//mik1maW6Pdz1kqSnr9urB6fv7XxvaY5IYEBqvN4dff5g/WTUw5crbXvPh+f\nn6YbTu2jQd07/k2BtZklevqr7fr4ANOmBwYYTRqYqAcuGaqiyjpNe2zvoKw/OaW3Xv56Z7OPu+6k\nXrr3wqbVvPd9sFEvLtmhIUmdlJ5fqWqXR9FhQXrsRyN1w6srFBhgNHvGiRrb2z/j4qzcXawfPbtM\nx3WJ0lPXjNajn23VxpwyDUuO0XtrnDFYhiR10sBu0fpyc56GJsXo4lHJOrlfvLp1ClNptUvj/jpf\nXWNCGyso19x9pjqFBWljTtkBJ/cor3Fp0sNfqbjKpRsn9NGtUwdo0j++Unbp3s9oz1wzWtOGOlWa\nt/9vrWavyNAT00fpzCFdFRoUqDq3V4P//IncXqsPfnWqhkaWSkU7tDQvSFfNK9Z/bhiva190Krgf\nuqCfftSvvquZq0oKDHVuJpbnOBdNlQV6fmmGdsSdqp9fcqYm/uOrJu1NjjL6dHqcojz1lYJ5G6XK\nAr2+yaX7ck/Wh7dOVb/Elgfv9XitfvF6qj7bmKu4iGAt/MMkdQoJlPI3OUMxhEZLMsratVV/XlCk\n+d6mXfYfufA4XRSfpTdTs/R2QW/tyclSnjdaXvm+d6y48wx1iQpVjcujHz33jdZklGhIUifde/7x\n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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "% matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "plt.rcParams[\"figure.figsize\"] = 20, 15\n", + "fig, ax = plt.subplots(2, sharex=True)\n", + "\n", + "total_variance.plot(legend=True, ax=ax[0])\n", + "component.plot(legend=True, ax=ax[0])\n", + "ax[0].set_title(\"Total variance and long term variance\")\n", + "# ax[0].set_ylim([0, 0.01])\n", + "\n", + "returns.plot(title=\"Returns\", legend=True, ax=ax[1])\n", + "plt.legend(loc=\"upper right\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From eed02f6f3501013b8cd892a0f9ad2df367b90740 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 6 Aug 2017 08:53:03 +0300 Subject: [PATCH 87/92] Modifycgarchbounds It turns out that not scaling my data was the reason the solver could not find a direction to descend to.This could not be fixed by tweaking starting values or bounds. Now bunds have been returned to their text book versions. --- arch/tests/univariate/test_volatility.py | 4 ++-- arch/univariate/volatility.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/tests/univariate/test_volatility.py b/arch/tests/univariate/test_volatility.py index 64e2e4eaf2..70bfe77b35 100644 --- a/arch/tests/univariate/test_volatility.py +++ b/arch/tests/univariate/test_volatility.py @@ -100,8 +100,8 @@ def test_cgarch(self): bounds = cgarch.bounds(self.resids) assert_equal(bounds[0], (0, 1)) assert_equal(bounds[1], (0, 1)) - assert_equal(bounds[2], (0, 0.1)) - assert_equal(bounds[3], (0.8, 1)) + assert_equal(bounds[2], (0, 1)) + assert_equal(bounds[3], (0.79, 1)) assert_equal(bounds[4], (0, 1)) backcast = cgarch.backcast(self.resids) w = 0.94 ** np.arange(75) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index d509c1ca65..aca9fd40dd 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2060,12 +2060,12 @@ def backcast(self, resids): return super(CGARCH, self).backcast(resids) def bounds(self, resids): - return [(0, 1), (0, 1), (0, 0.1), (0.8, 1), (0, 1)] + return [(0, 1), (0, 1), (0, 1), (0.79, 1), (0, 1)] def starting_values(self, resids): alphas = [0.08, 0.2] betas = [0.6, 0.3, 0.01] - omegas = [np.var(resids)*5, 0.005] + omegas = [np.var(resids), 0.1] rhos = [0.98, 0.8, 0.7] phis = [0.01, 0.2] combos = list(itertools.product(*[alphas, betas, omegas, rhos, phis])) From feef7e1e41cf05283c937fb76a44886005c57108 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 6 Aug 2017 08:53:27 +0300 Subject: [PATCH 88/92] Change back iter parameter to 100 --- arch/univariate/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index dc8ac3338a..9f02d484fa 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -515,7 +515,7 @@ def fit(self, update_freq=1, disp='final', starting_values=None, f_ieqcons = constraint(a, b) xopt = fmin_slsqp(func, sv, f_ieqcons=f_ieqcons, bounds=bounds, - args=args, iter=200, acc=1e-06, iprint=1, + args=args, iter=100, acc=1e-06, iprint=1, full_output=True, epsilon=1.4901161193847656e-08, callback=_callback, disp=disp) From 16514b7bd5cc17be98139e2b7568edc92dea5c64 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 6 Aug 2017 15:13:10 +0300 Subject: [PATCH 89/92] Modify docs for cgarch --- arch/univariate/base.py | 2 +- arch/univariate/volatility.py | 41 ++++++++++++++++++++------- doc/source/changes/4.0.txt | 2 ++ doc/source/univariate/forecasting.rst | 2 +- doc/source/univariate/univariate.rst | 1 + 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/arch/univariate/base.py b/arch/univariate/base.py index 9f02d484fa..4eb21e196b 100644 --- a/arch/univariate/base.py +++ b/arch/univariate/base.py @@ -1328,7 +1328,7 @@ class ARCHModelResult(ARCHModelFixedResult): resid : {array, Series} nobs element array containing model residuals model : ARCHModel - Model instance used to produce the fit + Model instance used to produce the fit. """ def __init__(self, params, param_cov, r2, resid, volatility, longterm_var, diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index aca9fd40dd..c905a96450 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -435,6 +435,11 @@ def compute_variance(self, parameters, resids, sigma2, backcast, Value to use when initializing ARCH recursion var_bounds : array Array containing columns of lower and upper bounds + + Returns + ------- + sigma : array + array of computed variances. """ raise NotImplementedError('Must be overridden') # pragma: no cover @@ -2008,15 +2013,12 @@ class CGARCH(GARCH): r""" Component GARCH model. A restricted version of GARCH(2,2) by Engle and Lee. Decomposes volatility into its long term and short term components. - - Parameters - ---------- - All parameters are estimated + No parameters needed Attributes ---------- num_params : int - The number of parameters in the model + The number of parameters in the model Examples -------- @@ -2029,10 +2031,9 @@ class CGARCH(GARCH): .. math:: - \sigma^{2}_{t}=q_{t}+g_{t} - q_{t}=\omega + \rho q_{t-1} + \phi(r^{2}_{t-1}-\sigma^{2}_{t-1}) - g_{t} = \alpha(r^{2}_{t-1}-q_{t-1})+\beta g_{t-1} - + \sigma^{2}_{t}=q_{t}+g_{t}\\ + q_{t}=\omega + \rho q_{t-1} + \phi(r^{2}_{t-1}-\sigma^{2}_{t-1})\\ + g_{t} = \alpha(r^{2}_{t-1}-q_{t-1})+\beta g_{t-1}\\. """ def __init__(self): @@ -2080,7 +2081,27 @@ def starting_values(self, resids): def compute_variance(self, parameters, resids, sigma2, backcast, var_bounds): - # this returns both sigma and long term variance + """ + Compute the variance for the ARCH model + + Parameters + ---------- + resids : array + Vector of mean zero residuals + sigma2 : array + Array with same size as resids to store the conditional variance + backcast : float + Value to use when initializing ARCH recursion + var_bounds : array + Array containing columns of lower and upper bounds + + Returns + ------- + sigma : array + array of computed variances. + q2 : array + array of computed longterm variances. + """ fresids = resids**2 nobs = len(fresids) g2, q2 = np.ndarray(nobs*2).reshape(2, nobs) diff --git a/doc/source/changes/4.0.txt b/doc/source/changes/4.0.txt index 7e99ed811c..158d058207 100644 --- a/doc/source/changes/4.0.txt +++ b/doc/source/changes/4.0.txt @@ -8,3 +8,5 @@ Changes since 4.0 a ``ZeroMean`` variance process. - Fixed a bug that prevented ``fix`` from being used with a new model (:issue:`156`) - Added ``first_obs`` and ``last_obs`` parameters to ``fix`` to mimic ``fit`` +- Added Component GARCH process which decomposes volatility into long run and short run components. + The model comes with an extra ``longterm_var`` attribute when fit. diff --git a/doc/source/univariate/forecasting.rst b/doc/source/univariate/forecasting.rst index 01164337bd..2e650163fd 100644 --- a/doc/source/univariate/forecasting.rst +++ b/doc/source/univariate/forecasting.rst @@ -186,7 +186,7 @@ The four core attributes are This will differ from ``variance`` whenever the model has dynamics (e.g. an AR model) for horizons larger than 1. * ``longterm_component`` - The forecast longterm conditional variance of residuals. - This is present only if the volatility process supports integer + This is present only if the volatility process supports it (e.g. ``CGARCH process``) Each attribute contains a ``DataFrame`` with a common structure. diff --git a/doc/source/univariate/univariate.rst b/doc/source/univariate/univariate.rst index c8ffd3a9ac..c2b1c587f8 100644 --- a/doc/source/univariate/univariate.rst +++ b/doc/source/univariate/univariate.rst @@ -12,6 +12,7 @@ Univariate Volatility Models Forecasting Examples Mean Models Volatility Processes + CGARCH Model Using the Fixed Variance Process Distributions Background and References From bbff084414260f590b3786107c02cad2d617d738 Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 6 Aug 2017 15:19:12 +0300 Subject: [PATCH 90/92] Include cgarch in list of volatility models --- examples/univariate_volatility_modeling.ipynb | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/univariate_volatility_modeling.ipynb b/examples/univariate_volatility_modeling.ipynb index 3d153bf108..7668bf6498 100644 --- a/examples/univariate_volatility_modeling.ipynb +++ b/examples/univariate_volatility_modeling.ipynb @@ -540,6 +540,7 @@ " * ARCH (`ARCH`)\n", " * GARCH (`GARCH`)\n", " * GJR-GARCH (`GARCH` using `o` argument) \n", + " * CGARCH (`CGARCH`)\n", " * TARCH/ZARCH (`GARCH` using `power` argument set to `1`)\n", " * Power GARCH and Asymmetric Power GARCH (`GARCH` using `power`)\n", " * Heterogeneous ARCH (`HARCH`)\n", From 0df450122929af78c1a8ba584b406c242d65c04c Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 6 Aug 2017 15:28:32 +0300 Subject: [PATCH 91/92] Remove whitespace in blankline --- arch/univariate/volatility.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index c905a96450..ef8b111b2f 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -435,7 +435,7 @@ def compute_variance(self, parameters, resids, sigma2, backcast, Value to use when initializing ARCH recursion var_bounds : array Array containing columns of lower and upper bounds - + Returns ------- sigma : array @@ -2094,7 +2094,7 @@ def compute_variance(self, parameters, resids, sigma2, backcast, Value to use when initializing ARCH recursion var_bounds : array Array containing columns of lower and upper bounds - + Returns ------- sigma : array From 5ad0aae4524df36de62f173b8320e6933484feff Mon Sep 17 00:00:00 2001 From: Richard MM Date: Sun, 24 Sep 2017 20:54:19 +0300 Subject: [PATCH 92/92] Correct error in cgarch simulation --- arch/tests/univariate/test_volatility.py | 2 +- arch/univariate/volatility.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/tests/univariate/test_volatility.py b/arch/tests/univariate/test_volatility.py index 70bfe77b35..48cc38330e 100644 --- a/arch/tests/univariate/test_volatility.py +++ b/arch/tests/univariate/test_volatility.py @@ -153,7 +153,7 @@ def test_cgarch(self): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) sigma2[i] = g2[i] + q2[i] - data[i] = e[i] * (np.sqrt(sigma2[i])) ** 2 + data[i] = e[i] * (np.sqrt(sigma2[i])) data = data[500:] sigma2 = sigma2[500:] diff --git a/arch/univariate/volatility.py b/arch/univariate/volatility.py index ef8b111b2f..2cf64b3b11 100644 --- a/arch/univariate/volatility.py +++ b/arch/univariate/volatility.py @@ -2152,7 +2152,7 @@ def simulate(self, parameters, nobs, rng, burn=500, initial_value=None): g2[i] = alpha * (data[i - 1]**2 - q2[i - 1]) + beta * g2[i - 1] q2[i] = omega + rho * q2[i - 1] + phi * (data[i - 1]**2 - sigma2[i - 1]) sigma2[i] = g2[i] + q2[i] - data[i] = errors[i] * (np.sqrt(sigma2[i])) ** 2 + data[i] = errors[i] * (np.sqrt(sigma2[i])) return data[burn:], sigma2[burn:] def _analytic_forecast(self, parameters, resids, backcast, var_bounds, start, horizon):