def test_mean_variance_builder_with_none_unity_lambda(self): er = np.array([0.01, 0.02, 0.03]) cov = np.array([[0.02, 0.01, 0.02], [0.01, 0.02, 0.03], [0.02, 0.03, 0.02]]) ids_var = np.diag([0.01, 0.02, 0.03]) cov += ids_var bm = np.array([0.3, 0.3, 0.4]) lbound = np.array([0., 0., 0.]) ubound = np.array([0.4, 0.4, 0.5]) risk_exposure = np.array([[1., 1., 1.], [1., 0., 1.]]).T risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7])) model = dict(cov=cov, factor_cov=None, factor_loading=None, idsync=None) status, _, x = mean_variance_builder(er, model, bm, lbound, ubound, risk_exposure, risk_target, lam=100) self.assertTrue(status == 'optimal') self.assertAlmostEqual(x.sum(), bm.sum()) self.assertTrue(np.all(x <= ubound + 1.e-6)) self.assertTrue(np.all(x >= lbound) - 1.e-6) self.assertTrue(np.all(x @ risk_exposure <= risk_target[1] + 1.e-6)) self.assertTrue(np.all(x @ risk_exposure >= risk_target[0] - 1.e-6)) np.testing.assert_array_almost_equal(x, [0.2950, 0.3000, 0.4050])
def test_mean_variance_builder(self): er = np.array([0.01, 0.02, 0.03]) cov = np.array([[0.02, 0.01, 0.02], [0.01, 0.02, 0.03], [0.02, 0.03, 0.02]]) ids_var = np.diag([0.01, 0.02, 0.03]) cov += ids_var bm = np.array([0.3, 0.3, 0.4]) lbound = np.array([0., 0., 0.]) ubound = np.array([0.4, 0.4, 0.5]) risk_exposure = np.array([[1., 1., 1.], [1., 0., 1.]]).T risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7])) status, _, x = mean_variance_builder(er, cov, bm, lbound, ubound, risk_exposure, risk_target) self.assertTrue(status == 'optimal') self.assertAlmostEqual(x.sum(), bm.sum()) self.assertTrue(np.all(x <= ubound + 1.e-6)) self.assertTrue(np.all(x >= lbound) - 1.e-6) self.assertTrue(np.all(x @ risk_exposure <= risk_target[1] + 1.e-6)) self.assertTrue(np.all(x @ risk_exposure >= risk_target[0] - 1.e-6)) np.testing.assert_array_almost_equal(x, [0.1, 0.4, 0.5])
def test_mean_variance_builder_without_constraints(self): er = np.array([0.01, 0.02, 0.03]) cov = np.array([[0.02, 0.01, 0.02], [0.01, 0.02, 0.03], [0.02, 0.03, 0.02]]) ids_var = np.diag([0.01, 0.02, 0.03]) cov += ids_var bm = np.array([0., 0., 0.]) model = dict(cov=cov, factor_cov=None, factor_loading=None, idsync=None) status, _, x = mean_variance_builder(er, model, bm, None, None, None, None, lam=1) np.testing.assert_array_almost_equal(x, np.linalg.inv(cov) @ er)
def er_portfolio_analysis( er: np.ndarray, industry: np.ndarray, dx_return: np.ndarray, constraints: Optional[Union[LinearConstraints, Constraints]] = None, detail_analysis=True, benchmark: Optional[np.ndarray] = None, is_tradable: Optional[np.ndarray] = None, method='risk_neutral', **kwargs) -> Tuple[pd.DataFrame, Optional[pd.DataFrame]]: er = er.flatten() def create_constraints(benchmark, **kwargs): if 'lbound' in kwargs: lbound = kwargs['lbound'].copy() del kwargs['lbound'] else: lbound = np.maximum(0., benchmark - 0.01) if 'ubound' in kwargs: ubound = kwargs['ubound'].copy() del kwargs['ubound'] else: ubound = 0.01 + benchmark if is_tradable is not None: ubound[~is_tradable] = np.minimum(lbound, ubound)[~is_tradable] risk_lbound, risk_ubound = constraints.risk_targets() cons_exp = constraints.risk_exp return lbound, ubound, cons_exp, risk_lbound, risk_ubound if method == 'risk_neutral': lbound, ubound, cons_exp, risk_lbound, risk_ubound = create_constraints( benchmark, **kwargs) turn_over_target = kwargs.get('turn_over_target') current_position = kwargs.get('current_position') status, _, weights = linear_builder(er, risk_constraints=cons_exp, lbound=lbound, ubound=ubound, risk_target=(risk_lbound, risk_ubound), turn_over_target=turn_over_target, current_position=current_position) if status != 'optimal': raise ValueError( 'linear programming optimizer in status: {0}'.format(status)) elif method == 'rank': weights = rank_build( er, use_rank=kwargs['use_rank'], masks=is_tradable).flatten() * benchmark.sum() / kwargs['use_rank'] elif method == 'ls' or method == 'long_short': weights = long_short_builder(er).flatten() elif method == 'mv' or method == 'mean_variance': lbound, ubound, cons_exp, risk_lbound, risk_ubound = create_constraints( benchmark, **kwargs) cov = kwargs['cov'] if 'lam' in kwargs: lam = kwargs['lam'] else: lam = 1. status, _, weights = mean_variance_builder(er, cov=cov, bm=benchmark, lbound=lbound, ubound=ubound, risk_exposure=cons_exp, risk_target=(risk_lbound, risk_ubound), lam=lam) if status != 'optimal': raise ValueError( 'mean variance optimizer in status: {0}'.format(status)) elif method == 'tv' or method == 'target_vol': lbound, ubound, cons_exp, risk_lbound, risk_ubound = create_constraints( benchmark, **kwargs) cov = kwargs['cov'] if 'target_vol' in kwargs: target_vol = kwargs['target_vol'] else: target_vol = 1. status, _, weights = target_vol_builder(er, cov=cov, bm=benchmark, lbound=lbound, ubound=ubound, risk_exposure=cons_exp, risk_target=(risk_lbound, risk_ubound), vol_low=0, vol_high=target_vol) else: raise ValueError("Unknown building type ({0})".format(method)) if detail_analysis: analysis = simple_settle(weights, dx_return, industry, benchmark) else: analysis = None return pd.DataFrame({'weight': weights, 'industry': industry, 'er': er}), \ analysis