Commit 2161714e authored by wegamekinglc's avatar wegamekinglc

update builder

parent a762b081
...@@ -92,7 +92,7 @@ def linear_builder(er: np.ndarray, ...@@ -92,7 +92,7 @@ def linear_builder(er: np.ndarray,
from cvxpy import Problem from cvxpy import Problem
from cvxpy import Variable from cvxpy import Variable
from cvxpy import multiply from cvxpy import multiply
from cvxpy import pnorm from cvxpy import norm1
from cvxpy import Minimize from cvxpy import Minimize
w = Variable(n) w = Variable(n)
...@@ -102,13 +102,13 @@ def linear_builder(er: np.ndarray, ...@@ -102,13 +102,13 @@ def linear_builder(er: np.ndarray,
w <= ubound, w <= ubound,
current_risk_exposure >= risk_lbound.flatten(), current_risk_exposure >= risk_lbound.flatten(),
current_risk_exposure <= risk_ubound.flatten(), current_risk_exposure <= risk_ubound.flatten(),
pnorm(w - current_position, 1) <= turn_over_target] norm1(w - current_position) <= turn_over_target]
objective = Minimize(-w.T * er) objective = Minimize(-w.T * er)
prob = Problem(objective, constraints) prob = Problem(objective, constraints)
prob.solve(solver='ECOS', feastol=1e-10, abstol=1e-10, reltol=1e-10) prob.solve(solver='ECOS', feastol=1e-9, abstol=1e-9, reltol=1e-9)
if prob.status == 'optimal': if prob.status == 'optimal' or prob.status == 'optimal_inaccurate':
return prob.status, prob.value, w.value.flatten() return prob.status, prob.value, w.value.flatten()
else: else:
raise PortfolioBuilderException(prob.status) raise PortfolioBuilderException(prob.status)
......
...@@ -10,6 +10,7 @@ from typing import Union ...@@ -10,6 +10,7 @@ from typing import Union
from typing import Tuple from typing import Tuple
from typing import Optional from typing import Optional
from typing import Dict from typing import Dict
import cvxpy
from alphamind.cython.optimizers import QPOptimizer from alphamind.cython.optimizers import QPOptimizer
from alphamind.cython.optimizers import CVOptimizer from alphamind.cython.optimizers import CVOptimizer
from alphamind.exceptions.exceptions import PortfolioBuilderException from alphamind.exceptions.exceptions import PortfolioBuilderException
...@@ -54,19 +55,41 @@ def mean_variance_builder(er: np.ndarray, ...@@ -54,19 +55,41 @@ def mean_variance_builder(er: np.ndarray,
lam: float=1.) -> Tuple[str, float, np.ndarray]: lam: float=1.) -> Tuple[str, float, np.ndarray]:
lbound, ubound, cons_mat, clbound, cubound = _create_bounds(lbound, ubound, bm, risk_exposure, risk_target) lbound, ubound, cons_mat, clbound, cubound = _create_bounds(lbound, ubound, bm, risk_exposure, risk_target)
optimizer = QPOptimizer(er, if np.all(lbound == -np.inf) and np.all(ubound == np.inf) and cons_mat is None:
risk_model['cov'], # using fast path cvxpy
lbound, n = len(er)
ubound, w = cvxpy.Variable(n)
cons_mat, cov = risk_model['cov']
clbound, special_risk = risk_model['idsync']
cubound, risk_cov = risk_model['factor_cov']
lam, risk_exposure = risk_model['factor_loading']
risk_model['factor_cov'], if cov is None:
risk_model['factor_loading'], risk = cvxpy.sum_squares(cvxpy.multiply(cvxpy.sqrt(special_risk), w)) \
risk_model['idsync']) + cvxpy.quad_form((w.T * risk_exposure).T, risk_cov)
else:
return _create_result(optimizer, bm) risk = cvxpy.quad_form(w, cov)
objective = cvxpy.Minimize(-w.T * er + 0.5 * lam * risk)
prob = cvxpy.Problem(objective)
prob.solve(solver='ECOS', feastol=1e-9, abstol=1e-9, reltol=1e-9)
if prob.status == 'optimal' or prob.status == 'optimal_inaccurate':
return 'optimal', prob.value, np.array(w.value) + bm
else:
raise PortfolioBuilderException(prob.status)
else:
optimizer = QPOptimizer(er,
risk_model['cov'],
lbound,
ubound,
cons_mat,
clbound,
cubound,
lam,
risk_model['factor_cov'],
risk_model['factor_loading'],
risk_model['idsync'])
return _create_result(optimizer, bm)
def target_vol_builder(er: np.ndarray, def target_vol_builder(er: np.ndarray,
......
...@@ -41,6 +41,22 @@ class TestMeanVarianceBuild(unittest.TestCase): ...@@ -41,6 +41,22 @@ class TestMeanVarianceBuild(unittest.TestCase):
self.assertTrue(np.all(x @ risk_exposure >= risk_target[0] - 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]) 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.])
lbound = np.array([-np.inf, -np.inf, -np.inf])
ubound = np.array([np.inf, np.inf, np.inf])
model = dict(cov=cov, factor_cov=None, factor_loading=None, idsync=None)
status, _, x = mean_variance_builder(er, model, bm, lbound, ubound, None, None, lam=1)
np.testing.assert_array_almost_equal(x, np.linalg.inv(cov) @ er)
def test_mean_variance_builder_with_none_unity_lambda(self): def test_mean_variance_builder_with_none_unity_lambda(self):
er = np.array([0.01, 0.02, 0.03]) er = np.array([0.01, 0.02, 0.03])
cov = np.array([[0.02, 0.01, 0.02], cov = np.array([[0.02, 0.01, 0.02],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment