def test_targeting(self): """Test targeting.""" 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 = 'h**o' target = param.get_uvar() param = ParamSpatial.from_abt(avecs=avecs, bvecs=bvecs, groups=groups, target=target, restriction=restriction, solve_dvecs=True) param = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=param.dvecs, groups=groups)
def test_from_abcmat(self): """Test spatial specification.""" nstocks = 4 groups = [[(0, 1), (2, 3)]] weights = ParamSpatial.get_weight(groups) ncat = 1 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]) amat = np.diag(avecs[0]) + np.diag(avecs[0]).dot(weights[0]) bmat = np.diag(bvecs[0]) + np.diag(bvecs[0]).dot(weights[0]) dmat = np.eye(nstocks) - np.diag(dvecs[1]).dot(weights[0]) dmat_inv = scl.inv(dmat) cmat = dmat_inv.dot(np.diag(dvecs[0])).dot(dmat_inv) param = ParamSpatial.from_abcmat(avecs=avecs, bvecs=bvecs, cmat=cmat, groups=groups) npt.assert_array_equal(amat, param.amat) npt.assert_array_equal(bmat, param.bmat) npt.assert_array_equal(cmat, param.cmat) npt.assert_array_equal(avecs, param.avecs) npt.assert_array_equal(bvecs, param.bvecs) npt.assert_array_equal(None, param.dvecs) npt.assert_array_equal(weights, param.weights)
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)
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)
def try_interative_estimation_spatial(): """Try estimating parameters from simple to more complicated model. """ restriction = 'full' nobs = 2000 groups = [[(0, 2), (1, 3)]] nstocks = np.max(groups) + 1 ncat = len(groups) alpha = np.array([.1, .01]) beta = np.array([.5, .01]) gamma = .0 # A, B, C - n x n matrices avecs = np.ones((ncat + 1, nstocks)) * alpha[:, np.newaxis]**.5 bvecs = np.ones((ncat + 1, nstocks)) * beta[:, np.newaxis]**.5 dvecs = np.ones((ncat, nstocks)) * gamma**.5 vvec = np.ones(nstocks) param_true = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs, vvec=vvec, groups=groups) print(param_true) innov, hvar_true = simulate_bekk(param_true, nobs=nobs, distr='normal') bekk = BEKK(innov) result = bekk.estimate(use_target=False, restriction=restriction, cfree=False, model='spatial', groups=groups) print(result)
def test_simulation_spatial(self): """Test simulation spatial.""" nobs = 10 nstocks = 4 groups = [[(0, 1), (2, 3)]] ncat = 1 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) for distr in ['normal', 'student', 'skewt']: innov, hvar = simulate_bekk(param, nobs=nobs, distr=distr) self.assertEqual(innov.shape, (nobs, nstocks)) self.assertEqual(hvar.shape, (nobs, nstocks, nstocks))
def try_interative_estimation_spatial(): """Try estimating parameters from simple to more complicated model. """ restriction = 'full' nobs = 2000 groups = [[(0, 2), (1, 3)]] nstocks = np.max(groups) + 1 ncat = len(groups) alpha = np.array([.1, .01]) beta = np.array([.5, .01]) gamma = .0 # A, B, C - n x n matrices avecs = np.ones((ncat+1, nstocks)) * alpha[:, np.newaxis]**.5 bvecs = np.ones((ncat+1, nstocks)) * beta[:, np.newaxis]**.5 dvecs = np.ones((ncat, nstocks)) * gamma**.5 vvec = np.ones(nstocks) param_true = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs, vvec=vvec, groups=groups) print(param_true) innov, hvar_true = simulate_bekk(param_true, nobs=nobs, distr='normal') bekk = BEKK(innov) result = bekk.estimate(use_target=False, restriction=restriction, cfree=False, model='spatial', groups=groups) print(result)
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)
def try_spatial(): """Try simulating and estimating spatial BEKK. """ cfree = False restriction = 'h**o' nobs = 2000 groups = [[(0, 1), (2, 3)]] nstocks = np.max(groups) + 1 ncat = len(groups) alpha = np.array([.1, .01]) beta = np.array([.5, .01]) gamma = .09 # A, B, C - n x n matrices avecs = np.ones((ncat + 1, nstocks)) * alpha[:, np.newaxis]**.5 bvecs = np.ones((ncat + 1, nstocks)) * beta[:, np.newaxis]**.5 dvecs = np.vstack( [np.ones((1, nstocks)), np.ones((ncat, nstocks)) * gamma**.5]) param_true = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs, groups=groups) print(param_true) innov, hvar_true = simulate_bekk(param_true, nobs=nobs, distr='normal') # plot_data(innov, hvar_true) bekk = BEKK(innov) for use_target in [True, False]: result = bekk.estimate(param_start=param_true, use_target=use_target, cfree=cfree, restriction=restriction, groups=groups, model='spatial', method='SLSQP', cython=True) print(result) theta_true = param_true.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) theta_final = result.param_final.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) norm = np.linalg.norm(theta_true - theta_final) print('\nParameters (true and estimated):') print(np.vstack([theta_true, theta_final]).T) print('\nEucledean norm of the difference = %.4f' % norm)
def init_param_spatial(self, restriction='shomo', groups=None, use_target=False, method='SLSQP', cfree=False, use_penalty=False): """Estimate scalar BEKK with variance targeting. Parameters ---------- restriction : str Restriction on parameters. Must be - 'hetero' (heterogeneous) - 'ghomo' (group homogeneous) - 'h**o' (homogeneous) - 'shomo' (scalar homogeneous) 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 Returns ------- ParamSpatial instance Parameter object """ param = ParamSpatial.from_groups(groups=groups, target=estimate_uvar(self.innov), abstart=(.2, .7)) if restriction == 'shomo': return param kwargs = {'use_target': False, 'groups': groups, 'use_target': use_target, 'use_penalty': use_penalty, 'model': 'spatial', 'cfree': cfree, 'method': method} est_partial = partial(self.estimate, **kwargs) if restriction in ('h**o', 'ghomo', 'hetero'): result = est_partial(param_start=param, restriction='shomo') param = result.param_final if restriction in ('ghomo', 'hetero'): result = est_partial(param_start=param, restriction='h**o') param = result.param_final if restriction in ('hetero'): result = est_partial(param_start=param, restriction='ghomo') param = result.param_final return param
def test_init_empty(self): """Test spatial specification.""" nstocks = 3 param = ParamSpatial(nstocks=nstocks) self.assertEqual(param.amat.shape, (nstocks, nstocks)) self.assertEqual(param.bmat.shape, (nstocks, nstocks)) self.assertEqual(param.cmat.shape, (nstocks, nstocks)) self.assertEqual(param.avecs.shape, (2, nstocks)) self.assertEqual(param.bvecs.shape, (2, nstocks)) self.assertEqual(param.dvecs.shape, (2, nstocks)) self.assertEqual(param.weights.shape, (1, nstocks, nstocks))
def test_get_weight(self): """Test construction of spatial weights from groups. """ groups = [[(0, 1), (2, 3)]] weight = ParamSpatial.get_weight(groups=groups) weight_exp = np.zeros((1, 4, 4)) weight_exp[0, 0, 1] = 1 weight_exp[0, 1, 0] = 1 weight_exp[0, 2, 3] = 1 weight_exp[0, 3, 2] = 1 npt.assert_almost_equal(weight, weight_exp) groups = [[(0, 1, 2)]] weight = ParamSpatial.get_weight(groups=groups) weight_exp = np.array([[[0, .5, .5], [.5, 0, .5], [.5, .5, 0]]]) npt.assert_almost_equal(weight, weight_exp) groups = [[(0, 1), (2, 3)], [(0, 2), (1, 3)]] weight = ParamSpatial.get_weight(groups=groups) weight_exp = np.zeros((len(groups), 4, 4)) weight_exp[0, :2, :2] = np.array([[0, 1], [1, 0]]) weight_exp[0, 2:, 2:] = np.array([[0, 1], [1, 0]]) weight_exp[1, 0:3:2, 0:3:2] = np.array([[0, 1], [1, 0]]) weight_exp[1, 1:4:2, 1:4:2] = np.array([[0, 1], [1, 0]]) npt.assert_almost_equal(weight, weight_exp) groups = [[(0, 1), (2, 3, 4)]] weight = ParamSpatial.get_weight(groups=groups) weight_exp = np.zeros((len(groups), 5, 5)) weight_exp[0, :2, :2] = np.array([[0, 1], [1, 0]]) weight_exp[0, 2:, 2:] = np.array([[[0, .5, .5], [.5, 0, .5], [.5, .5, 0]]]) npt.assert_almost_equal(weight, weight_exp)
def test_get_theta_homo(self): """Test theta vector for spatial specification.""" nstocks = 4 groups = [[(0, 1), (2, 3)]] ncat = 1 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 = 'h**o' use_target = True theta = [avecs[0], avecs[1:, 0], bvecs[0], bvecs[1:, 0]] theta = np.concatenate(theta) nparams = 2 * (nstocks + ncat) theta_exp = param.get_theta(restriction=restriction, use_target=use_target) self.assertEqual(nparams, theta_exp.size) self.assertEqual(nparams, theta.size) npt.assert_array_equal(theta, theta_exp) use_target = False theta = [avecs[0], avecs[1:, 0], bvecs[0], bvecs[1:, 0], dvecs[0], dvecs[1:, 0]] theta = np.concatenate(theta) nparams = 3 * (nstocks + ncat) theta_exp = param.get_theta(restriction=restriction, use_target=use_target) self.assertEqual(nparams, theta_exp.size) self.assertEqual(nparams, theta.size) npt.assert_array_equal(theta, theta_exp) cfree = True theta = [avecs[0], avecs[1:, 0], bvecs[0], bvecs[1:, 0], param.cmat[np.tril_indices(param.cmat.shape[0])]] theta = np.concatenate(theta) nparams = 2 * (nstocks + ncat) + nstocks * (nstocks + 1) // 2 theta_exp = param.get_theta(restriction=restriction, cfree=cfree) self.assertEqual(nparams, theta_exp.size) self.assertEqual(nparams, theta.size) npt.assert_array_equal(theta, theta_exp)
def test_from_abt(self): """Test spatial specification.""" nstocks = 4 groups = [[(0, 1), (2, 3)]] weights = ParamSpatial.get_weight(groups) ncat = 1 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]) amat = np.diag(avecs[0]) + np.diag(avecs[0]).dot(weights[0]) bmat = np.diag(bvecs[0]) + np.diag(bvecs[0]).dot(weights[0]) dmat = np.eye(nstocks) - np.diag(dvecs[1]).dot(weights[0]) dmat_inv = scl.inv(dmat) ccmat = dmat_inv.dot(np.diag(dvecs[0])).dot(dmat_inv) cmat = scl.cholesky(ccmat, 1) target = ParamSpatial.find_stationary_var(amat=amat, bmat=bmat, cmat=cmat) cmat_new = ParamSpatial.find_cmat(amat=amat, bmat=bmat, target=target) npt.assert_array_almost_equal(cmat[np.tril_indices(nstocks)], cmat_new[np.tril_indices(nstocks)]) param = ParamSpatial.from_abt(avecs=avecs, bvecs=bvecs, target=target, groups=groups, restriction='hetero') npt.assert_array_equal(amat, param.amat) npt.assert_array_equal(bmat, param.bmat) npt.assert_array_almost_equal(cmat, param.cmat) npt.assert_array_equal(avecs, param.avecs) npt.assert_array_equal(bvecs, param.bvecs) # npt.assert_array_equal(None, param.dvecs) npt.assert_array_equal(weights, param.weights)
def try_spatial(): """Try simulating and estimating spatial BEKK. """ cfree = False restriction = 'h**o' nobs = 2000 groups = [[(0, 1), (2, 3)]] nstocks = np.max(groups) + 1 ncat = len(groups) alpha = np.array([.1, .01]) beta = np.array([.5, .01]) gamma = .09 # A, B, C - n x n matrices avecs = np.ones((ncat+1, nstocks)) * alpha[:, np.newaxis]**.5 bvecs = np.ones((ncat+1, nstocks)) * beta[:, np.newaxis]**.5 dvecs = np.vstack([np.ones((1, nstocks)), np.ones((ncat, nstocks)) * gamma**.5]) param_true = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs, groups=groups) print(param_true) innov, hvar_true = simulate_bekk(param_true, nobs=nobs, distr='normal') # plot_data(innov, hvar_true) bekk = BEKK(innov) for use_target in [True, False]: result = bekk.estimate(param_start=param_true, use_target=use_target, cfree=cfree, restriction=restriction, groups=groups, model='spatial', method='SLSQP', cython=True) print(result) theta_true = param_true.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) theta_final = result.param_final.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) norm = np.linalg.norm(theta_true - theta_final) print('\nParameters (true and estimated):') print(np.vstack([theta_true, theta_final]).T) print('\nEucledean norm of the difference = %.4f' % norm)
def test_get_theta_from_ab(self): """Test theta vector for spatial specification.""" nstocks = 4 groups = [[(0, 1), (2, 3)]] ncat = 1 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 = 'hetero' theta = np.concatenate([avecs.flatten(), bvecs.flatten()]) theta_exp = param.get_theta_from_ab(restriction=restriction) npt.assert_array_equal(theta, theta_exp) restriction = 'ghomo' theta = np.concatenate([avecs[0], avecs[1:, :2].flatten(), bvecs[0], bvecs[1:, :2].flatten()]) theta_exp = param.get_theta_from_ab(restriction=restriction) npt.assert_array_equal(theta, theta_exp) restriction = 'h**o' theta = np.concatenate([avecs[0], avecs[1:, 0], bvecs[0], bvecs[1:, 0]]) theta_exp = param.get_theta_from_ab(restriction=restriction) npt.assert_array_equal(theta, theta_exp) restriction = 'shomo' theta = np.concatenate([avecs[:, 0], bvecs[:, 0]]) theta_exp = param.get_theta_from_ab(restriction=restriction) npt.assert_array_equal(theta, theta_exp)
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
def estimate_loop(self, model='standard', use_target=True, groups=None, restriction='scalar', cfree=False, method='SLSQP', ngrid=2, use_penalty=False): """Estimate parameters starting from a grid of a and b. Parameters ---------- model : str Specific model to estimate. Must be - 'standard' - 'spatial' restriction : str Restriction on parameters. Must be - 'full' = 'diagonal' - 'group' - 'scalar' groups : list of lists of tuples Encoded groups of items use_target : bool Whether to use variance targeting (True) or not (False) cfree : bool Whether to leave C matrix free (True) or not (False) method : str Optimization method. See scipy.optimize.minimize ngrid : int Number of starting values in one dimension use_penalty : bool Whether to include penalty term in the likelihood Returns ------- BEKKResults instance Estimation results object """ target = estimate_uvar(self.innov) nstocks = self.innov.shape[1] achoice = np.linspace(.01, .5, ngrid) bchoice = np.linspace(.1, .9, ngrid) out = dict() for abstart in itertools.product(achoice, bchoice): if model == 'spatial': param = ParamSpatial.from_groups(groups=groups, target=target, abstart=abstart) if model == 'standard': param = ParamStandard(nstocks=nstocks, target=target, abstart=abstart) if param.constraint() >= 1: continue result = self.estimate(param_start=param, method=method, use_target=use_target, cfree=cfree, model=model, restriction=restriction, groups=groups, use_penalty=use_penalty) out[abstart] = (result.opt_out.fun, result) df = pd.DataFrame.from_dict(out, orient='index') return df.sort_values(by=0).iloc[0, 1]
def init_param_spatial(self, restriction='shomo', groups=None, use_target=False, method='SLSQP', cfree=False, use_penalty=False): """Estimate scalar BEKK with variance targeting. Parameters ---------- restriction : str Restriction on parameters. Must be - 'hetero' (heterogeneous) - 'ghomo' (group homogeneous) - 'h**o' (homogeneous) - 'shomo' (scalar homogeneous) 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 Returns ------- ParamSpatial instance Parameter object """ param = ParamSpatial.from_groups(groups=groups, target=estimate_uvar(self.innov), abstart=(.2, .7)) if restriction == 'shomo': return param kwargs = { 'use_target': False, 'groups': groups, 'use_target': use_target, 'use_penalty': use_penalty, 'model': 'spatial', 'cfree': cfree, 'method': method } est_partial = partial(self.estimate, **kwargs) if restriction in ('h**o', 'ghomo', 'hetero'): result = est_partial(param_start=param, restriction='shomo') param = result.param_final if restriction in ('ghomo', 'hetero'): result = est_partial(param_start=param, restriction='h**o') param = result.param_final if restriction in ('hetero'): result = est_partial(param_start=param, restriction='ghomo') param = result.param_final return param
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)
def try_spatial_combinations(): """Try simulating spatial BEKK and estimating it with both spatial and standard. """ use_target = False cfree = True restriction = 'full' nstocks = 3 nobs = 2000 groups = [(0, 1)] weights = ParamSpatial.get_weight(groups=groups, nitems=nstocks) ncat = weights.shape[0] alpha = np.array([.1, .01]) beta = np.array([.5, .01]) gamma = .0 # A, B, C - n x n matrices avecs = np.ones((ncat + 1, nstocks)) * alpha[:, np.newaxis]**.5 bvecs = np.ones((ncat + 1, nstocks)) * beta[:, np.newaxis]**.5 dvecs = np.ones((ncat, nstocks)) * gamma**.5 vvec = np.ones(nstocks) param_true = ParamSpatial.from_spatial(avecs=avecs, bvecs=bvecs, dvecs=dvecs, vvec=vvec, weights=weights) print(param_true) innov, hvar_true = simulate_bekk(param_true, nobs=nobs, distr='normal') bekk = BEKK(innov) # ------------------------------------------------------------------------- # Estimate spatial result = bekk.estimate(param_start=param_true, use_target=use_target, restriction=restriction, cfree=cfree, model='spatial', weights=weights, method='SLSQP', cython=True) print(result) theta_true = param_true.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) theta_final = result.param_final.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) norm = np.linalg.norm(theta_true - theta_final) print('\nParameters (true and estimated):\n', np.vstack([theta_true, theta_final]).T) print('\nEucledean norm of the difference = %.4f' % norm) # ------------------------------------------------------------------------- # Estimate standard param_true = ParamStandard.from_abc(amat=param_true.amat, bmat=param_true.bmat, cmat=param_true.cmat) result = bekk.estimate(param_start=param_true, use_target=use_target, restriction=restriction, cfree=cfree, model='standard', weights=weights, method='SLSQP', cython=True) print(result) theta_true = param_true.get_theta(use_target=use_target, restriction=restriction) theta_final = result.param_final.get_theta(use_target=use_target, restriction=restriction) norm = np.linalg.norm(theta_true - theta_final) print('\nParameters (true and estimated):\n', np.vstack([theta_true, theta_final]).T) print('\nEucledean norm of the difference = %.4f' % norm)
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)
def try_spatial_combinations(): """Try simulating spatial BEKK and estimating it with both spatial and standard. """ use_target = False cfree = True restriction = 'full' nstocks = 3 nobs = 2000 groups = [(0, 1)] weights = ParamSpatial.get_weight(groups=groups, nitems=nstocks) ncat = weights.shape[0] alpha = np.array([.1, .01]) beta = np.array([.5, .01]) gamma = .0 # A, B, C - n x n matrices avecs = np.ones((ncat+1, nstocks)) * alpha[:, np.newaxis]**.5 bvecs = np.ones((ncat+1, nstocks)) * beta[:, np.newaxis]**.5 dvecs = np.ones((ncat, nstocks)) * gamma**.5 vvec = np.ones(nstocks) param_true = ParamSpatial.from_spatial(avecs=avecs, bvecs=bvecs, dvecs=dvecs, vvec=vvec, weights=weights) print(param_true) innov, hvar_true = simulate_bekk(param_true, nobs=nobs, distr='normal') bekk = BEKK(innov) # ------------------------------------------------------------------------- # Estimate spatial result = bekk.estimate(param_start=param_true, use_target=use_target, restriction=restriction, cfree=cfree, model='spatial', weights=weights, method='SLSQP', cython=True) print(result) theta_true = param_true.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) theta_final = result.param_final.get_theta(use_target=use_target, cfree=cfree, restriction=restriction) norm = np.linalg.norm(theta_true - theta_final) print('\nParameters (true and estimated):\n', np.vstack([theta_true, theta_final]).T) print('\nEucledean norm of the difference = %.4f' % norm) # ------------------------------------------------------------------------- # Estimate standard param_true = ParamStandard.from_abc(amat=param_true.amat, bmat=param_true.bmat, cmat=param_true.cmat) result = bekk.estimate(param_start=param_true, use_target=use_target, restriction=restriction, cfree=cfree, model='standard', weights=weights, method='SLSQP', cython=True) print(result) theta_true = param_true.get_theta(use_target=use_target, restriction=restriction) theta_final = result.param_final.get_theta(use_target=use_target, restriction=restriction) norm = np.linalg.norm(theta_true - theta_final) print('\nParameters (true and estimated):\n', np.vstack([theta_true, theta_final]).T) print('\nEucledean norm of the difference = %.4f' % norm)
def test_get_theta_ghomo(self): """Test theta vector for spatial specification.""" nstocks = 4 groups = [[(0, 1), (2, 3)]] ncat = len(groups) alpha = [.01, .02, .03] beta = [.04, .05, .06] delta = [.07, .08] # 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[0] avecs[1, :2] *= alpha[1] avecs[1, 2:] *= alpha[2] bvecs[0, :] *= beta[0] bvecs[1, :2] *= beta[1] bvecs[1, 2:] *= beta[2] dvecs[1, :2] *= delta[0] dvecs[1, 2:] *= delta[1] param = ParamSpatial.from_abdv(avecs=avecs, bvecs=bvecs, dvecs=dvecs, groups=groups) restriction = 'ghomo' use_target = True theta = [avecs[0], [avecs[1, 0]], [avecs[1, 2]], bvecs[0], [bvecs[1, 0]], [bvecs[1, 2]]] theta = np.concatenate(theta) nparams = 2 * (nstocks + 2 * ncat) theta_exp = param.get_theta(restriction=restriction, use_target=use_target) self.assertEqual(nparams, theta_exp.size) self.assertEqual(nparams, theta.size) npt.assert_array_equal(theta, theta_exp) use_target = False theta = [avecs[0], [avecs[1, 0]], [avecs[1, 2]], bvecs[0], [bvecs[1, 0]], [bvecs[1, 2]], dvecs[0], [dvecs[1, 0]], [dvecs[1, 2]]] theta = np.concatenate(theta) nparams = 3 * (nstocks + 2 * ncat) theta_exp = param.get_theta(restriction=restriction, use_target=use_target) self.assertEqual(nparams, theta_exp.size) self.assertEqual(nparams, theta.size) npt.assert_array_equal(theta, theta_exp) cfree = True theta = [avecs[0], [avecs[1, 0]], [avecs[1, 2]], bvecs[0], [bvecs[1, 0]], [bvecs[1, 2]], param.cmat[np.tril_indices(param.cmat.shape[0])]] theta = np.concatenate(theta) nparams = 2 * (nstocks + 2 * ncat) + nstocks * (nstocks + 1) // 2 theta_exp = param.get_theta(restriction=restriction, cfree=cfree) self.assertEqual(nparams, theta_exp.size) self.assertEqual(nparams, theta.size) npt.assert_array_equal(theta, theta_exp)