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_max_sharpe_long_weight_bounds(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(0.03, 0.13)) ef.max_sharpe() np.testing.assert_almost_equal(ef.weights.sum(), 1) assert ef.weights.min() >= 0.03 assert ef.weights.max() <= 0.13 bounds = [(0.01, 0.13), (0.02, 0.11)] * 10 ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=bounds) ef.max_sharpe() 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()
def portfolio_opt(self): portfolio = self.portfolio.split(",") df = self.db.load_data(TableName.DAY, time_from=self.time_from, symbols=portfolio) # df = FinI.add_date_col(df) df = df[["close", "sym"]] df2 = df.copy() df2 = df2.drop(columns=["close", "sym"]) for sym in portfolio: df2[sym] = df[df["sym"] == sym]["close"] df2 = df2.drop_duplicates() # df = df.transpose() # df.index = pd.to_datetime(df['date']).astype(int) / 10**9 st.write(df2) # Calculate expected returns and sample covariance mu = expected_returns.mean_historical_return(df2) S = risk_models.sample_cov(df2) # Optimize for maximal Sharp ratio ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() # ef.save_weights_to_file("weights.csv") # saves to file st.write(cleaned_weights) mu, sigma, sharpe = ef.portfolio_performance(verbose=True) st.write("Expected annual return: {:.1f}%".format(100 * mu)) st.write("Annual volatility: {:.1f}%".format(100 * sigma)) st.write("Sharpe Ratio: {:.2f}".format(sharpe))
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 plot_stock_insights(self, scatter=False): ef = EfficientFrontier(self.mu, self.S) weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() cla = CLA(self.mu, self.S) try: eff_front = plotting.plot_efficient_frontier(cla) eff_front.tick_params(axis='both', which='major', labelsize=5) eff_front.tick_params(axis='both', which='minor', labelsize=5) eff_front.get_figure().savefig(os.path.join( self.output_path, "efficient_frontier.png"), dpi=300) except: print("Failed to plot efficient frontier") cov = plotting.plot_covariance(self.S) weights_bar = plotting.plot_weights(cleaned_weights) if self.save_output: cov.tick_params(axis='both', which='major', labelsize=5) cov.tick_params(axis='both', which='minor', labelsize=5) cov.get_figure().savefig(os.path.join(self.output_path, "cov_matrix.png"), dpi=300) weights_bar.tick_params(axis='both', which='major', labelsize=5) weights_bar.tick_params(axis='both', which='minor', labelsize=5) weights_bar.get_figure().savefig(os.path.join( self.output_path, "weights_bar.png"), dpi=300) retscomp = self.stock_prices.pct_change() corrMatrix = retscomp.corr() corr_heat = sns.heatmap(corrMatrix, xticklabels=True, yticklabels=True) plt.title("Corr heatmap") if self.save_output: corr_heat.tick_params(axis='both', which='major', labelsize=5) corr_heat.tick_params(axis='both', which='minor', labelsize=5) fig = corr_heat.get_figure() fig.figsize = (10, 10) fig.savefig(os.path.join(self.output_path, "corr_heatmap.png"), dpi=300) plt.show() if scatter: plt.figure() plt.title("Corr scatter") self.scattermat = pd.plotting.scatter_matrix(retscomp, diagonal='kde', figsize=(10, 10)) if self.save_output: plt.savefig(os.path.join(self.output_path, "corr_scatter.png"), dpi=300) plt.show()
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_max_sharpe_short_semicovariance(): df = get_data() ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.cov_matrix = risk_models.semicovariance(df, benchmark=0) w = ef.max_sharpe() 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.42444834528495234, 0.0898263632679403, 4.50255727350929), )
def test_max_sharpe_short_semicovariance(): df = get_data() ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.cov_matrix = risk_models.semicovariance(df, benchmark=0) w = ef.max_sharpe() 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.3907992623559733, 0.0809285460933456, 4.581810501430255), )
def test_max_sharpe_short_semicovariance(): df = get_data() ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.cov_matrix = risk_models.semicovariance(df, benchmark=0) w = ef.max_sharpe() 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.3564305116656491, 0.07201282488003401, 4.671813836300796), )
def calculate_allocation(self, cash): # if you have cash to allocate to a set of stocks, this function will return how to allocate that # see rebalance_weight to identify most suitable portfolio self.cash = cash ef = EfficientFrontier(self.mu, self.S) weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() latest_prices = get_latest_prices(self.stock_prices) da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value=cash) allocation, leftover = da.lp_portfolio() print("Discrete allocation:", allocation) print("Funds remaining: ${:.2f}".format(leftover))
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.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 build_portfolio_weights(stock_data, weights_filename): # Calculate expected returns and sample covariance if isinstance(stock_data, pd.Series): stock_data = stock_data.to_frame() mu = expected_returns.mean_historical_return(stock_data) S = risk_models.sample_cov(stock_data) # Optimize for maximal Sharpe ratio ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.save_weights_to_file(weights_filename) # saves to file ef.portfolio_performance(verbose=True) return cleaned_weights
def optimise_portfolio(stock_price, Portfolio): returns = stock_price.pct_change().dropna() # Calculate expected returns and sample covariance mu = expected_returns.mean_historical_return(stock_price) S = risk_models.sample_cov(stock_price) # Optimise for maximal Sharpe ratio ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.save_weights_to_file("weights.csv") # saves to file print(cleaned_weights) ef.portfolio_performance(verbose=True) Portfolio.ef = ef Portfolio.mu = mu Portfolio.S = S Portfolio.weights = cleaned_weights
def get_result(l): data = yf.download(tickers=l, period="max", interval="1d", auto_adjust=True) data = data['Close'] mu = expected_returns.mean_historical_return(data) S = CovarianceShrinkage(data).ledoit_wolf() ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() data = [] for x in cleaned_weights.keys(): if cleaned_weights[x] != 0: data.append({'name': x, 'y': cleaned_weights[x]}) answer = {'data': data, 'performance': ef.portfolio_performance()} return answer
def test_max_sharpe_L2_reg_with_shorts(): ef_no_reg = setup_efficient_frontier() ef_no_reg.max_sharpe() initial_number = sum(ef_no_reg.weights > 0.01) ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(None, None)) ef.add_objective(objective_functions.L2_reg) w = ef.max_sharpe() 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.2995338981166366, 0.2234696161770517, 1.2508810052063901), ) new_number = sum(ef.weights > 0.01) assert new_number >= initial_number
def test_max_sharpe_short(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(None, None)) w = ef.max_sharpe() 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.4937195216716211, 0.29516576454651955, 1.6049270564945908), ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.max_sharpe() long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def test_max_sharpe_short(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(None, None)) w = ef.max_sharpe() 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.4072439477276246, 0.24823487545231313, 1.5599900981762558), ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.max_sharpe() long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def test_max_sharpe_L2_reg_with_shorts(): ef_no_reg = setup_efficient_frontier() ef_no_reg.max_sharpe() initial_number = sum(ef_no_reg.weights > 0.01) ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(None, None)) ef.add_objective(objective_functions.L2_reg) w = ef.max_sharpe() 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.3076093180094401, 0.22415982749409985, 1.2830546901496447), ) new_number = sum(ef.weights > 0.01) assert new_number >= initial_number
def Optimize(array): df = pd.read_csv('latest_stock_prices.csv', parse_dates=True, index_col="date") data = df[df.columns.intersection(array)] data.dtypes mu = expected_returns.mean_historical_return(data) S = risk_models.sample_cov(data) # Optimise for maximal Sharpe ratio ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.save_weights_to_file("weights.csv") # saves to file print(cleaned_weights) ef.portfolio_performance(verbose=True)
def run_portfolio_optimization() -> None: df_corr = _load_df_correlation_economist() df_corr = df_corr.set_index(df_corr['state']) df_mu_sigma = _compute_df_mu_sigma_return() df_mu_sigma = df_mu_sigma.sort_values('STATE_INIT') df_corr = df_corr.loc[df_mu_sigma['STATE_INIT']][ df_mu_sigma['STATE_INIT'].values] # Covariance = diag(S) * Corr * diag(S) # Note: This isn't going to be exactly correct since the Economist correlations are not the # market returns, but let's assume they're roughly equal df_cov = pandas.DataFrame(np.matmul( np.matmul(np.diag(df_mu_sigma['STD_D_YES'].values), df_corr.values), np.diag(df_mu_sigma['STD_D_YES'].values)), index=df_mu_sigma['STATE_INIT'].values, columns=df_mu_sigma['STATE_INIT'].values) sns.heatmap(df_corr, fmt=',.1f') plt.title('Correlation matrix of state performance') plt.show() df_mu_sigma.to_csv(os.path.join(_data_dir(), 'mu_sigma.csv')) df_cov.to_csv(os.path.join(_data_dir(), 'vcov_matrix.csv')) ef = EfficientFrontier( expected_returns=df_mu_sigma.set_index('STATE_INIT')['MU_D_YES'], cov_matrix=df_cov) raw_weights = ef.max_sharpe(risk_free_rate=0) df_weights = pandas.DataFrame([(state, w) for state, w in ef.clean_weights().items()], columns=['STATE_INIT', 'WEIGHT']) df_weights[df_weights['WEIGHT'].gt(0)].set_index( 'STATE_INIT')['WEIGHT'].plot.barh() plt.title('Optimal portfolio weights (D win)') plt.ylabel('State market') plt.xlabel('Weight') sns.despine() plt.show() print(df_weights.sort_values('WEIGHT', ascending=False)) ef.portfolio_performance(verbose=True) df_weights.to_csv('portfolio_weights.csv', index=False)
def optimise_portfolio(self, use_filter=True): self.stock_prices.fillna(value=self.stock_prices.mean(), inplace=True) self.stock_prices = self.stock_prices.dropna(axis=1, how='any') risk_free_rate = 0.02 risk_aversion = 0.5 self.filter_stock_prices() self.holding = self.holding[self.holding.Symbol.isin( self.fil_stock_prices.keys())] if use_filter: self.mu = expected_returns.mean_historical_return( self.fil_stock_prices) self.S = risk_models.sample_cov(self.fil_stock_prices) else: self.mu = expected_returns.mean_historical_return( self.stock_prices) self.S = risk_models.sample_cov(self.stock_prices) self.index_return = self.stock_prices.sum( axis=1)[-1] / self.stock_prices.sum(axis=1)[0] self.index_price = self.stock_prices.sum(axis=1) returns = self.stock_prices.pct_change().dropna() # Calculate expected returns and sample covariance #calculate old portfolio position # Optimise for maximal Sharpe ratio ef = EfficientFrontier(self.mu, self.S) # raw_weights = ef.max_quadratic_utility(risk_aversion) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.save_weights_to_file(os.path.join(self.output_path, "weights.csv")) # saves to file print(cleaned_weights) ef.portfolio_performance(verbose=True) self.ef = ef self.weights = cleaned_weights self.rebalance_weight()
def cli(risk_free_rate, start, span, verbose, tickers): # Read in price data thelen = len(tickers) price_data = [] successful_tickers = [] for ticker in range(thelen): click.echo(tickers[ticker]) try: prices = web.DataReader(tickers[ticker], start=start, data_source='yahoo') if verbose >= 1: click.echo(tickers[ticker] + ':') click.echo(prices) price_data.append(prices.assign(ticker=ticker)[['Adj Close']]) successful_tickers.append(tickers[ticker]) except: pass df = pd.concat(price_data, axis=1) df.columns = successful_tickers df.head() #Checking if any NaN values in the data nullin_df = pd.DataFrame(df, columns=tickers) print(nullin_df.isnull().sum()) # Calculate expected returns and sample covariance mu = expected_returns.ema_historical_return(df, span=span) S = risk_models.sample_cov(df) # Optimise for maximal Sharpe ratio ef = EfficientFrontier( mu, S) #weight bounds in negative allows shorting of stocks raw_weights = ef.max_sharpe(risk_free_rate=risk_free_rate) cleaned_weights = ef.clean_weights() click.echo(cleaned_weights) ef.portfolio_performance(verbose=True)
def efficient_frontier(my_portfolio, 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") df = 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 df = df.fillna(1) mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df) # optimize for max sharpe ratio ef = EfficientFrontier(mu, S) 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) weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() wts = cleaned_weights.items() result = [] for val in wts: a, b = map(list, zip(*[val])) result.append(b) if perf is True: pred = ef.portfolio_performance(verbose=True) return flatten(result)
def show_ef(stocks: List[str], other_args: List[str]): """Display efficient frontier Parameters ---------- stocks : List[str] List of the stocks to be included in the weights other_args : List[str] argparse other args """ parser = argparse.ArgumentParser( add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, prog="ef", description="""This function plots random portfolios based on their risk and returns and shows the efficient frontier.""", ) parser.add_argument( "-p", "--period", default="3mo", dest="period", help="period to get yfinance data from", choices=period_choices, ) parser.add_argument( "-n", "--number-portfolios", default=300, type=check_non_negative, dest="n_port", help="number of portfolios to simulate", ) try: if other_args: if "-" not in other_args[0]: other_args.insert(0, "-n") ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return if len(stocks) < 2: print( "Please have at least 2 loaded tickers to calculate weights.\n" ) return stock_prices = process_stocks(stocks, ns_parser.period) mu = expected_returns.mean_historical_return(stock_prices) S = risk_models.sample_cov(stock_prices) ef = EfficientFrontier(mu, S) _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) # Generate random portfolios n_samples = ns_parser.n_port w = np.random.dirichlet(np.ones(len(mu)), n_samples) rets = w.dot(mu) stds = np.sqrt(np.diag(w @ S @ w.T)) sharpes = rets / stds ax.scatter(stds, rets, marker=".", c=sharpes, cmap="viridis_r") plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True) # Find the tangency portfolio ef.max_sharpe() ret_sharpe, std_sharpe, _ = ef.portfolio_performance() ax.scatter(std_sharpe, ret_sharpe, marker="*", s=100, c="r", label="Max Sharpe") ax.set_title( f"Efficient Frontier simulating {ns_parser.n_port} portfolios") ax.legend() plt.tight_layout() plt.grid(b=True, which="major", color="#666666", linestyle="-") plt.minorticks_on() plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2) if gtff.USE_ION: plt.ion() plt.show() print("") except Exception as e: print(e, "\n")
daily_return = np.log(prices / prices.shift(1)) #relabel columns daily_return['Date'] = dates cols = ['Date'] + prices.columns.to_list() daily_return = daily_return.reindex(columns=cols) #write to csv daily_return.to_csv(r"C:\Users\Jonathan\Investing\ETF_daily_returns.csv", na_rep=np.nan) # Read in price data df = pd.read_csv(r"C:\Users\Jonathan\Investing\ETF_closing_prices.csv", parse_dates=True, index_col="Unnamed: 0") # Calculate expected returns and sample covariance mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df) # Optimise for maximal Sharpe ratio ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.save_weights_to_file(r"C:\Users\Jonathan\Investing\weights.csv") print(cleaned_weights) ef.portfolio_performance(verbose=True) weights = pd.read_csv(r"C:\Users\Jonathan\Investing\weights.csv", header=None) weights.columns = ['Ticker', 'Prop'] non_zero_weights = weights[weights.Prop != 0] print(non_zero_weights) non_zero_weights.to_csv(r'C:\Users\Jonathan\Desktop\stash_weights.csv')
#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() 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()
from pypfopt import CLA from pypfopt import black_litterman from pypfopt import BlackLittermanModel from pypfopt import Plotting # Reading in the data; preparing expected returns and a risk model df = pd.read_csv("tests/resources/stock_prices.csv", parse_dates=True, index_col="date") returns = df.pct_change().dropna() mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df) # Long-only Maximum Sharpe portfolio, with discretised weights ef = EfficientFrontier(mu, S) weights = ef.max_sharpe() ef.portfolio_performance(verbose=True) latest_prices = get_latest_prices(df) da = DiscreteAllocation(weights, latest_prices) allocation, leftover = da.lp_portfolio() print("Discrete allocation:", allocation) print("Funds remaining: ${:.2f}".format(leftover)) """ 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
} prior = black_litterman.market_implied_prior_returns(mcaps, delta, S) # 1. SBUX will drop by 20% # 2. GOOG outperforms FB by 10% # 3. BAC and JPM will outperform T and GE by 15% views = np.array([-0.20, 0.10, 0.15]).reshape(-1, 1) picking = np.array([ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, -0.5, 0, 0, 0.5, 0, -0.5, 0, 0, 0, 0, 0, 0, 0, 0.5, 0], ]) bl = BlackLittermanModel(S, Q=views, P=picking, pi=prior, tau=0.01) rets = bl.bl_returns() ef = EfficientFrontier(rets, S) ef.max_sharpe() print(ef.clean_weights()) ef.portfolio_performance(verbose=True) """ {'GOOG': 0.2015, 'AAPL': 0.2368, 'FB': 0.0, 'BABA': 0.06098, 'AMZN': 0.17148, 'GE': 0.0, 'AMD': 0.0, 'WMT': 0.0, 'BAC': 0.18545, 'GM': 0.0, 'T': 0.0, 'UAA': 0.0,