def test_exp_cov_matrix(): df = get_data() S = risk_models.exp_cov(df) assert S.shape == (20, 20) assert S.index.equals(df.columns) assert S.index.equals(S.columns) assert S.notnull().all().all() S2 = risk_models.exp_cov(df, frequency=2) pd.testing.assert_frame_equal(S / 126, S2)
def test_exp_cov_limits(): df = get_data() sample_cov = risk_models.sample_cov(df) S = risk_models.exp_cov(df) assert not np.allclose(sample_cov, S) # As span gets larger, it should tend towards sample covariance S2 = risk_models.exp_cov(df, span=1e20) assert np.abs(S2 - sample_cov).max().max() < 1e-3
def test_exp_cov_matrix(): df = get_data() S = risk_models.exp_cov(df) assert S.shape == (20, 20) assert S.index.equals(df.columns) assert S.index.equals(S.columns) assert S.notnull().all().all() S2 = risk_models.exp_cov(df, frequency=2) pd.testing.assert_frame_equal(S / 126, S2)
def test_exp_cov_limits(): df = get_data() sample_cov = risk_models.sample_cov(df) S = risk_models.exp_cov(df) assert not np.allclose(sample_cov, S) # As span gets larger, it should tend towards sample covariance S2 = risk_models.exp_cov(df, span=1e20) assert np.abs(S2 - sample_cov).max().max() < 1e-3
def test_exp_cov_matrix(): df = get_data() S = risk_models.exp_cov(df) assert S.shape == (20, 20) assert S.index.equals(df.columns) assert S.index.equals(S.columns) assert S.notnull().all().all() assert risk_models._is_positive_semidefinite(S) S2 = risk_models.exp_cov(df, frequency=2) pd.testing.assert_frame_equal(S / 126, S2) # Cover that it works on np.ndarray, with a warning with pytest.warns(RuntimeWarning): S2_np = risk_models.exp_cov(df.to_numpy(), frequency=2) np.testing.assert_equal(S2_np, S2.to_numpy()) # Too short a span causes a warning. with pytest.warns(UserWarning): risk_models.exp_cov(df, frequency=2, span=9)
def portfolio_optimization(): optimal_path = "optimal_weights.txt" if not os.path.exists(optimal_path): data_path = os.path.join("tickers_data", "all_data.csv") if not os.path.exists(data_path): data = get_data.load_data( ) # [["Ticker", "close"]].groupby(["Ticker"]).T else: data = pd.read_csv(data_path) data_series = pd.pivot_table(data, index="datetime", columns="Ticker", values="close") # print(data_series.head()) mu = expected_returns.ema_historical_return(data_series) cov = risk_models.exp_cov(data_series) # plotting.plot_covariance(cov, plot_correlation=True) # print(mu, cov) ef = efficient_frontier.EfficientFrontier(mu, cov, weight_bounds=(0, 1)) ef.add_objective(objective_functions.L2_reg, gamma=1) ef.max_sharpe(0.02) weights_portfolio = ef.weights # ef.max_sharpe(risk_free_rate=0.002) # ef.max_sharpe() dict_keys = data_series.columns.values.tolist() # print(dict_keys) weights = {} for key, value in zip(dict_keys, weights_portfolio): # print(f"{key} - {value}") weights[key] = value # print("SORTED WEIGHTS") sorted_weights = dict( sorted(weights.items(), key=lambda item: item[1], reverse=True)) '''for key in sorted_weights.keys(): print(f"{key} - {sorted_weights[key]}") ''' cleaned_weights = { k: v for k, v in sorted_weights.items() if v > 10e-4 } with open(optimal_path, "w") as file: file.write(json.dumps(cleaned_weights)) # plt.pie(cleaned_weights.values(), labels=cleaned_weights.keys()) # plt.show() else: with open(optimal_path, "r") as file: cleaned_weights = json.loads(file.read()) return cleaned_weights
def test_cla_custom_bounds(): bounds = [(0.01, 0.13), (0.02, 0.11)] * 10 cla = CLA(*setup_cla(data_only=True), weight_bounds=bounds) df = get_data() cla.cov_matrix = risk_models.exp_cov(df).values w = cla.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(cla.tickers) np.testing.assert_almost_equal(cla.weights.sum(), 1) assert (0.01 <= cla.weights[::2]).all() and (cla.weights[::2] <= 0.13).all() assert (0.02 <= cla.weights[1::2]).all() and (cla.weights[1::2] <= 0.11).all() # Test polymorphism of the weight_bounds param. bounds2 = ([bounds[0][0], bounds[1][0]] * 10, [bounds[0][1], bounds[1][1]] * 10) cla2 = CLA(*setup_cla(data_only=True), weight_bounds=bounds2) cla2.cov_matrix = risk_models.exp_cov(df).values w2 = cla2.min_volatility() assert dict(w2) == dict(w)
def test_cla_max_sharpe_exp_cov(): df = get_data() cla = setup_cla() cla.cov_matrix = risk_models.exp_cov(df).values w = cla.max_sharpe() assert isinstance(w, dict) assert set(w.keys()) == set(cla.tickers) np.testing.assert_almost_equal(cla.weights.sum(), 1) np.testing.assert_allclose( cla.portfolio_performance(), (0.32971891062187103, 0.17670121760851704, 1.7527831149871063), )
def test_ef_plot(): df = get_data() rets = expected_returns.mean_historical_return(df) S = risk_models.exp_cov(df) cla = CLA(rets, S) ax = Plotting.plot_efficient_frontier(cla, showfig=False) assert len(ax.findobj()) == 137 ax = Plotting.plot_efficient_frontier(cla, show_assets=False, showfig=False) assert len(ax.findobj()) == 149
def test_cla_min_volatility_exp_cov_short(): cla = CLA(*setup_cla(data_only=True), weight_bounds=(-1, 1)) df = get_data() cla.cov_matrix = risk_models.exp_cov(df).values w = cla.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(cla.tickers) np.testing.assert_almost_equal(cla.weights.sum(), 1) np.testing.assert_allclose( cla.portfolio_performance(), (0.23215576461823062, 0.1325959061825329, 1.6000174569958052), )
def test_cla_plot_ax(): plt.figure() df = get_data() rets = expected_returns.mean_historical_return(df) S = risk_models.exp_cov(df) cla = CLA(rets, S) fig, ax = plt.subplots(figsize=(12, 10)) plotting.plot_efficient_frontier(cla, ax=ax) assert len(ax.findobj()) == 143 plt.close() plt.close()
def test_cla_min_volatility_exp_cov_short(): cla = CLA(*setup_cla(data_only=True), weight_bounds=(-1, 1)) df = get_data() cla.cov_matrix = risk_models.exp_cov(df).values w = cla.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(cla.tickers) np.testing.assert_almost_equal(cla.weights.sum(), 1) np.testing.assert_allclose( cla.portfolio_performance(), (0.2634735528776959, 0.13259590618253303, 1.8362071642131053), )
def test_cla_max_sharpe_exp_cov(): df = get_data() cla = setup_cla() cla.cov_matrix = risk_models.exp_cov(df).values w = cla.max_sharpe() assert isinstance(w, dict) assert set(w.keys()) == set(cla.tickers) np.testing.assert_almost_equal(cla.weights.sum(), 1) np.testing.assert_allclose( cla.portfolio_performance(), (0.3619453128519127, 0.1724297730592084, 1.9830990135009723), )
def test_max_sharpe_exp_cov(): df = get_data() ef = setup_efficient_frontier() ef.cov_matrix = risk_models.exp_cov(df) w = ef.max_sharpe() assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) assert all([i >= 0 for i in w.values()]) np.testing.assert_allclose( ef.portfolio_performance(), (0.3678835305574766, 0.17534146043561463, 1.9840346355802103))
def test_cla_custom_bounds(): bounds = [(0.01, 0.13), (0.02, 0.11)] * 10 cla = CLA(*setup_cla(data_only=True), weight_bounds=bounds) df = get_data() cla.cov_matrix = risk_models.exp_cov(df).values w = cla.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(cla.tickers) np.testing.assert_almost_equal(cla.weights.sum(), 1) assert (0.01 <= cla.weights[::2]).all() and (cla.weights[::2] <= 0.13).all() assert (0.02 <= cla.weights[1::2]).all() and (cla.weights[1::2] <= 0.11).all()
def test_max_sharpe_exp_cov(): df = get_data() ef = setup_efficient_frontier() ef.cov_matrix = risk_models.exp_cov(df) w = ef.max_sharpe() 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_allclose( ef.portfolio_performance(), (0.3678817256187322, 0.1753405505478982, 1.9840346373481956), )
def test_max_sharpe_exp_cov(): df = get_data() ef = setup_efficient_frontier() ef.cov_matrix = risk_models.exp_cov(df) w = ef.max_sharpe() 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_allclose( ef.portfolio_performance(), (0.33700887443850647, 0.1807332515488447, 1.7540152225548384), )
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 test_min_volatility_exp_cov_L2_reg(): df = get_data() ef = setup_efficient_frontier() ef.add_objective(objective_functions.L2_reg) ef.cov_matrix = risk_models.exp_cov(df) 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_allclose( ef.portfolio_performance(), (0.2434082300792007, 0.17835412793427002, 1.2526103694192867), )
def test_min_volatility_exp_cov_L2_reg(): df = get_data() ef = setup_efficient_frontier() ef.gamma = 1 ef.cov_matrix = risk_models.exp_cov(df) w = ef.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) assert all([i >= 0 for i in w.values()]) np.testing.assert_allclose( ef.portfolio_performance(), (0.24340406492258035, 0.17835396894670616, 1.2525881326999546))
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) assert set(w.keys()) == set(ef.expected_returns.index) 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.39089308906686077, 0.19, 1.9520670176494717), 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_cla_plot(): plt.figure() df = get_data() rets = expected_returns.mean_historical_return(df) S = risk_models.exp_cov(df) cla = CLA(rets, S) ax = plotting.plot_efficient_frontier(cla, showfig=False) assert len(ax.findobj()) == 143 plt.clf() ax = plotting.plot_efficient_frontier(cla, show_assets=False, showfig=False) assert len(ax.findobj()) == 161 plt.clf() plt.close()
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 handle_data(context, data): date = data.today() if date in context.balance_dates: temp = {} for code in context.stocks: history_price = data.history_bars(code, context.expected_return_days, '1d', 'close') if history_price is not None: temp.update({code: history_price}) history_prices = pd.DataFrame(temp) mu = expected_returns.mean_historical_return(history_prices) if context.cov_method == 'sample': S = risk_models.sample_cov(history_prices) elif context.cov_method == 'semi': S = risk_models.semicovariance(history_prices) elif context.cov_method == 'exp_cov': S = risk_models.exp_cov(history_prices) ef = EfficientFrontier(mu, S) if context.opt_criterion == 'max_sharpe': weights = ef.max_sharpe() elif context.opt_criterion == 'efficient_return': weights = ef.efficient_return(context.target_return) elif context.opt_criterion == 'efficient_risk': weights = ef.efficient_risk(context.targe_risk, context.risk_free_rate) elif context.opt_criterion == 'min_volatility': weights = ef.min_volatility() if context.cleaned_weights is True: weights = ef.clean_weights() weight = [] prices = [] for code in context.stocks: weight.append(weights[code]) prices.append(data.latest_price(code, "1d")) data.order_target_percent(context.stocks, weight, prices)
def handle_bar(context, api): date = api.now() #if date in context.balance_dates: history_prices = {} for stock in context.stocks: history_price = api.history_bars(stock, context.expected_return_days, '1d', 'close') history_prices.update({stock: history_price}) history_prices = pd.DataFrame(history_prices) mu = expected_returns.mean_historical_return(history_prices) if context.cov_method == 'sample': S = risk_models.sample_cov(history_prices) elif context.cov_method == 'semi': S = risk_models.semicovariance(history_prices) elif context.cov_method == 'exp_cov': S = risk_models.exp_cov(history_prices) ef = EfficientFrontier(mu, S) if context.opt_criterion == 'max_sharpe': weights = ef.max_sharpe() elif context.opt_criterion == 'efficient_return': weights = ef.efficient_return(context.target_return) elif context.opt_criterion == 'efficient_risk': weights = ef.efficient_risk(context.targe_risk, context.risk_free_rate) elif context.opt_criterion == 'min_volatility': weights = ef.min_volatility() if context.cleaned_weights is True: weights = ef.clean_weights() prices = [] weight = [] for stock in context.stocks: weight.append(weights[stock]) prices.append(api.latest_price(stock, "1d")) api.order_target_percent(stocks, weight, prices)
def get_max_sharpe_recent_weights(self, exp_span, target_return=2.0): mu = expected_returns.ema_historical_return(self.pf, span=exp_span, frequency=252) sigma = risk_models.exp_cov(self.pf, span=exp_span, frequency=252) ef = EfficientFrontier(mu, sigma) try: # ef.efficient_return(target_return) ef.max_sharpe() clean_weights_maxSR = ef.clean_weights() print('the optimal weights for recent max_SR portfolio is \n{}'. format(clean_weights_maxSR)) ef.portfolio_performance(verbose=True) out = [] for weight in list(clean_weights_maxSR.values()): if weight == 0: out.append(0) else: out.append(weight) return out except: return [0] * len(self.stock_list)
# Calculate weights for the maximum Sharpe ratio portfolio raw_weights_maxsharpe = ef.max_sharpe() cleaned_weights_maxsharpe = ef.clean_weights() print(raw_weights_maxsharpe, cleaned_weights_maxsharpe) # Calculate weights for the minimum volatility portfolio raw_weights_minvol = ef.min_volatility() cleaned_weights_minvol = ef.clean_weights() # Show portfolio performance print(cleaned_weights_minvol) ef.portfolio_performance(verbose=True) # Define exponentially weightedSigma and mu using stock_prices Sigma = risk_models.exp_cov(stock_prices, span=180, frequency=252) mu = expected_returns.ema_historical_return(stock_prices, frequency=252, span=180) # Calculate the efficient frontier ef = EfficientFrontier(mu, Sigma) # Calculate weights for the maximum sharpe ratio optimization raw_weights_maxsharpe = ef.max_sharpe() # Show portfolio performance ef.portfolio_performance(verbose=True) # datacamp hack import inspect
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'
plt.show() fig.savefig("Markovitz' portfolio with maximum return.png") # Calculating weights for the minimum volatility portfolio raw_weights_minvol = ef.min_volatility() cleaned_weights_minvol = ef.clean_weights() # Showing portfolio performance print(cleaned_weights_minvol) ef.portfolio_performance(verbose=True) size = list(cleaned_weights_minvol.values()) print(size) plt.pie(size, labels=l, autopct='%1.1f%%') plt.title('Min Risk') plt.show() #Calculating an exponentially weighted portfolio Sigma_ew = risk_models.exp_cov(df, span=180, frequency=252) mu_ew = expected_returns.ema_historical_return(df, frequency=252, span=180) # Calculate the efficient frontier ef_ew = EfficientFrontier(mu_ew, Sigma_ew) # Calculate weights for the maximum sharpe ratio optimization raw_weights_maxsharpe_ew = ef_ew.max_sharpe() # Show portfolio performance ef_ew.portfolio_performance(verbose=True) size = list(raw_weights_maxsharpe_ew.values()) print(size) plt.pie(size, labels=l, autopct='%1.1f%%') plt.title('Max Return EW') plt.show()