def max_quad_utility_weights(rets_bl, covar_bl, config): print('Begin max quadratic utility optimization') returns, sigmas, weights, deltas = [], [], [], [] for delta in np.arange(1, 10, 1): ef = EfficientFrontier(rets_bl, covar_bl, weight_bounds= \ (config['min_position_size'] ,config['max_position_size'])) ef.max_quadratic_utility(delta) ret, sigma, __ = ef.portfolio_performance() weights_vec = ef.clean_weights() returns.append(ret) sigmas.append(sigma) deltas.append(delta) weights.append(weights_vec) fig, ax = plt.subplots() ax.plot(sigmas, returns) for i, delta in enumerate(deltas): ax.annotate(str(delta), (sigmas[i], returns[i])) plt.xlabel('Volatility (%) ') plt.ylabel('Returns (%)') plt.title('Efficient Frontier for Max Quadratic Utility Optimization') plt.show() opt_delta = float( input('Enter the desired point on the efficient frontier: ')) ef = EfficientFrontier(rets_bl, covar_bl, weight_bounds= \ (config['min_position_size'] ,config['max_position_size'])) ef.max_quadratic_utility(opt_delta) opt_weights = ef.clean_weights() opt_weights = pd.DataFrame.from_dict(opt_weights, orient='index') opt_weights.columns = ['Max Quad Util'] return opt_weights, ef
def test_max_quadratic_utility_market_neutral(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.max_quadratic_utility(market_neutral=True) np.testing.assert_almost_equal(ef.weights.sum(), 0) np.testing.assert_allclose( ef.portfolio_performance(), (1.13434841843883, 0.9896404148973286, 1.1260134506071473), )
def test_max_quadratic_utility_market_neutral(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.max_quadratic_utility(market_neutral=True) np.testing.assert_almost_equal(ef.weights.sum(), 0) np.testing.assert_allclose( ef.portfolio_performance(), (1.248936321062371, 1.0219175004907117, 1.2025787996313317), )
def test_max_quadratic_utility_with_shorts(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.max_quadratic_utility() np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (1.3318330413711252, 1.0198436183533854, 1.2863080356272452), )
def test_max_quadratic_utility_with_shorts(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.max_quadratic_utility() np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (1.4170505733098597, 1.0438577623242156, 1.3383533884915872), )
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
# w_prev=initial_weights, k=0.01) ef_minvol.min_volatility() weights_minvol = ef_minvol.clean_weights() weights_minvol ef_minvol.portfolio_performance(verbose=True) # max sharpe portfolio 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()
def update_graph1(n_clicks, stock_ticker, lookforward_period, risk): exp_ret = pd.Series() content1 = list(stock_ticker) data3 = pd.DataFrame() for contents in content1: data3 = pd.concat([ data3, yf.download(f"{contents}", start="2015-01-01", end="2020-01-01").iloc[:, 4] ], axis=1, sort=False) data3.columns = content1 data4 = data3.dropna(how="all") data4 = data4.dropna(axis='columns', how="any") cumulative_ret_data = pd.DataFrame() for contents in content1: cumulative_ret_data[f"{contents}"] = ( 1 + (data4[f"{contents}"]).pct_change()).cumprod() cumulative_ret_data = cumulative_ret_data.fillna(1) S = risk_models.sample_cov(data4) if lookforward_period == 2: exp_ret = pypfopt.expected_returns.mean_historical_return( data4, frequency=500) if (risk == 2): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_sharpe(risk_free_rate=0.02) elif (risk == 3): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_quadratic_utility(risk_aversion=0.00001, market_neutral=False) else: ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.min_volatility() elif (lookforward_period == 3): exp_ret = pypfopt.expected_returns.mean_historical_return( data4, frequency=750) if (risk == 2): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_sharpe(risk_free_rate=0.02) elif (risk == 3): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_quadratic_utility(risk_aversion=0.00001, market_neutral=False) else: ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.min_volatility() else: exp_ret = pypfopt.expected_returns.mean_historical_return( data4, frequency=250) if (risk == 2): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_sharpe(risk_free_rate=0.02) elif (risk == 3): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_quadratic_utility(risk_aversion=0.00001, market_neutral=False) else: ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.min_volatility() #exp_ret=pypfopt.expected_returns.mean_historical_return(data4, frequency=250) #exp_ret=pypfopt.expected_returns.mean_historical_return(data4, frequency=252) if (risk == 2): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_sharpe(risk_free_rate=0.02) elif (risk == 3): ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.max_quadratic_utility(risk_aversion=0.00001, market_neutral=False) else: ef = EfficientFrontier(exp_ret, S, weight_bounds=(-1, 1), gamma=1) weights_ef = ef.min_volatility() dictlist = [] for key, value in weights_ef.items(): temp = [key, value] dictlist.append(temp) weights = pd.DataFrame(dictlist, columns=['ticker', 'weight']).set_index('ticker') weights = weights.iloc[:, 0] weights = weights.sort_index() weight_list = weights.tolist() HRP_df = weights.multiply(weights, weight_list) HRP_cumu = cumulative_ret_data.reindex( sorted(cumulative_ret_data.columns), axis=1) #sort column by company names HRP_df = HRP_cumu.mul(weight_list, axis=1) HRP_df['final_returns'] = HRP_df.sum(axis=1) fig2 = { # set data equal to traces 'data': [{ 'x': HRP_df.index, 'y': HRP_df["final_returns"], 'name': tic }], # use string formatting to include all symbols in the chart title 'layout': { 'title': ', '.join(stock_ticker) + ' portfolio' } } return fig2