def test_efficient_risk_exp_cov_market_neutral():
    df = get_data()
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    ef.cov_matrix = risk_models.exp_cov(df)
    w = ef.efficient_risk(0.19, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.3934093962620499, 0.18999999989011893, 1.9653126130421081),
        atol=1e-6,
    )
def test_efficient_return_longshort_target():
    mu = pd.Series([-0.15, -0.12, -0.1, -0.05, -0.01, 0.02, 0.03, 0.04, 0.05])
    cov = pd.DataFrame(np.diag([0.2, 0.2, 0.4, 0.3, 0.1, 0.5, 0.2, 0.3, 0.1]))

    ef = EfficientFrontier(mu, cov, weight_bounds=(-1, 1))
    w = ef.efficient_return(target_return=0.08, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)

    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.08, 0.16649041068958137, 0.3603811159542937),
        atol=1e-6,
    )
def test_efficient_risk_exp_cov_market_neutral():
    df = get_data()
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    ef.cov_matrix = risk_models.exp_cov(df)
    w = ef.efficient_risk(0.19, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.3908928033782067, 0.18999999995323363, 1.9520673866815672),
        atol=1e-6,
    )
def test_min_volatility_sector_constraints():
    sector_mapper = {
        "T": "auto",
        "UAA": "airline",
        "SHLD": "retail",
        "XOM": "energy",
        "RRC": "energy",
        "BBY": "retail",
        "MA": "fig",
        "PFE": "pharma",
        "JPM": "fig",
        "SBUX": "retail",
        "GOOG": "tech",
        "AAPL": "tech",
        "FB": "tech",
        "AMZN": "tech",
        "BABA": "tech",
        "GE": "utility",
        "AMD": "tech",
        "WMT": "retail",
        "BAC": "fig",
        "GM": "auto",
    }

    sector_upper = {
        "tech": 0.2,
        "utility": 0.1,
        "retail": 0.2,
        "fig": 0.4,
        "airline": 0.05,
        "energy": 0.2,
    }
    sector_lower = {"utility": 0.01, "fig": 0.02, "airline": 0.01}

    # ef = setup_efficient_frontier()
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    ef.add_sector_constraints(sector_mapper, sector_lower, sector_upper)

    weights = ef.min_volatility()

    for sector in list(set().union(sector_upper, sector_lower)):
        sector_sum = 0
        for t, v in weights.items():
            if sector_mapper[t] == sector:
                sector_sum += v
        assert sector_sum <= sector_upper.get(sector, 1) + 1e-5
        assert sector_sum >= sector_lower.get(sector, 0) - 1e-5
def test_efficient_return_market_neutral():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    w = ef.efficient_return(0.25, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_almost_equal(
        ef.portfolio_performance(),
        (0.25, 0.1833060046337015, 1.2547324920403273))
    sharpe = ef.portfolio_performance()[2]
    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]
    assert long_only_sharpe < sharpe
def test_efficient_return_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    w = ef.efficient_return(0.25)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(ef.portfolio_performance(),
                               (0.25, 0.16826225873038014, 1.3669137793315087))
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
Ejemplo n.º 7
0
def test_efficient_return_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    w = ef.efficient_return(0.25)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(ef.portfolio_performance(),
                               (0.25, 0.17149595234895817, 1.3411395245760582))
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_efficient_return_market_neutral():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    w = ef.efficient_return(0.25, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_almost_equal(
        ef.portfolio_performance(),
        (0.25, 0.20567263154580923, 1.1182819914898223))
    sharpe = ef.portfolio_performance()[2]
    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]
    assert long_only_sharpe > sharpe
Ejemplo n.º 9
0
def test_ef_plot_utility_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    delta_range = np.linspace(0.001, 20, 100)
    ax = plotting.plot_efficient_frontier(ef,
                                          ef_param_range=delta_range,
                                          showfig=False)
    assert len(ax.findobj()) == 161
Ejemplo n.º 10
0
def test_bound_input_types():
    bounds = [0.01, 0.13]
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=bounds)
    assert ef
    np.testing.assert_allclose(ef._lower_bounds,
                               np.array([0.01] * ef.n_assets))
    np.testing.assert_allclose(ef._upper_bounds,
                               np.array([0.13] * ef.n_assets))

    lb = np.array([0.01, 0.02] * 10)
    ub = np.array([0.07, 0.2] * 10)
    assert EfficientFrontier(*setup_efficient_frontier(data_only=True),
                             weight_bounds=(lb, ub))
    bounds = ((0.01, 0.13), (0.02, 0.11)) * 10
    assert EfficientFrontier(*setup_efficient_frontier(data_only=True),
                             weight_bounds=bounds)
Ejemplo n.º 11
0
def get_result(l):
    data = yf.download(tickers=l,
                       period="max",
                       interval="1d",
                       auto_adjust=True)
    data = data['Close']
    mu = expected_returns.mean_historical_return(data)
    S = CovarianceShrinkage(data).ledoit_wolf()
    ef = EfficientFrontier(mu, S)
    raw_weights = ef.max_sharpe()
    cleaned_weights = ef.clean_weights()
    data = []
    for x in cleaned_weights.keys():
        if cleaned_weights[x] != 0:
            data.append({'name': x, 'y': cleaned_weights[x]})
    answer = {'data': data, 'performance': ef.portfolio_performance()}
    return answer
Ejemplo n.º 12
0
def allocate(df):
    tickers = [df.columns[k] for k in range(df.shape[1])]

    ohlc = yf.download(tickers, start="2010-01-01", end="2020-01-01")
    prices = ohlc["Adj Close"]

    market_prices = yf.download("^BVSP", start="2010-01-01",
                                end="2020-01-01")["Adj Close"]

    mcaps = {}
    for t in tickers:
        stock = yf.Ticker(t)
        mcaps[t] = stock.info["marketCap"]

    S = risk_models.CovarianceShrinkage(prices).ledoit_wolf()
    delta = black_litterman.market_implied_risk_aversion(market_prices)

    market_prior = black_litterman.market_implied_prior_returns(
        mcaps, delta, S)

    bl = BlackLittermanModel(S,
                             pi="market",
                             market_caps=mcaps,
                             risk_aversion=delta,
                             absolute_views=df.to_dict('records')[0])

    ret_bl = bl.bl_returns()
    S_bl = bl.bl_cov()

    ef = EfficientFrontier(ret_bl, S_bl)
    ef.add_objective(objective_functions.L2_reg)
    ef.max_sharpe()
    weights = ef.clean_weights()

    return weights
Ejemplo n.º 13
0
    def optimizePortfolio(self, option='sharpe'):
        '''
            Optimize for maximal Sharpe ratio / minimum volatility (Default to Sharpe)
            TODO: Allow for more options
            Return EfficientFrontier object
        '''

        mu = self.calculateMu()
        S = self.calculateSampleCovarianceMatrix()
        ef = EfficientFrontier(mu, S)

        if option == 'sharpe':
            weights = ef.max_sharpe(
            )  #Maximize the Sharpe ratio, and get the raw weights

        elif option == 'volatility':
            weights = ef.min_volatility()

        else:
            raise SystemExit("Not found optimize option (Sharpe/Volatility)")

        self.cleaned_weights = ef.clean_weights()
        print(
            self.cleaned_weights
        )  #Note the weights may have some rounding error, meaning they may not add up exactly to 1 but should be close
        ef.portfolio_performance(verbose=True)

        return ef
def test_max_sharpe_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    w = ef.max_sharpe()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.4937195216716211, 0.29516576454651955, 1.6049270564945908),
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.max_sharpe()
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_max_sharpe_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    w = ef.max_sharpe()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.4072439477276246, 0.24823487545231313, 1.5599900981762558),
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.max_sharpe()
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_min_volatility_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    w = ef.min_volatility()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.1721356467349655, 0.1555915367269669, 0.9777887019776287),
    )

    # Shorting should reduce volatility
    volatility = ef.portfolio_performance()[1]
    ef_long_only = setup_efficient_frontier()
    ef_long_only.min_volatility()
    long_only_volatility = ef_long_only.portfolio_performance()[1]
    assert volatility < long_only_volatility
Ejemplo n.º 17
0
 def fit(self, prices: pd.DataFrame):
     # TODO: make prices instance of portfolio
     '''
     Given prices finds wieghts (coefficients), most optimal portfolio given target function.
     :param prices:
     :return:
     '''
     self.frequency = autodetect_frequency(prices)
     self.mu = expected_returns.mean_historical_return(
         prices, frequency=self.frequency)
     self.S = risk_models.CovarianceShrinkage(
         prices, frequency=self.frequency).ledoit_wolf()
     # self.S=risk_models.exp_cov(prices)
     self.ef = EfficientFrontier(self.mu, self.S)
     self.ef.add_objective(objective_functions.L2_reg)
     getattr(self.ef, self.target_function)(**self.target_function_params)
     self.coef_ = self.ef.clean_weights()
     return self
Ejemplo n.º 18
0
def test_custom_convex_abs_exposure():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))

    ef.add_constraint(lambda x: cp.norm(x, 1) <= 2)
    ef.min_volatility()
    ef.convex_objective(
        objective_functions.portfolio_variance,
        cov_matrix=ef.cov_matrix,
        weights_sum_to_one=False,
    )
Ejemplo n.º 19
0
def test_bound_failure():
    # Ensure optimization fails when lower bound is too high or upper bound is too low
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(0.06, 0.13))
    with pytest.raises(exceptions.OptimizationError):
        ef.min_volatility()

    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(0, 0.04))
    with pytest.raises(exceptions.OptimizationError):
        ef.min_volatility()
Ejemplo n.º 20
0
def test_none_bounds():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, 0.3))
    ef.min_volatility()
    w1 = ef.weights

    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 0.3))
    ef.min_volatility()
    w2 = ef.weights
    np.testing.assert_array_almost_equal(w1, w2)
Ejemplo n.º 21
0
def test_custom_convex_kelly():

    lb = 0.01
    ub = 0.3
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(lb, ub))

    def kelly_objective(w, e_returns, cov_matrix, k=3):
        variance = cp.quad_form(w, cov_matrix)

        objective = variance * 0.5 * k - w @ e_returns
        return objective

    weights = ef.convex_objective(kelly_objective,
                                  e_returns=ef.expected_returns,
                                  cov_matrix=ef.cov_matrix)

    for w in weights.values():
        assert w >= lb - 1e-8 and w <= ub + 1e-8
Ejemplo n.º 22
0
def test_efficient_risk_market_neutral():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    w = ef.efficient_risk(0.21, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.28640632960825885, 0.20999999995100788, 1.2686015698590967),
        atol=1e-6,
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_risk(0.21)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]
    assert long_only_sharpe > sharpe
def test_efficient_risk_market_neutral():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    w = ef.efficient_risk(0.21, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.2552600197428133, 0.21, 1.1202858085349783),
        atol=1e-6,
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_risk(0.21)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]
    assert long_only_sharpe > sharpe
Ejemplo n.º 24
0
def portfolio_opt(input_return_df: pd.DataFrame, input_freq: str, solution: str, weight_bounds = (0,1), risk_aversion=1, market_neutral=False,
                                risk_free_rate=0.0, target_volatility=0.01, target_return=0.11, 
                                returns_data=True, compounding=False):
    """
    pyportfolioopt Portfolios

    Args
    ----------
    input_return_df: pd.DataFrame
        historical prices only, or historical + forecasts
    solution: str
        'max_sharpe','min_volatility','max_quadratic_utility',
        'efficient_risk','efficient_return','custom'
    input_freq: str
        daily/monthly

    Returns
    ----------
    weights_df: 1 x n pd.DataFrame

    """ 
    if not isinstance(input_return_df, pd.DataFrame):
        raise ValueError("Not a valid input_price_df. Type should be a pd.DataFrame.") 
    if not isinstance(input_freq, str):
        raise ValueError("Not a valid input_freq, please enter daily/monthly.")
    if not isinstance(solution, str):
        raise ValueError("Not a valid solution.")
    # annualized mean returns: returns.mean() * frequency
    mu = calculate_annualized_expected_returns(input_price_df = input_return_df, 
                                                                input_freq = input_freq, 
                                                                returns_data = returns_data, 
                                                                compounding = compounding)
    # annulized return covariance matrix: returns.cov() * frequency
    S = calculate_annualized_return_covariance(input_price_df = input_return_df,
                                                    input_freq = input_freq,
                                                    returns_data = returns_data, 
                                                    compounding = compounding)
    # Optimise for maximal Sharpe ratio
    ef = EfficientFrontier(mu, S, weight_bounds = weight_bounds, gamma = 0)

    if solution == 'max_sharpe':
        raw_weights = ef.max_sharpe(risk_free_rate = risk_free_rate)
    elif solution == 'min_volatility':
        raw_weights = ef.min_volatility()
    elif solution == 'max_quadratic_utility':
        raw_weights = ef.max_quadratic_utility(risk_aversion = risk_aversion, market_neutral = market_neutral)
    elif solution == 'efficient_risk':
        raw_weights = ef.efficient_risk(target_volatility = target_volatility, market_neutral = market_neutral)
    elif solution == 'efficient_return':
        raw_weights = ef.efficient_return(target_return = target_return, market_neutral = market_neutral)
    elif solution == 'custom':
        print('Outside Implement Required.')
        return None

    date = input_return_df.index[-1] # the date on which weights are calculated
    weights_df = pd.DataFrame(raw_weights, columns = raw_weights.keys(), index=[date])
    return weights_df
Ejemplo n.º 25
0
def test_efficient_risk_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    w = ef.efficient_risk(0.19)

    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.30035471606347336, 0.1900000003049494, 1.4755511348079207),
        atol=1e-6,
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_risk(0.19)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_efficient_risk_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    w = ef.efficient_risk(0.19)

    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.30468522897430295, 0.19, 1.4983424153337392),
        atol=1e-6,
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_risk(0.19)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
Ejemplo n.º 27
0
def test_weight_bounds_minus_one_to_one():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    assert ef.max_sharpe()
    ef2 = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                            weight_bounds=(-1, 1))
    assert ef2.min_volatility()
def test_max_sharpe_long_weight_bounds():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(0.03, 0.13))
    ef.max_sharpe()
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    assert ef.weights.min() >= 0.03
    assert ef.weights.max() <= 0.13

    bounds = [(0.01, 0.13), (0.02, 0.11)] * 10
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=bounds)
    ef.max_sharpe()
    assert (0.01 <= ef.weights[::2]).all() and (ef.weights[::2] <= 0.13).all()
    assert (0.02 <= ef.weights[1::2]).all() and (ef.weights[1::2] <=
                                                 0.11).all()
Ejemplo n.º 29
0
def build_portfolio_weights(stock_data, weights_filename):

    # Calculate expected returns and sample covariance
    if isinstance(stock_data, pd.Series):
        stock_data = stock_data.to_frame()

    mu = expected_returns.mean_historical_return(stock_data)
    S = risk_models.sample_cov(stock_data)

    # Optimize for maximal Sharpe ratio
    ef = EfficientFrontier(mu, S)
    raw_weights = ef.max_sharpe()
    cleaned_weights = ef.clean_weights()
    ef.save_weights_to_file(weights_filename)  # saves to file
    ef.portfolio_performance(verbose=True)
    return cleaned_weights
Ejemplo n.º 30
0
def test_constrained_ef_plot_risk():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))

    ef.add_constraint(lambda w: w[0] >= 0.2)
    ef.add_constraint(lambda w: w[2] == 0.15)
    ef.add_constraint(lambda w: w[3] + w[4] <= 0.10)

    # 100 portfolios with risks between 0.10 and 0.30
    risk_range = np.linspace(0.157, 0.40, 100)
    ax = plotting.plot_efficient_frontier(ef,
                                          ef_param="risk",
                                          ef_param_range=risk_range,
                                          show_assets=True,
                                          showfig=False)
    assert len(ax.findobj()) == 137