diff --git a/pypfopt/discrete_allocation.py b/pypfopt/discrete_allocation.py index b5f5e35a..df6f6391 100644 --- a/pypfopt/discrete_allocation.py +++ b/pypfopt/discrete_allocation.py @@ -241,7 +241,9 @@ def greedy_portfolio(self, reinvest=False, verbose=False): # Calculate the equivalent continuous weights of the shares that # have already been bought current_weights = np.array(buy_prices) * np.array(shares_bought) - current_weights /= current_weights.sum() + invested = current_weights.sum() + if invested > 0: + current_weights /= invested ideal_weights = np.array([i[1] for i in self.weights]) deficit = ideal_weights - current_weights diff --git a/tests/test_discrete_allocation.py b/tests/test_discrete_allocation.py index e5da0368..4fda59d7 100644 --- a/tests/test_discrete_allocation.py +++ b/tests/test_discrete_allocation.py @@ -7,6 +7,18 @@ from tests.utilities_for_tests import get_data, setup_efficient_frontier +@pytest.mark.parametrize("budget, expected, cash", [(100, {"B": 1}, 50), (10, {}, 10)]) +def test_greedy_portfolio_with_no_initial_shares(budget, expected, cash): + da = DiscreteAllocation( + {"A": 0.9, "B": 0.1}, pd.Series({"A": 1000.0, "B": 50.0}), + total_portfolio_value=budget, + ) + with np.errstate(divide="raise", invalid="raise"): + allocation, leftover = da.greedy_portfolio() + assert allocation == expected + assert leftover == pytest.approx(cash) + + @pytest.mark.parametrize( "prices", [