Esempio n. 1
0
def test_efficient_semivariance_vs_heuristic_weekly():
    benchmark = 0
    _, historic_returns = setup_efficient_semivariance(data_only=True)
    weekly_returns = historic_returns.resample("W").sum()
    mean_weekly_returns = weekly_returns.mean(axis=0)

    es = EfficientSemivariance(mean_weekly_returns,
                               weekly_returns,
                               frequency=52)
    es.efficient_return(0.20 / 52)
    mu_es, semi_deviation, _ = es.portfolio_performance()

    pairwise_semivariance = risk_models.semicovariance(weekly_returns,
                                                       returns_data=True,
                                                       benchmark=0,
                                                       frequency=1)
    ef = EfficientFrontier(mean_weekly_returns, pairwise_semivariance)
    ef.efficient_return(0.20 / 52)
    mu_ef, _, _ = ef.portfolio_performance()
    portfolio_returns = historic_returns @ ef.weights
    drops = np.fmin(portfolio_returns - benchmark, 0)
    T = weekly_returns.shape[0]
    semivariance = np.sum(np.square(drops)) / T * 52
    semi_deviation_ef = np.sqrt(semivariance)

    assert semi_deviation < semi_deviation_ef
    assert mu_es / semi_deviation > mu_ef / semi_deviation_ef
Esempio n. 2
0
def test_efficient_semivariance_vs_heuristic():
    benchmark = 0
    es = setup_efficient_semivariance()
    es.efficient_return(0.20)
    mu_es, semi_deviation, _ = es.portfolio_performance()
    np.testing.assert_almost_equal(mu_es, 0.2)

    mean_return, historic_returns = setup_efficient_semivariance(
        data_only=True)

    pairwise_semivariance = risk_models.semicovariance(historic_returns,
                                                       returns_data=True,
                                                       benchmark=0,
                                                       frequency=1)
    ef = EfficientFrontier(mean_return, pairwise_semivariance)
    ef.efficient_return(0.20)
    mu_ef, _, _ = ef.portfolio_performance()
    # mu_ef *= 252

    portfolio_returns = historic_returns @ ef.weights
    drops = np.fmin(portfolio_returns - benchmark, 0)
    T = historic_returns.shape[0]
    semivariance = np.sum(np.square(drops)) / T * 252
    semi_deviation_ef = np.sqrt(semivariance)

    assert semi_deviation < semi_deviation_ef
    assert mu_es / semi_deviation > mu_ef / semi_deviation_ef
def test_ef_example_weekly():
    df = get_data()
    prices_weekly = df.resample("W").first()
    mu = expected_returns.mean_historical_return(prices_weekly, frequency=52)
    S = risk_models.sample_cov(prices_weekly, frequency=52)
    ef = EfficientFrontier(mu, S)
    ef.efficient_return(0.2)
    np.testing.assert_almost_equal(ef.portfolio_performance()[0], 0.2)
def test_ef_example():
    df = get_data()
    mu = expected_returns.mean_historical_return(df)
    S = risk_models.sample_cov(df)

    ef = EfficientFrontier(mu, S)
    ef.efficient_return(0.2)
    np.testing.assert_almost_equal(ef.portfolio_performance()[0], 0.2)
def test_efficient_return_short():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(None, None))
    target_return = 0.25
    weights_sum = 1.0  # Not market neutral, weights must sum to 1.
    w = ef.efficient_return(target_return)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    np.testing.assert_almost_equal(ef.weights.sum(), weights_sum)
    w_expected = simple_ef_weights(ef.expected_returns, ef.cov_matrix,
                                   target_return, weights_sum)
    np.testing.assert_almost_equal(ef.weights, w_expected)
    vol_expected = np.sqrt(
        objective_functions.portfolio_variance(w_expected, ef.cov_matrix))
    sharpe_expected = objective_functions.sharpe_ratio(w_expected,
                                                       ef.expected_returns,
                                                       ef.cov_matrix,
                                                       negative=False)
    np.testing.assert_allclose(ef.portfolio_performance(),
                               (target_return, vol_expected, sharpe_expected))
    sharpe = ef.portfolio_performance()[2]

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

    assert sharpe > long_only_sharpe
Esempio n. 6
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
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_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
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
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
Esempio n. 11
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
Esempio n. 12
0
ef_maxquad = EfficientFrontier(exp_ret, S, weight_bounds=(0.025, 0.15))
ef_maxquad.max_quadratic_utility(risk_aversion=1, market_neutral=False)
weights_maxquad = ef_maxquad.clean_weights()
weights_maxquad
ef_maxquad.portfolio_performance(verbose=True)

# efficient risk
ef_effrisk = EfficientFrontier(exp_ret, S, weight_bounds=(0.0, 0.15))
ef_effrisk.efficient_risk(0.15, market_neutral=False)
weights_effrisk = ef_effrisk.clean_weights()
weights_effrisk
ef_effrisk.portfolio_performance(verbose=True)

# efficient return
ef_effret = EfficientFrontier(exp_ret, S, weight_bounds=(0.03, 0.15))
ef_effret.efficient_return(target_return=0.30, market_neutral=False)
weights_effret = ef_effret.clean_weights()
weights_effret
ef_effret.portfolio_performance(verbose=True)


def minimize_negative_skew(w, skew, negative=True):
    """
    Calculate the (negative) "Skew" of a portfolio

    :param w: asset weights in the portfolio
    :type w: np.ndarray OR cp.Variable
    :param skew: expected return of each asset
    :type skew: np.ndarray
    :param cov_matrix: covariance matrix
    :type cov_matrix: np.ndarray
Esempio n. 13
0
weights = ef.efficient_risk(target_volatility=0.10)
ef.portfolio_performance(verbose=True)
"""
Expected annual return: 21.0%
Annual volatility: 16.8%
Sharpe Ratio: 1.13
"""

# A market-neutral Markowitz portfolio finding the minimum volatility
# for a target return of 20%, taking into account transaction costs.
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))

# pretend we were initially equal-weighted
old_weights = np.array([1 / ef.n_assets] * ef.n_assets)
ef.add_objective(objective_functions.transaction_cost, w_prev=old_weights)
weights = ef.efficient_return(target_return=0.20, market_neutral=True)
ef.portfolio_performance(verbose=True)
"""
Expected annual return: 20.0%
Annual volatility: 16.5%
Sharpe Ratio: 1.09
"""


# Custom convex objective from 60 Years of Portfolio Optimisation, Kolm et al (2014)
def logarithmic_barrier(w, cov_matrix, k=0.1):
    log_sum = cp.sum(cp.log(w))
    var = cp.quad_form(w, cov_matrix)
    return var - k * log_sum

Esempio n. 14
0
ef.portfolio_performance(verbose=True)

# In[63]:
"""

Let's now work with the assumption that we have a required rate of return, such as an investor to retire, 
or the actuarial level necessary to cover the liabilities of a pension fund or scheme. We also suppose 
our portfolio to be market neutral, equally exposed to long and short positions. 

"""

# In[71]:

ef = EfficientFrontier(mu, S, weight_bounds=(None, None))
ef.add_objective(objective_functions.L2_reg)
ef.efficient_return(target_return=0.15, market_neutral=True)
weights = ef.clean_weights()
weights

# In[72]:

ef.portfolio_performance(verbose=True)

# In[73]:

pd.Series(weights).plot.barh(figsize=(10, 10))

# In[74]:

print(f"Net weight: {sum(weights.values()):.2f}")