def test_min_volatility_vs_max_sharpe(): # Test based on issue #75 expected_returns_daily = pd.Series( [0.043622, 0.120588, 0.072331, 0.056586], index=["AGG", "SPY", "GLD", "HYG"]) covariance_matrix = pd.DataFrame( [ [0.000859, -0.000941, 0.001494, -0.000062], [-0.000941, 0.022400, -0.002184, 0.005747], [0.001494, -0.002184, 0.011518, -0.000129], [-0.000062, 0.005747, -0.000129, 0.002287], ], index=["AGG", "SPY", "GLD", "HYG"], columns=["AGG", "SPY", "GLD", "HYG"], ) ef = EfficientFrontier(expected_returns_daily, covariance_matrix) ef.min_volatility() vol_min_vol = ef.portfolio_performance(risk_free_rate=0.00)[1] ef = EfficientFrontier(expected_returns_daily, covariance_matrix) ef.max_sharpe(risk_free_rate=0.00) vol_max_sharpe = ef.portfolio_performance(risk_free_rate=0.00)[1] assert vol_min_vol < vol_max_sharpe
def min_var(my_portfolio, perf=True) -> list: 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) 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.min_volatility() 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 min_volatility_weights(rets_bl, covar_bl, config): ef = EfficientFrontier(rets_bl, covar_bl, weight_bounds= \ (config['min_position_size'] ,config['max_position_size'])) ef.min_volatility() weights = ef.clean_weights() weights = pd.DataFrame.from_dict(weights, orient='index') weights.columns = ['Min Vol'] return weights, ef
def test_efficient_frontier_expected_returns_list(): """Cover the edge case that the expected_returns param is a list.""" ef = setup_efficient_frontier() ef.min_volatility() ef_r = EfficientFrontier(expected_returns=ef.expected_returns.tolist(), cov_matrix=ef.cov_matrix) ef_r.min_volatility() np.testing.assert_equal(ef.portfolio_performance(), ef_r.portfolio_performance())
def test_clean_weights_short(): ef = setup_efficient_frontier() ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.min_volatility() # In practice we would never use such a high cutoff number_tiny_weights = sum(np.abs(ef.weights) < 0.05) cleaned = ef.clean_weights(cutoff=0.05) cleaned_weights = cleaned.values() clean_number_tiny_weights = sum(abs(i) < 0.05 for i in cleaned_weights) assert clean_number_tiny_weights == number_tiny_weights
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()
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, )
def optimise(portfolio_data): returns = pd.Series(get_returns(portfolio_data)) covariance_matrix = pd.DataFrame(get_cov_matrix(portfolio_data)) ef = EfficientFrontier(returns, covariance_matrix) ef.min_volatility() # max_sharpe or min_volatility cleaned_weights = ef.clean_weights() fix_keys(cleaned_weights, portfolio_data) print(cleaned_weights) ef.save_weights_to_file("weights.csv") # saves to file ef.portfolio_performance(verbose=True)
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)
def test_custom_bounds(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(0.02, 0.13)) ef.min_volatility() np.testing.assert_allclose(ef._lower_bounds, np.array([0.02] * ef.n_assets)) np.testing.assert_allclose(ef._upper_bounds, np.array([0.13] * ef.n_assets)) assert ef.weights.min() >= 0.02 assert ef.weights.max() <= 0.13 np.testing.assert_almost_equal(ef.weights.sum(), 1)
def test_custom_bounds_different_values(): bounds = [(0.01, 0.13), (0.02, 0.11)] * 10 ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=bounds) ef.min_volatility() 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() np.testing.assert_almost_equal(ef.weights.sum(), 1) bounds = ((0.01, 0.13), (0.02, 0.11)) * 10 assert EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=bounds)
def optimMarkowitz(datatrain, datatest, pmin, pmax, optimmodel, returnmodel, riskmodel, Gam, rf): try: if returnmodel == 'historical': mu = expected_returns.mean_historical_return(datatrain) elif returnmodel == 'emahistorical': mu = expected_returns.ema_historical_return(datatrain) if riskmodel == 'historicalcov': S = risk_models.sample_cov(datatrain) elif riskmodel == 'exphistoricalcov': S = risk_models.exp_cov(datatrain) ef = EfficientFrontier(mu, S, weight_bounds=(pmin, pmax)) #gamma>0 permet de forcer l'optimiseur à utiliser plus de titres ef.add_objective(objective_functions.L2_reg, gamma=Gam) if optimmodel == 'min_volatility': ef.min_volatility() elif optimmodel == 'max_sharpe': ef.max_sharpe(risk_free_rate=rf) cleaned_weights = ef.clean_weights() #round and clean ... ef.save_weights_to_file( '/Users/Maxime/AMUNDI/PortMgmnt/ModulePyPortfolioOpt/OptimiseurProjet/weights.csv' ) # save to file perf = ef.portfolio_performance(verbose=True, risk_free_rate=rf) weightsfinal = pd.read_csv( '/Users/Maxime/AMUNDI/PortMgmnt/ModulePyPortfolioOpt/OptimiseurProjet/weights.csv', header=None) #For the following chart poids = weightsfinal.to_numpy() poids = poids[:, 1] RankedDataFrame = pd.DataFrame(index=datatest.index) for i, rows in weightsfinal.iterrows(): RankedDataFrame[rows[0]] = datatest[rows[0]] weightsfinal.rename(columns={ 0: ' Asset Class', 1: 'Poids' }, inplace=True) weightsfinal['Poids'] = round(weightsfinal['Poids'] * 100, 4) except ValueError: print('Le modèle spécifié est incorrect') return poids, RankedDataFrame, cleaned_weights, S, mu, perf
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_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 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 lv_backtest(self): self.strate = "Low Volatility" for i in range(len(self.cov_list)): sample_cov = pd.DataFrame(self.cov_list[i]) df = self.ret_list[i] mu = df.mean() ef = EfficientFrontier(mu, sample_cov) self.weights.append(ef.min_volatility())
def test_min_volatility_no_rets(): # Should work with no rets, see issue #82 df = get_data() S = risk_models.sample_cov(df) ef = EfficientFrontier(None, S) w = ef.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) np.testing.assert_almost_equal(ef.weights.sum(), 1) assert all([i >= 0 for i in w.values()]) np.testing.assert_almost_equal(ef.portfolio_performance()[1], 0.15915084514118694)
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
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_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
def get_portfolio_distribution(watchlist_id): assets = get_assets(watchlist_id) if (len(assets) == 0): aggregate_data = {} aggregate_data['composition'] = "No stocks in the watchlist" aggregate_data['Expected annual return:'] = "0" aggregate_data['Annual volatility:'] = "0" aggregate_data['Sharpe Ratio:'] = "0" return aggregate_data tickers = [] for stock_x in assets: # Create empty dict for stock data tickers.append(f"{stock_x[1]}.AX") yf.pdr_override() x = datetime.datetime.now() Previous_Date = datetime.datetime.today() - datetime.timedelta(days=365) data = pdr.get_data_yahoo(tickers, start=Previous_Date.strftime('%Y-%m-%d'), end=x.strftime('%Y-%m-%d')) data = data['Close'] mu = expected_returns.mean_historical_return(data) S = risk_models.sample_cov(data) ef = EfficientFrontier(mu, S) raw_weights = ef.min_volatility() cleaned_weights = ef.clean_weights() perf = ef.portfolio_performance() aggregate_data = {} aggregate_data['dictionary_composition'] = cleaned_weights.items() aggregate_data['Expected_annual_return:'] = f"Expected annual return: {perf[0]*100:.2f}%" aggregate_data['Annual_volatility:'] = f"Annual volatility: {perf[1]*100:.2f}%" aggregate_data['Sharpe_Ratio:'] = f"Sharpe Ratio: {perf[2]:.2f}"" return aggregate_data
T = risk_models.CovarianceShrinkage(prices).ledoit_wolf() plotting.plot_covariance(S) plotting.plot_covariance(T) #equal weights initial_weights = np.array([1 / len(tickers)] * len(tickers)) print(initial_weights) #transaction cost objective ef = EfficientFrontier(mum, T) # 1% broker commission ef.add_objective(objective_functions.transaction_cost, w_prev=initial_weights, k=0.01) ef.min_volatility() weights = ef.clean_weights() weights # smaller broker comms ef = EfficientFrontier(mu, S) ef.add_objective(objective_functions.transaction_cost, w_prev=initial_weights, k=0.001) ef.min_volatility() weights = ef.clean_weights() weights #limit number of zero weights ef = EfficientFrontier(mu, S) ef.add_objective(objective_functions.transaction_cost,
def BLmain(): #Excell Call sht = xw.Book.caller().sheets['Optim'] shtdata = xw.Book.caller().sheets['Data'] sht.range('J17').value = 'Optimizing...' #Clear Values sht.range('L23').expand().clear_contents() shtdata.range('A1').expand().clear_contents() shtdata.range('J1').expand().clear_contents() #Set variables from excel rf = sht.range('J10').value MinWeight = sht.range('J11').value MaxWeight = sht.range('J12').value Delta = sht.range('J13').value Tau = sht.range('J14').value Output = sht.range('J15').value ModelOptim = sht.range('J8').value RiskModel = sht.range('J9').value listticker = xw.Range('B3').expand().value indexname = sht.range('J7').value startdate = sht.range('J3').value enddate = sht.range('J6').value EFBool = sht.range('J16').value traintestdate = sht.range( 'J4' ).value #Dataset is divided in two sub: train (optimization) and test for backtest #Initializing train, test = initialize(startdate, enddate, traintestdate, listticker) trainindex, testindex = initializeIndex(startdate, enddate, traintestdate, indexname) #for risk aversion #Black Litterman if RiskModel == 'historicalcov': S = risk_models.sample_cov(train) elif RiskModel == 'exphistoricalcov': S = risk_models.exp_cov(train) if Delta != None: delta = Delta else: delta = black_litterman.market_implied_risk_aversion(trainindex, risk_free_rate=rf) s = data.get_quote_yahoo(listticker)['marketCap'] mcaps = {tick: mcap for tick, mcap in zip(listticker, s) } #Dictionnary of Market Cap for each stock #Expected returns implied from the market prior = black_litterman.market_implied_prior_returns(mcaps, delta, S, risk_free_rate=rf) views, picking = createviews(listticker) bl = BlackLittermanModel(S, Q=views, P=picking, pi=prior, tau=Tau) rets = bl.bl_returns() cov = bl.bl_cov() #Two ways of displaying outputs: either using Optimizer, either returning implied weights if Output == 'Optimization': ef = EfficientFrontier(rets, S, weight_bounds=(MinWeight, MaxWeight)) #RiskModel if ModelOptim == 'min_volatility': raw_weights = ef.min_volatility() elif ModelOptim == 'max_sharpe': raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() finalw = [cleaned_weights.get(i, 1) for i in listticker] perf = ef.portfolio_performance(verbose=True, risk_free_rate=rf) sht.range('H21').value = perf elif Output == 'Return-Implied-Weight': bl.bl_weights(delta) weights = bl.clean_weights() finalw = [weights.get(i, 1) for i in listticker] finalr = [rets.get(i, 1) for i in listticker] #E(R) from BL #Display results sht.range('L23').options(transpose=True).value = listticker sht.range('M23').options(transpose=True).value = finalw sht.range('N23').options(transpose=True).value = finalr #Copy Data in Data Range shtdata.range((1, 1)).value = train shtdata.range((1, len(listticker) + 3)).value = test #numshares, left = getoptimprices(test, cleanW, InitialAmountInPortfolio) #Visualisation sht.charts['BLweights'].set_source_data( sht.range((23, 12), (22 + len(listticker), 13))) CorrMap(sht, 'CorrMatPrior', S, 'coolwarm') CorrMap(sht, 'CorrMatBL', cov, 'YlGn') if EFBool == "YES": effrontier(rets, S, sht, 'EFBL') #Done sht.range('J17').value = 'Optimization Done'
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
""" Expected annual return: 33.0% Annual volatility: 21.7% Sharpe Ratio: 1.43 Discrete allocation: {'AAPL': 5.0, 'FB': 11.0, 'BABA': 5.0, 'AMZN': 1.0, 'BBY': 7.0, 'MA': 14.0, 'PFE': 50.0, 'SBUX': 5.0} Funds remaining: $8.42 """ # Long-only minimum volatility portfolio, with a weight cap and regularisation # e.g if we want at least 15/20 tickers to have non-neglible weights, and no # asset should have a weight greater than 10% ef = EfficientFrontier(mu, S, weight_bounds=(0, 0.10)) ef.add_objective(objective_functions.L2_reg, gamma=0.1) weights = ef.min_volatility() print(weights) ef.portfolio_performance(verbose=True) """ {'GOOG': 0.0584267903998156, 'AAPL': 0.0369081348579286, 'FB': 0.0997609043032782, 'BABA': 0.1, 'AMZN': 0.0, 'GE': 0.0646457157900559, 'AMD': 0.0, 'WMT': 0.1, 'BAC': 0.0, 'GM': 0.1, 'T': 0.1, 'UAA': 0.0,
y=df.columns, ), layout = layout) fig.show() fig.write_image(fr"{output_dir}\CorrelationHeatmap.png") #py.iplot(fig, filename='Beta/Untreated_Heatmap') #fig.write_image(fr"{output_dir3}\{name}_range_graph.png") # min volatility portfolio ef_minvol = EfficientFrontier(exp_ret, S) # ef.add_objective(objective_functions.transaction_cost, # 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()