diff --git a/pypfopt/cla.py b/pypfopt/cla.py index bde53b19..aec3b574 100644 --- a/pypfopt/cla.py +++ b/pypfopt/cla.py @@ -363,9 +363,10 @@ def _solve(self): meanF.shape[0] - 1, self.w[-1][i], ) + lam_cmp = CLA._infnone(lam) if ( - self.ls[-1] is None or lam < self.ls[-1] - ) and lam > CLA._infnone(l_out): + self.ls[-1] is None or lam_cmp < self.ls[-1] + ) and lam_cmp > CLA._infnone(l_out): l_out, i_out = lam, i if (l_in is None or l_in < 0) and (l_out is None or l_out < 0): # 3) compute minimum variance solution diff --git a/tests/test_cla.py b/tests/test_cla.py index c5f69e23..72af8c6b 100644 --- a/tests/test_cla.py +++ b/tests/test_cla.py @@ -52,6 +52,20 @@ def test_cla_max_sharpe_short(): assert sharpe > long_only_sharpe +def test_cla_max_sharpe_equal_expected_returns_falls_back_to_min_var(): + mu = np.array([0.1, 0.1]) + cov = np.array([[0.01, 0.01], [0.01, 0.02]]) + + cla = CLA(mu, cov) + cla_min_var = CLA(mu, cov) + min_var_weights = cla_min_var.min_volatility() + w = cla.max_sharpe() + + assert isinstance(w, dict) + np.testing.assert_allclose(cla.weights, cla_min_var.weights) + np.testing.assert_allclose(np.array(list(w.values())), np.array(list(min_var_weights.values()))) + + def test_cla_custom_bounds(): bounds = [(0.01, 0.13), (0.02, 0.11)] * 10 cla = setup_cla(weight_bounds=bounds)