Пример #1
0
    def test_from_theta_shomo(self):
        """Test init from theta for spatial specification."""

        nstocks = 4
        groups = [[(0, 1), (2, 3)]]
        ncat = len(groups)
        alpha, beta, gamma = .01, .16, .09
        # A, B, C - n x n matrices
        avecs = np.ones((ncat+1, nstocks)) * alpha**.5
        bvecs = np.ones((ncat+1, nstocks)) * beta**.5
        dvecs = np.vstack([np.ones((1, nstocks)),
                           np.ones((ncat, nstocks)) * gamma**.5])

        param = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs,
                                       groups=groups)

        restriction = 'shomo'
        target = None
        theta = [avecs[:, 0], bvecs[:, 0], dvecs[0], dvecs[1:, 0]]
        theta = np.concatenate(theta)
        param_new = ParamSpatial.from_theta(theta=theta, groups=groups,
                                            restriction=restriction,
                                            target=target)

        npt.assert_array_equal(param.amat, param_new.amat)
        npt.assert_array_equal(param.bmat, param_new.bmat)
        npt.assert_array_equal(param.cmat, param_new.cmat)
        npt.assert_array_equal(param.avecs, param_new.avecs)
        npt.assert_array_equal(param.bvecs, param_new.bvecs)
        npt.assert_array_equal(param.dvecs, param_new.dvecs)

        target = param.get_uvar()
        theta = [avecs[:, 0], bvecs[:, 0]]
        theta = np.concatenate(theta)
        cmat = param.find_cmat(amat=param.amat, bmat=param.bmat, target=target)
        param_new = ParamSpatial.from_theta(theta=theta, groups=groups,
                                            restriction=restriction,
                                            target=target)

        npt.assert_array_equal(param.amat, param_new.amat)
        npt.assert_array_equal(param.bmat, param_new.bmat)
        npt.assert_array_equal(cmat, param_new.cmat)
        npt.assert_array_equal(param.avecs, param_new.avecs)
        npt.assert_array_equal(param.bvecs, param_new.bvecs)
#        npt.assert_array_equal(None, param_new.dvecs)

        cfree = True
        theta = [avecs[:, 0], bvecs[:, 0],
                 param.cmat[np.tril_indices(nstocks)]]
        theta = np.concatenate(theta)
        param_new = ParamSpatial.from_theta(theta=theta, groups=groups,
                                            restriction=restriction,
                                            cfree=cfree)

        npt.assert_array_equal(param.amat, param_new.amat)
        npt.assert_array_equal(param.bmat, param_new.bmat)
        npt.assert_array_equal(np.tril(param.cmat), param_new.cmat)
        npt.assert_array_equal(param.avecs, param_new.avecs)
        npt.assert_array_equal(param.bvecs, param_new.bvecs)
        npt.assert_array_equal(None, param_new.dvecs)
Пример #2
0
    def test_from_theta_ghomo_special(self):
        """Test group init from theta for spatial specification."""

        nstocks = 4
        groups = [[(0, 1, 2, 3)]]
        ncat = len(groups)
        alpha = [.01, .02, .03, .04, .05]
        beta = [.07, .08, .09, .1, .11]
        delta = [.13, .14, .15, .16, .17]
        # A, B, C - n x n matrices
        avecs = np.ones((ncat+1, nstocks))
        bvecs = np.ones((ncat+1, nstocks))
        dvecs = np.ones((ncat+1, nstocks))
        avecs[0] = alpha[:4]
        avecs[1] *= alpha[-1]
        bvecs[0] = beta[:4]
        bvecs[1] *= beta[-1]
        dvecs[0] = delta[:4]
        dvecs[1] *= delta[-1]

        param = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs,
                                       groups=groups)

        target = param.get_uvar()
        theta = np.concatenate([alpha, beta])
        cmat = param.find_cmat(amat=param.amat, bmat=param.bmat, target=target)
        uvar = param.find_stationary_var(amat=param.amat, bmat=param.bmat,
                                         cmat=cmat)
        npt.assert_array_almost_equal(target, uvar)

        restriction = 'h**o'
        param_homo = ParamSpatial.from_theta(theta=theta, groups=groups,
                                             restriction=restriction,
                                             target=target)
        theta_homo = param_homo.get_theta(restriction=restriction,
                                          use_target=False)

        restriction = 'ghomo'
        param_ghomo = ParamSpatial.from_theta(theta=theta, groups=groups,
                                              restriction=restriction,
                                              target=target)
        theta_ghomo = param_ghomo.get_theta(restriction=restriction,
                                            use_target=False)

        npt.assert_array_almost_equal(cmat, param.cmat)
        npt.assert_array_almost_equal(theta_ghomo, theta_homo, decimal=3)
        for param_check in [param_homo, param_ghomo]:
            npt.assert_array_equal(param.avecs, param_check.avecs)
            npt.assert_array_equal(param.bvecs, param_check.bvecs)
            npt.assert_array_equal(param.amat, param_check.amat)
            npt.assert_array_equal(param.bmat, param_check.bmat)
            npt.assert_array_equal(cmat, param_check.cmat)
Пример #3
0
    def test_from_theta_ghomo(self):
        """Test group init from theta for spatial specification."""

        nstocks = 4
        groups = [[(0, 1), (2, 3)]]
        ncat = len(groups)
        alpha = [.01, .02, .03, .04, .05, .06]
        beta = [.07, .08, .09, .1, .11, .12]
        delta = [.13, .14, .15, .16, .17, .18]
        # A, B, C - n x n matrices
        avecs = np.ones((ncat+1, nstocks))
        bvecs = np.ones((ncat+1, nstocks))
        dvecs = np.ones((ncat+1, nstocks))
        avecs[0] = alpha[:4]
        avecs[1, :2] *= alpha[-2]
        avecs[1, 2:] *= alpha[-1]
        bvecs[0] = beta[:4]
        bvecs[1, :2] *= beta[-2]
        bvecs[1, 2:] *= beta[-1]
        dvecs[0] = delta[:4]
        dvecs[1, :2] *= delta[-2]
        dvecs[1, 2:] *= delta[-1]

        param = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs,
                                       groups=groups)

        restriction = 'ghomo'
        target = param.get_uvar()
        theta = np.concatenate([alpha, beta])
        cmat = param.find_cmat(amat=param.amat, bmat=param.bmat, target=target)
        uvar = param.find_stationary_var(amat=param.amat, bmat=param.bmat,
                                         cmat=cmat)
        npt.assert_array_almost_equal(target, uvar)

        param_new = ParamSpatial.from_theta(theta=theta, groups=groups,
                                            restriction=restriction,
                                            target=target)

        npt.assert_array_equal(param.avecs, param_new.avecs)
        npt.assert_array_equal(param.bvecs, param_new.bvecs)
#        npt.assert_array_equal(None, param_new.dvecs)
        npt.assert_array_equal(param.amat, param_new.amat)
        npt.assert_array_equal(param.bmat, param_new.bmat)
        npt.assert_array_equal(cmat, param_new.cmat)
        npt.assert_array_almost_equal(cmat, param.cmat)
Пример #4
0
    def likelihood(self,
                   theta,
                   model='standard',
                   restriction='full',
                   target=None,
                   cfree=False,
                   groups=None,
                   cython=True,
                   use_penalty=False):
        """Compute the conditional log-likelihood function.

        Parameters
        ----------
        theta : 1dim array
            Dimension depends on the model restriction
        model : str
            Specific model to estimate.

            Must be
                - 'standard'
                - 'spatial'

        restriction : str
            Restriction on parameters.

            Must be
                - 'full'
                - 'diagonal'
                - 'scalar'

        target : (nstocks, nstocks) array
            Estimate of unconditional variance matrix
        cfree : bool
            Whether to leave C matrix free (True) or not (False)
        groups : list of lists of tuples
            Encoded groups of items
        cython : bool
            Whether to use Cython optimizations (True) or not (False)
        use_penalty : bool
            Whether to include penalty term in the likelihood

        Returns
        -------
        float
            The value of the minus log-likelihood function.
            If some regularity conditions are violated, then it returns
            some obscene number.

        """
        try:
            if model == 'standard':
                param = ParamStandard.from_theta(theta=theta,
                                                 target=target,
                                                 nstocks=self.innov.shape[1],
                                                 restriction=restriction)
            elif model == 'spatial':
                param = ParamSpatial.from_theta(theta=theta,
                                                target=target,
                                                cfree=cfree,
                                                restriction=restriction,
                                                groups=groups)
            else:
                raise NotImplementedError('The model is not implemented!')

            # TODO: Temporary hack to exclude errors in optimization
            if isinstance(param, np.ndarray):
                return 1e10
            if param.constraint() >= 1:
                return 1e10
            # if param.uvar_bad():
            #     return 1e10

            args = [self.hvar, self.innov, param.amat, param.bmat, param.cmat]

            penalty = param.penalty() if use_penalty else 0

            if cython:
                filter_var(*args)
                nstocks = self.innov.shape[1]
                idxl = np.tril_indices(nstocks)
                idxu = np.triu_indices(nstocks)
                self.hvar[:, idxu[0], idxu[1]] = self.hvar[:, idxl[0], idxl[1]]
                return likelihood_gauss(self.hvar, self.innov) + penalty
            else:
                filter_var_python(*args)
                return likelihood_python(self.hvar, self.innov) + penalty
        except:
            return 1e10
Пример #5
0
    def estimate(self,
                 param_start=None,
                 restriction='scalar',
                 cfree=False,
                 use_target=False,
                 model='standard',
                 groups=None,
                 method='SLSQP',
                 cython=True,
                 use_penalty=False):
        """Estimate parameters of the BEKK model.

        Parameters
        ----------
        param_start : ParamStandard or ParamSpatial instance
            Starting parameters. See Notes for more details.
        model : str
            Specific model to estimate.

            Must be
                - 'standard'
                - 'spatial'

        restriction : str
            Restriction on parameters.

            Must be
                - 'full'
                - 'diagonal'
                - 'group' (only applicable with 'spatial' model)
                - 'scalar'

        use_target : bool
            Whether to use variance targeting (True) or not (False)
        cfree : bool
            Whether to leave C matrix free (True) or not (False)
        groups : list of lists of tuples
            Encoded groups of items
        method : str
            Optimization method. See scipy.optimize.minimize
        cython : bool
            Whether to use Cython optimizations (True) or not (False)
        use_penalty : bool
            Whether to include penalty term in the likelihood

        Returns
        -------
        BEKKResults instance
            Estimation results object

        Notes
        -----

        If no param_start is given, the program will estimate parameters in
        the order 'from simple to more complicated' (from scalar to diagonal
        to full) while always using variance targeting.

        """
        # Start timer for the whole optimization
        time_start = time.time()

        # Check for incompatible inputs
        if use_target and cfree:
            raise ValueError('use_target and cfree are incompatible!')
#        if (groups is not None) and (model != 'spatial'):
#            raise ValueError('The model is incompatible with weights!')
# Update default settings
        nobs, nstocks = self.innov.shape
        var_target = estimate_uvar(self.innov)
        self.hvar = np.zeros((nobs, nstocks, nstocks), dtype=float)
        self.hvar[0] = var_target.copy()

        # Check for existence of initial guess among arguments.
        # Otherwise, initialize.
        if param_start is None:
            common = {
                'restriction': restriction,
                'method': method,
                'use_penalty': use_penalty,
                'use_target': use_target
            }
            if model == 'standard':
                param_start = self.init_param_standard(**common)
            elif model == 'spatial':
                param_start = self.init_param_spatial(groups=groups,
                                                      cfree=cfree,
                                                      **common)
            else:
                raise NotImplementedError('The model is not implemented!')

        # Get vector of parameters to start optimization
        theta_start = param_start.get_theta(restriction=restriction,
                                            use_target=use_target,
                                            cfree=cfree)
        if use_target:
            target = var_target
        else:
            target = None

        # Optimization options
        options = {'disp': False, 'maxiter': int(1e6)}
        if method == 'Nelder-Mead':
            options['maxfev'] = 3000
        # Likelihood arguments
        kwargs = {
            'model': model,
            'target': target,
            'cfree': cfree,
            'restriction': restriction,
            'groups': groups,
            'cython': cython,
            'use_penalty': use_penalty
        }
        # Likelihood function
        likelihood = partial(self.likelihood, **kwargs)

        # Run optimization
        if method == 'basin':
            opt_out = basinhopping(likelihood,
                                   theta_start,
                                   niter=100,
                                   disp=options['disp'],
                                   minimizer_kwargs={'method': 'Nelder-Mead'})
        else:
            opt_out = minimize(likelihood,
                               theta_start,
                               method=method,
                               options=options)
        # How much time did it take in minutes?
        time_delta = time.time() - time_start

        # Store optimal parameters in the corresponding class
        if model == 'standard':
            param_final = ParamStandard.from_theta(theta=opt_out.x,
                                                   restriction=restriction,
                                                   target=target,
                                                   nstocks=nstocks)
        elif model == 'spatial':
            param_final = ParamSpatial.from_theta(theta=opt_out.x,
                                                  restriction=restriction,
                                                  target=target,
                                                  cfree=cfree,
                                                  groups=groups)
        else:
            raise NotImplementedError('The model is not implemented!')

        return BEKKResults(innov=self.innov,
                           hvar=self.hvar,
                           cython=cython,
                           var_target=var_target,
                           model=model,
                           method=method,
                           use_target=use_target,
                           cfree=cfree,
                           restriction=restriction,
                           param_start=param_start,
                           param_final=param_final,
                           time_delta=time_delta,
                           opt_out=opt_out)
Пример #6
0
    def likelihood(self, theta, model='standard', restriction='full',
                   target=None, cfree=False, groups=None, cython=True,
                   use_penalty=False):
        """Compute the conditional log-likelihood function.

        Parameters
        ----------
        theta : 1dim array
            Dimension depends on the model restriction
        model : str
            Specific model to estimate.

            Must be
                - 'standard'
                - 'spatial'

        restriction : str
            Restriction on parameters.

            Must be
                - 'full'
                - 'diagonal'
                - 'scalar'

        target : (nstocks, nstocks) array
            Estimate of unconditional variance matrix
        cfree : bool
            Whether to leave C matrix free (True) or not (False)
        groups : list of lists of tuples
            Encoded groups of items
        cython : bool
            Whether to use Cython optimizations (True) or not (False)
        use_penalty : bool
            Whether to include penalty term in the likelihood

        Returns
        -------
        float
            The value of the minus log-likelihood function.
            If some regularity conditions are violated, then it returns
            some obscene number.

        """
        try:
            if model == 'standard':
                param = ParamStandard.from_theta(theta=theta, target=target,
                                                 nstocks=self.innov.shape[1],
                                                 restriction=restriction)
            elif model == 'spatial':
                param = ParamSpatial.from_theta(theta=theta, target=target,
                                                cfree=cfree,
                                                restriction=restriction,
                                                groups=groups)
            else:
                raise NotImplementedError('The model is not implemented!')

            # TODO: Temporary hack to exclude errors in optimization
            if isinstance(param, np.ndarray):
                return 1e10
            if param.constraint() >= 1:
                return 1e10
            # if param.uvar_bad():
            #     return 1e10

            args = [self.hvar, self.innov, param.amat, param.bmat, param.cmat]

            penalty = param.penalty() if use_penalty else 0

            if cython:
                filter_var(*args)
                nstocks = self.innov.shape[1]
                idxl = np.tril_indices(nstocks)
                idxu = np.triu_indices(nstocks)
                self.hvar[:, idxu[0], idxu[1]] = self.hvar[:, idxl[0], idxl[1]]
                return likelihood_gauss(self.hvar, self.innov) + penalty
            else:
                filter_var_python(*args)
                return likelihood_python(self.hvar, self.innov) + penalty
        except:
            return 1e10
Пример #7
0
    def estimate(self, param_start=None, restriction='scalar', cfree=False,
                 use_target=False, model='standard', groups=None,
                 method='SLSQP', cython=True, use_penalty=False):
        """Estimate parameters of the BEKK model.

        Parameters
        ----------
        param_start : ParamStandard or ParamSpatial instance
            Starting parameters. See Notes for more details.
        model : str
            Specific model to estimate.

            Must be
                - 'standard'
                - 'spatial'

        restriction : str
            Restriction on parameters.

            Must be
                - 'full'
                - 'diagonal'
                - 'group' (only applicable with 'spatial' model)
                - 'scalar'

        use_target : bool
            Whether to use variance targeting (True) or not (False)
        cfree : bool
            Whether to leave C matrix free (True) or not (False)
        groups : list of lists of tuples
            Encoded groups of items
        method : str
            Optimization method. See scipy.optimize.minimize
        cython : bool
            Whether to use Cython optimizations (True) or not (False)
        use_penalty : bool
            Whether to include penalty term in the likelihood

        Returns
        -------
        BEKKResults instance
            Estimation results object

        Notes
        -----

        If no param_start is given, the program will estimate parameters in
        the order 'from simple to more complicated' (from scalar to diagonal
        to full) while always using variance targeting.

        """
        # Start timer for the whole optimization
        time_start = time.time()

        # Check for incompatible inputs
        if use_target and cfree:
            raise ValueError('use_target and cfree are incompatible!')
#        if (groups is not None) and (model != 'spatial'):
#            raise ValueError('The model is incompatible with weights!')
        # Update default settings
        nobs, nstocks = self.innov.shape
        var_target = estimate_uvar(self.innov)
        self.hvar = np.zeros((nobs, nstocks, nstocks), dtype=float)
        self.hvar[0] = var_target.copy()

        # Check for existence of initial guess among arguments.
        # Otherwise, initialize.
        if param_start is None:
            common = {'restriction': restriction, 'method': method,
                      'use_penalty': use_penalty, 'use_target': use_target}
            if model == 'standard':
                param_start = self.init_param_standard(**common)
            elif model == 'spatial':
                param_start = self.init_param_spatial(groups=groups,
                                                      cfree=cfree, **common)
            else:
                raise NotImplementedError('The model is not implemented!')

        # Get vector of parameters to start optimization
        theta_start = param_start.get_theta(restriction=restriction,
                                            use_target=use_target, cfree=cfree)
        if use_target:
            target = var_target
        else:
            target = None

        # Optimization options
        options = {'disp': False, 'maxiter': int(1e6)}
        if method == 'Nelder-Mead':
            options['maxfev'] = 3000
        # Likelihood arguments
        kwargs = {'model': model, 'target': target, 'cfree': cfree,
                  'restriction': restriction, 'groups': groups,
                  'cython': cython, 'use_penalty': use_penalty}
        # Likelihood function
        likelihood = partial(self.likelihood, **kwargs)

        # Run optimization
        if method == 'basin':
            opt_out = basinhopping(likelihood, theta_start, niter=100,
                                   disp=options['disp'],
                                   minimizer_kwargs={'method': 'Nelder-Mead'})
        else:
            opt_out = minimize(likelihood, theta_start,
                               method=method, options=options)
        # How much time did it take in minutes?
        time_delta = time.time() - time_start

        # Store optimal parameters in the corresponding class
        if model == 'standard':
            param_final = ParamStandard.from_theta(theta=opt_out.x,
                                                   restriction=restriction,
                                                   target=target,
                                                   nstocks=nstocks)
        elif model == 'spatial':
            param_final = ParamSpatial.from_theta(theta=opt_out.x,
                                                  restriction=restriction,
                                                  target=target, cfree=cfree,
                                                  groups=groups)
        else:
            raise NotImplementedError('The model is not implemented!')

        return BEKKResults(innov=self.innov, hvar=self.hvar, cython=cython,
                           var_target=var_target, model=model, method=method,
                           use_target=use_target, cfree=cfree,
                           restriction=restriction,
                           param_start=param_start, param_final=param_final,
                           time_delta=time_delta, opt_out=opt_out)