def optimizePortEfficient(port, weights, start, plot = False, short = False, printBasicStats=True, how = 'Sharpe'):
    #Getting Data
    df = bpf.getData(port, start)
    #Plotting the portfolio
    if plot: 
        bpf.plotPort(df, port)
        
    if printBasicStats:
        bpf.basicStats(df, weights, start)
    #Optimization for Sharpe using Efficient Frontier
    if short: 
        bounds = (-1,1)
    else:
        bounds = (0,1)
    mu = df.pct_change().mean() * 252
    S = risk_models.sample_cov(df)
    #Method and constraints for optimization
    if how == 'Sharpe':
        # Maximized on Sharpe Ratio
        ef = EfficientFrontier(mu, S, weight_bounds=bounds) #Here the weight bounds are being used to allow short positions as well
        weights = ef.max_sharpe()
        cleaned_weights = dict(ef.clean_weights())
        print("Weights of an optimal portfolio maximised on Sharpe Ratio:")
        print(cleaned_weights)
        ef.portfolio_performance(verbose = True)
        bpf.getDiscreteAllocations(df, weights)
        plotting.plot_weights(weights)
        return weights 
    elif how == "Vol":
        # Minimized on Volatility
        efi = EfficientFrontier(mu, S, weight_bounds=bounds)
        w = dict(efi.min_volatility())
        print("Weights of an optimal portfolio minimized on Volatilty (Risk):")
        print(w)
        efi.portfolio_performance(verbose = True)
        bpf.getDiscreteAllocations(df, w)
        plotting.plot_weights(w)
        return w
    elif how == "targetRisk":
        #Optimized for a given target risk
        efi = EfficientFrontier(mu, S, weight_bounds=bounds)
        efi.efficient_risk(0.25)
        w = dict(efi.clean_weights())
        if w ==None:
            print("No portfolio possible at the given risk level")
        else:
            print("Weights of an optimal portfolio for given risk:")
            print(w)
            efi.portfolio_performance(verbose = True)
            bpf.getDiscreteAllocations(df, w)
            plotting.plot_weights(w)
        return w
Esempio n. 2
0
def test_custom_convex_objective_market_neutral_efficient_risk():
    target_risk = 0.19
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    ef.efficient_risk(target_risk, market_neutral=True)
    built_in = ef.weights

    # Recreate the market-neutral efficient_risk optimiser using this API
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    ef.add_constraint(lambda x: cp.sum(x) == 0)
    ef.add_constraint(
        lambda x: cp.quad_form(x, ef.cov_matrix) <= target_risk**2)
    ef.convex_objective(lambda x: -x @ ef.expected_returns,
                        weights_sum_to_one=False)
    custom = ef.weights
    np.testing.assert_allclose(built_in, custom, atol=1e-7)
Esempio n. 3
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
Esempio n. 4
0
def mean_var(my_portfolio, vol_max=0.15, perf=True) -> list:
    # changed to take in desired timeline, the problem is that it would use all historical data

    ohlc = yf.download(
        my_portfolio.portfolio,
        start=my_portfolio.start_date,
        end=my_portfolio.end_date,
        progress=False,
    )
    prices = ohlc["Adj Close"].dropna(how="all")
    prices = prices.filter(my_portfolio.portfolio)

    # sometimes we will pick a date range where company isn't public we can't set price to 0 so it has to go to 1
    prices = prices.fillna(1)

    mu = expected_returns.capm_return(prices)
    S = risk_models.CovarianceShrinkage(prices).ledoit_wolf()

    ef = EfficientFrontier(mu, S)
    ef.add_objective(objective_functions.L2_reg,
                     gamma=my_portfolio.diversification)
    if my_portfolio.min_weights is not None:
        ef.add_constraint(lambda x: x >= my_portfolio.min_weights)
    if my_portfolio.max_weights is not None:
        ef.add_constraint(lambda x: x <= my_portfolio.max_weights)
    ef.efficient_risk(vol_max)
    weights = ef.clean_weights()

    wts = weights.items()

    result = []
    for val in wts:
        a, b = map(list, zip(*[val]))
        result.append(b)

    if perf is True:
        ef.portfolio_performance(verbose=True)

    return flatten(result)
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_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_risk_market_neutral_L2_reg():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    ef.add_objective(objective_functions.L2_reg)

    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.10755645826336145, 0.11079556786108302, 0.7902523535340413),
        atol=1e-6,
    )
def test_efficient_risk_market_neutral_L2_reg():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(-1, 1))
    ef.add_objective(objective_functions.L2_reg)

    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.12790320789339854, 0.1175336636355454, 0.9180621496492316),
        atol=1e-6,
    )
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
Esempio n. 10
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_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
Esempio n. 12
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
Esempio n. 13
0
ef_maxsharpe = EfficientFrontier(exp_ret, S)
ef_maxsharpe.max_sharpe(risk_free_rate=0.005)
weights_maxsharpe = ef_maxsharpe.clean_weights()
weights_maxsharpe
ef_maxsharpe.portfolio_performance(verbose=True)

# max quadratic utility
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
Esempio n. 14
0
 'MA': 0.0236174643376172,
 'PFE': 0.1,
 'JPM': 0.0044154412364586,
 'SBUX': 0.0453107516879149}

Expected annual return: 22.7%
Annual volatility: 12.7%
Sharpe Ratio: 1.63
"""

# A long/short portfolio maximising return for a target volatility of 10%,
# with a shrunk covariance matrix risk model
shrink = risk_models.CovarianceShrinkage(df)
S = shrink.ledoit_wolf()
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))
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)
Esempio n. 15
0
pd.Series(weights).plot.pie(figsize=(10, 10))

# In[21]:
"""
As we may check from the output, only part of the stocks compounding the Ibovespa index were selected to
be part of our SP maximised portfolio. Let's now conduct some exercises, obtaining other portfolios
for different risks. Let's remember that, according to the model for a long-only portfolio, the investor
would maximise the SP by taking 11.4% of expected risk, or volatility. What if the investor
is a risk-lover, and is willing to invest in a riskier portfolio to increase the odds of higher returns?
"""

# In[22]:

ef = EfficientFrontier(mu, S)
ef.efficient_risk(target_volatility=0.15)
weights = ef.clean_weights()
weights

# In[23]:

num_small = len([k for k in weights if weights[k] <= 1e-4])
print(f"{num_small}/{len(ef.tickers)} ticker have zero weight")

# In[24]:

ef.portfolio_performance(verbose=True)

# In[25]:
"""
Comparing this portfolio with 15% of risk, higher than the natural portfolio maximising the SP for the lowest 
Esempio n. 16
0
 'MA': 0.0236174643376172,
 'PFE': 0.1,
 'JPM': 0.0044154412364586,
 'SBUX': 0.0453107516879149}

Expected annual return: 22.7%
Annual volatility: 12.7%
Sharpe Ratio: 1.63
"""

# A long/short portfolio maximising return for a target volatility of 10%,
# with a shrunk covariance matrix risk model
shrink = risk_models.CovarianceShrinkage(df)
S = shrink.ledoit_wolf()
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))
weights = ef.efficient_risk(target_risk=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)
Esempio n. 17
0
def generate_outlook(t):
    df = pd.read_csv("index-125.csv", index_col=None, header=0)## read index
    d2=get_prices(df)# put index in correct way
    
    ###build dates
    w="-05-27"
    a=t+w
    x=str(pd.to_numeric(a[:4])+1)+a[4:]
    y=str(pd.to_numeric(a[:4])+2)+a[4:]
    
    ##find index returns
    index_t0=d2.loc[a:x]
    d3=index_t0.sort_index()
    returns3 =d3.iloc[:,0]
    returns3=pd.to_numeric(returns3)
    index_t0 = raw_return(prices=returns3, lag=True)
    target=qs.stats.volatility(index_t0)

    #for protfolio for t0
    d1=pd.read_csv("prices.csv",parse_dates=True, index_col="תאריך")##read data
    stocks_t0=d1.dropna(thresh=len(d1) , axis=1)
    m1 = expected_returns.mean_historical_return(stocks_t0)
    m2=m1[m1 < m1.quantile(.95)]##drop top 5%
    stocks_t0=stocks_t0[m2.index]
    stocks_t0=stocks_t0.sort_index()
    stocks_t0=stocks_t0.loc[a:x]
    stocks_t0=stocks_t0.dropna(thresh=len(stocks_t0) , axis=1)
    stocks_t0=stocks_t0.sort_index(ascending=False)

    
    S=risk_models.risk_matrix(stocks_t0,frequency=len(stocks_t0))
    mu=expected_returns.mean_historical_return(stocks_t0,frequency=len(stocks_t0))
    ef = EfficientFrontier(mu, S)
    ##target=target+0.017##use this if target is not correct
    weights = ef.efficient_risk(target_volatility=target)##build weights for EF
    ef.portfolio_performance(verbose=True)
    wei=pd.Series(weights)#change to pandas series

    
    d7=stocks_t0.pct_change().dropna()
    d7=d7[wei.index]
    returns1=wei*d7
    d8=returns1.sum(axis=1)
    portfolio_t0=d8.sort_index()
    name_index_t0="index_t0"+str(t)+".html"
    name_portfolio_t0="portfolio_t0"+str(t)+".html"
    qs.reports.html(index_t0,output=name_index_t0)
    qs.reports.html(portfolio_t0,output=name_portfolio_t0)
    
        #year t1
    df3=d1.dropna(thresh=len(d1) , axis=1)
    df3=df3.sort_index()
    stocks_t0=df3.loc[x:y]
    stocks_returns = raw_return(prices=stocks_t0,lag=True)
    new_rets=stocks_returns[wei.index]
    protfiolio=wei*new_rets
    port_t1=protfiolio.sum(axis=1)
    

    df = pd.read_csv("index-125.csv", index_col=None, header=0)
    d2=get_prices(df)
    index_t1=d2.loc[x:y]
    index_t1=index_t1.sort_index()

    returns3 =index_t1.iloc[:,0]
    returns3=pd.to_numeric(returns3)
    index_t1 = raw_return(prices=returns3, lag=True)
    
    qs.reports.metrics(port_t1,mode='full')
    name_index_t1="index_t1"+str(t)+".html"
    name_portfolio_t1="portfolio_t1"+str(t)+".html"
    name_compare_graph="compare_graph_t1"+str(t)+".html"
    qs.reports.html(index_t1,output=name_index_t1)
    qs.reports.html(port_t1,output=name_portfolio_t1)
    qs.reports.html(port_t1,index_t1,output=name_compare_graph)