예제 #1
0
def test_cla_max_sharpe_short():
    cla = CLA(*setup_cla(data_only=True), weight_bounds=(-1, 1))
    w = cla.max_sharpe()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(cla.tickers)
    np.testing.assert_almost_equal(cla.weights.sum(), 1)
    np.testing.assert_allclose(
        cla.portfolio_performance(),
        (0.44859872371106785, 0.26762066559448255, 1.601515797589826),
    )
    sharpe = cla.portfolio_performance()[2]

    cla_long_only = setup_cla()
    cla_long_only.max_sharpe()
    long_only_sharpe = cla_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
예제 #2
0
def test_cla_max_sharpe_short():
    cla = CLA(*setup_cla(data_only=True), weight_bounds=(-1, 1))
    w = cla.max_sharpe()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(cla.tickers)
    np.testing.assert_almost_equal(cla.weights.sum(), 1)
    np.testing.assert_allclose(
        cla.portfolio_performance(),
        (0.3799273115521356, 0.23115368271125736, 1.5570909679242886),
    )
    sharpe = cla.portfolio_performance()[2]

    cla_long_only = setup_cla()
    cla_long_only.max_sharpe()
    long_only_sharpe = cla_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
예제 #3
0
 def _get_efficient_weights(self):
     cla = CLA(self.mu, self.S)
     cla.max_sharpe()
     (mu, sigma, weights) = cla.efficient_frontier()
     return mu, sigma, weights
예제 #4
0
 'GOOG': 0.049560084289929286,
 'JPM': 0.017675709092515708,
 'MA': 0.03812737349732021,
 'PFE': 0.07786528342813454,
 'RRC': 0.03161528695094597,
 'SBUX': 0.039844436656239136,
 'SHLD': 0.027113184241298865,
 'T': 0.11138956508836476,
 'UAA': 0.02711590957075009,
 'WMT': 0.10569551148587905,
 'XOM': 0.11175337115721229}
"""

# Crticial Line Algorithm
cla = CLA(mu, S)
print(cla.max_sharpe())
cla.portfolio_performance(verbose=True)
"""
{'GOOG': 0.020889868669945022,
 'AAPL': 0.08867994115132602,
 'FB': 0.19417572932251745,
 'BABA': 0.10492386821217001,
 'AMZN': 0.0644908140418782,
 'GE': 0.0,
 'AMD': 0.0,
 'WMT': 0.0034898157701416382,
 'BAC': 0.0,
 'GM': 0.0,
 'T': 2.4138966206946562e-19,
 'UAA': 0.0,
 'SHLD': 0.0,
예제 #5
0
def optimal_portfolio(mu, S, objective='max_sharpe', get_entire_frontier=True, **kwargs):
    """Solve for optimal portfolio. Wrapper for pypfopt functions

    Arguments:
        mu (pd.Series) - Expected annual returns
        S (pd.DataFrame/np.ndarray) - Expected annual volatility
        objective (string, optional) - Optimise for either 'max_sharpe', or 'min_volatility', defaults to 'max_sharpe'
        get_entire_frontier (boolean, optional) - Also get the entire efficient frontier, defaults to True

    """

    # if need to efficiently compute the entire efficient frontier for plotting, use CLA
    # else use standard EfficientFrontier optimiser.
    # (Note that optimum weights might be slightly different depending on whether CLA or EfficientFrontier was used)
    Optimiser = CLA if get_entire_frontier else EfficientFrontier
    op = Optimiser(mu, S)
    # risk_aversion = kwargs.get("risk_aversion", 1)  # only for max quadratic utility

    if (objective is None):
        # Get weights for both max_sharpe and min_volatility
        opt_weights = []
        op.max_sharpe()
        opt_weights.append(op.clean_weights())
        op.min_volatility()
        opt_weights.append(op.clean_weights())

        # ef = EfficientFrontier(mu, S)
        # ef.max_quadratic_utility(risk_aversion)
        # opt_weights.append(ef.clean_weights())
    else:
        if (objective == 'max_sharpe'):
            op.max_sharpe()
        elif ('min_vol' in objective):
            op.min_volatility()
        elif (objective == 'efficient_risk'):
            target_volatility = kwargs.get("target_volatility", None)
            if target_volatility is None:
                print("Error: You have to specify the target_volatility!")
                return None, None, None, None
            else:
                try:
                    op.efficient_risk(target_volatility)
                except ValueError:
                    # could not solve based on target_volatility, we try lookup table instead
                    cla = CLA(mu, S)
                    cla.max_sharpe()
                    ef_returns, ef_risks, ef_weights = cla.efficient_frontier(points=300)

                    lookup_v_w = dict(zip(ef_risks, ef_weights))
                    lookup_v_w = OrderedDict(sorted(lookup_v_w.items()))
                    w = lookup_v_w[min(lookup_v_w.keys(), key=lambda key: abs(key-target_volatility))]
                    w = [i[0] for i in w]  # flatten
                    return w, None, None

        elif (objective == 'efficient_return'):
            target_return = kwargs.get("target_return", None)
            if target_return is None:
                print("Error: You have to specify the target_return!")
                return None, None, None, None
            else:
                op.efficient_return(target_return)

        # elif (objective == 'max_quadratic_utility'):
        #     op.max_quadratic_utility(risk_aversion)
        #     # print("Using MAX_QUADRATIC UTILITY")

        opt_weights = op.clean_weights()

    if get_entire_frontier:
        opt_returns, opt_risks, _ = op.efficient_frontier(points=200)
        return opt_weights, opt_returns, opt_risks
    else:
        return opt_weights, None, None