def test_mean_historical_returns_type_warning(): df = get_data() mean = expected_returns.mean_historical_return(df) with warnings.catch_warnings(record=True) as w: mean_from_array = expected_returns.mean_historical_return(np.array(df)) assert len(w) == 1 assert issubclass(w[0].category, RuntimeWarning) assert str(w[0].message) == "prices are not in a dataframe" np.testing.assert_array_almost_equal(mean.values, mean_from_array.values, decimal=6)
def setup_cla(data_only=False): df = get_data() mean_return = expected_returns.mean_historical_return(df) sample_cov_matrix = risk_models.sample_cov(df) if data_only: return mean_return, sample_cov_matrix return CLA(mean_return, sample_cov_matrix)
def setup_efficient_frontier(data_only=False): df = get_data() mean_return = expected_returns.mean_historical_return(df) sample_cov_matrix = risk_models.sample_cov(df) if data_only: return mean_return, sample_cov_matrix return EfficientFrontier(mean_return, sample_cov_matrix)
def test_mean_historical_returns(): df = get_data() mean = expected_returns.mean_historical_return(df) assert isinstance(mean, pd.Series) assert list(mean.index) == list(df.columns) assert mean.notnull().all() assert mean.dtype == "float64" correct_mean = np.array( [ 0.26770284, 0.3637864, 0.31709032, 0.22616723, 0.49982007, 0.16888704, 0.22754479, 0.14783539, 0.19001915, 0.08150653, 0.12826351, 0.25797816, 0.07580128, 0.16087243, 0.20510267, 0.3511536, 0.38808003, 0.24635612, 0.21798433, 0.28474973, ] ) np.testing.assert_array_almost_equal(mean.values, correct_mean)
def test_negative_mean_return_real(): df = get_data() e_rets = mean_historical_return(df) w = np.array([1 / len(e_rets)] * len(e_rets)) negative_mu = objective_functions.negative_mean_return(w, e_rets) assert isinstance(negative_mu, float) assert negative_mu < 0 assert negative_mu == -w.dot(e_rets) assert negative_mu == -(w * e_rets).sum() np.testing.assert_almost_equal(-e_rets.sum() / len(e_rets), negative_mu)
def test_mean_historical_returns_dummy(): data = pd.DataFrame( [ [4.0, 2.0, 0.6, -12], [4.2, 2.1, 0.59, -13.2], [3.9, 2.0, 0.58, -11.3], [4.3, 2.1, 0.62, -11.7], [4.1, 2.2, 0.63, -10.1], ] ) mean = expected_returns.mean_historical_return(data, frequency=1) test_answer = pd.Series([0.00865598, 0.025, 0.01286968, -0.03632333]) pd.testing.assert_series_equal(mean, test_answer)
def test_negative_sharpe(): df = get_data() e_rets = mean_historical_return(df) S = sample_cov(df) w = np.array([1 / len(e_rets)] * len(e_rets)) sharpe = objective_functions.negative_sharpe(w, e_rets, S) assert isinstance(sharpe, float) assert sharpe < 0 sigma = np.sqrt(np.dot(w, np.dot(S, w.T))) negative_mu = objective_functions.negative_mean_return(w, e_rets) np.testing.assert_almost_equal(sharpe * sigma - 0.02, negative_mu) # Risk free rate increasing should lead to negative Sharpe increasing. assert sharpe < objective_functions.negative_sharpe( w, e_rets, S, risk_free_rate=0.1 )
def test_greedy_portfolio_allocation_short_different_params_reinvest(): df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da = DiscreteAllocation(w, latest_prices, total_portfolio_value=50000, short_ratio=0.5) allocation, leftover = da.greedy_portfolio(reinvest=True) print(allocation) assert allocation == { "MA": 145, "PFE": 317, "FB": 53, "GOOG": 6, "BABA": 34, "AAPL": 27, "SBUX": 58, "AMZN": 2, "BBY": 41, "XOM": 30, "WMT": 17, "JPM": 1, "BAC": -269, "AMD": -399, "SHLD": -1099, "GM": -78, "RRC": -154, "GE": -119, "T": -41, "UAA": -64, } long_total = 0 short_total = 0 for ticker, num in allocation.items(): if num > 0: long_total += num * latest_prices[ticker] else: short_total -= num * latest_prices[ticker] np.testing.assert_almost_equal(long_total + short_total + leftover, 100000)
def test_greedy_portfolio_allocation_short_different_params(): df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da = DiscreteAllocation(w, latest_prices, total_portfolio_value=50000, short_ratio=0.5) allocation, leftover = da.greedy_portfolio() assert da.allocation == { "MA": 77, "PFE": 225, "FB": 41, "BABA": 25, "AAPL": 23, "BBY": 44, "AMZN": 2, "SBUX": 45, "GOOG": 3, "WMT": 11, "XOM": 11, "BAC": -271, "GM": -133, "GE": -356, "SHLD": -922, "AMD": -285, "JPM": -5, "T": -14, "UAA": -8, "RRC": -3, } long_total = 0 short_total = 0 for ticker, num in allocation.items(): if num > 0: long_total += num * latest_prices[ticker] else: short_total -= num * latest_prices[ticker] np.testing.assert_almost_equal(long_total + short_total + leftover, 75000)
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 test_estimate(self, estimator, expected_value, prices_df): mu = mean_historical_return(prices_df).values cov = sample_cov(prices_df).values allocation = np.array([ 0.01269, 0.09202, 0.19856, 0.09642, 0.07158, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.06129, 0.24562, 0.18413, 0.0, 0.03769 ]) optimal_allocation = np.array([ 0.0, 0.15, 0.27, 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.02, 0.35, 0.1, 0.0, 0.01 ]) estimation = estimator.estimate(mu, cov, allocation, optimal_allocation) assert_almost_equal(estimation, expected_value)
def test_portfolio_allocation_errors(): df = get_data() e_ret = mean_historical_return(df) cov = sample_cov(df) ef = EfficientFrontier(e_ret, cov) w = ef.max_sharpe() latest_prices = discrete_allocation.get_latest_prices(df) with pytest.raises(TypeError): discrete_allocation.portfolio(ef.weights, latest_prices) with pytest.raises(TypeError): discrete_allocation.portfolio(w, latest_prices.values.tolist()) with pytest.raises(ValueError): discrete_allocation.portfolio(w, latest_prices, min_allocation=0.5) with pytest.raises(ValueError): discrete_allocation.portfolio(w, latest_prices, total_portfolio_value=0)
def test_es_example(): df = get_data() mu = expected_returns.mean_historical_return(df) historical_rets = expected_returns.returns_from_prices(df).dropna() es = EfficientSemivariance(mu, historical_rets) w = es.efficient_return(0.2) assert isinstance(w, dict) assert set(w.keys()) == set(es.tickers) np.testing.assert_almost_equal(es.weights.sum(), 1) assert all([i >= -1e-5 for i in w.values()]) np.testing.assert_allclose( es.portfolio_performance(), (0.20, 0.08558991313395496, 2.1030523036993265), rtol=1e-4, atol=1e-4, )
def test_lp_portfolio_allocation(): df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da = DiscreteAllocation(w, latest_prices, short_ratio=0.3) allocation, leftover = da.lp_portfolio() # Weirdly, this gives different answers for py3.8+ vs py3.6-3.7. assert allocation == { "AMD": 1, "GOOG": 1, "AAPL": 4, "FB": 12, "BABA": 4, "BBY": 2, "MA": 20, "PFE": 54, "SBUX": 1, } or allocation == { "GOOG": 1, "AAPL": 4, "FB": 12, "BABA": 4, "BBY": 2, "MA": 20, "PFE": 54, "SBUX": 1, } total = 0 for ticker, num in allocation.items(): total += num * latest_prices[ticker] np.testing.assert_almost_equal(total + leftover, 10000, decimal=4) # Cover the verbose parameter, allocation_verbose, leftover_verbose = da.lp_portfolio(verbose=True) assert allocation_verbose == allocation assert leftover_verbose == leftover
def test_lp_portfolio_allocation_short_reinvest(): df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da = DiscreteAllocation(w, latest_prices, short_ratio=0.3) allocation, leftover = da.lp_portfolio(reinvest=True) assert allocation == { "GOOG": 1, "AAPL": 5, "FB": 10, "BABA": 6, "WMT": 3, "XOM": 6, "BBY": 7, "MA": 26, "PFE": 55, "SBUX": 10, "JPM": 1, "GE": -14, "AMD": -48, "BAC": -32, "GM": -9, "T": -5, "UAA": -8, "SHLD": -132, "RRC": -19, } long_total = 0 short_total = 0 for ticker, num in allocation.items(): if num > 0: long_total += num * latest_prices[ticker] else: short_total -= num * latest_prices[ticker] np.testing.assert_almost_equal(long_total + short_total + leftover, 16000, decimal=5)
def rebal(self): prices = pd.DataFrame( [self.prices[d._name][:self.day] for d in self.datas]).T prices.columns = [d._name for d in self.datas] avg_returns = expected_returns.mean_historical_return(prices) cov_mat = risk_models.sample_cov(prices) # get weights maximizing the Sharpe ratio ef = EfficientFrontier(avg_returns, cov_mat) self.last_weights = copy.deepcopy(self.weights) self.weights = ef.max_sharpe() self.weight_chg = pd.Series(self.weights) - pd.Series( self.last_weights) self.cleaned_weights = ef.clean_weights() for i, d in enumerate(self.datas): self.rebalance_dict[d] = dict() self.rebalance_dict[d]['rebalanced'] = False for asset in self.p.assets: if asset[0] == d._name: self.rebalance_dict[d]['target_percent'] = self.weights[ d._name] * 99 #less than 100%
def construct_price_df(): dates, ticker_to_closing_prices = get_ticker_to_closing_prices( TEST_START_DATE, TEST_END_DATE) tickers = ticker_to_closing_prices.keys() prices = list( zip(*[ticker_to_closing_prices[ticker] for ticker in tickers])) df = pd.DataFrame( prices, index=dates, columns=tickers, ) mu = mean_historical_return(df) S = CovarianceShrinkage(df).ledoit_wolf() ef = EfficientFrontier(mu, S) weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() ef.portfolio_performance(verbose=True)
def test_cvar_example_short(): df = get_data() mu = expected_returns.mean_historical_return(df) historical_rets = expected_returns.returns_from_prices(df).dropna() cv = EfficientCVaR( mu, historical_rets, weight_bounds=(-1, 1), ) w = cv.efficient_return(0.2, market_neutral=True) assert isinstance(w, dict) assert set(w.keys()) == set(cv.tickers) np.testing.assert_almost_equal(cv.weights.sum(), 0) np.testing.assert_allclose( cv.portfolio_performance(), (0.2, 0.013406209257292611), rtol=1e-4, atol=1e-4, )
def test_greedy_portfolio_allocation_short(): df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da = DiscreteAllocation(w, latest_prices) allocation, leftover = da.greedy_portfolio() assert da.allocation == { "MA": 15, "PFE": 45, "FB": 8, "BABA": 5, "AAPL": 4, "BBY": 8, "AMZN": 1, "SBUX": 9, "WMT": 2, "XOM": 2, "BAC": -32, "GM": -16, "GE": -43, "SHLD": -110, "AMD": -34, "JPM": -1, "T": -1, "UAA": -1, } long_total = 0 short_total = 0 for ticker, num in allocation.items(): if num > 0: long_total += num * latest_prices[ticker] else: short_total -= num * latest_prices[ticker] np.testing.assert_almost_equal(long_total + short_total + leftover, 13000, decimal=4)
def test_cvar_errors(): df = get_data() mu = expected_returns.mean_historical_return(df) historical_rets = expected_returns.returns_from_prices(df) with pytest.warns(UserWarning): EfficientCVaR(mu, historical_rets) historical_rets = historical_rets.dropna(axis=0, how="any") assert EfficientCVaR(mu, historical_rets) cv = setup_efficient_cvar() with pytest.raises(NotImplementedError): cv.min_volatility() with pytest.raises(NotImplementedError): cv.max_sharpe() with pytest.raises(NotImplementedError): cv.max_quadratic_utility() with pytest.raises(ValueError): # Beta must be between 0 and 1 cv = EfficientCVaR(mu, historical_rets, 1) with pytest.warns(UserWarning): cv = EfficientCVaR(mu, historical_rets, 0.1) with pytest.raises(OptimizationError): # Must be <= max expected return cv = EfficientCVaR(mu, historical_rets) cv.efficient_return(target_return=np.abs(mu).max() + 0.01) with pytest.raises(AttributeError): # list not supported. EfficientCVaR(mu, historical_rets.to_numpy().tolist()) historical_rets = historical_rets.iloc[:, :-1] with pytest.raises(ValueError): EfficientCVaR(mu, historical_rets)
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 test_cvar_example_weekly(): beta = 0.95 df = get_data() df = df.resample("W").first() mu = expected_returns.mean_historical_return(df, frequency=52) historical_rets = expected_returns.returns_from_prices(df).dropna() cv = EfficientCVaR(mu, historical_rets, beta=beta) cv.efficient_return(0.2) np.testing.assert_allclose( cv.portfolio_performance(), (0.2, 0.03447723250708958), rtol=1e-4, atol=1e-4, ) cvar = cv.portfolio_performance()[1] portfolio_rets = historical_rets @ cv.weights var_hist = portfolio_rets.quantile(1 - beta) cvar_hist = -portfolio_rets[portfolio_rets < var_hist].mean() np.testing.assert_almost_equal(cvar_hist, cvar, decimal=3)
def test_es_example_short(): df = get_data() mu = expected_returns.mean_historical_return(df) historical_rets = expected_returns.returns_from_prices(df).dropna() es = EfficientSemivariance( mu, historical_rets, weight_bounds=(-1, 1), ) w = es.efficient_return(0.2, market_neutral=True) goog_weight = w["GOOG"] historical_rets["GOOG"] -= historical_rets["GOOG"].quantile(0.75) es = EfficientSemivariance( mu, historical_rets, weight_bounds=(-1, 1), ) w = es.efficient_return(0.2, market_neutral=True) goog_weight2 = w["GOOG"] assert abs(goog_weight2) >= abs(goog_weight)
def operate(self) -> tuple: """ポートフォリオを最適化する関数""" #平均リターンを求める #returns.mean() * 252 mu = expected_returns.mean_historical_return(self.financial_data) #リスク(分散)を求める #Get the sample covariance matrix S = risk_models.sample_cov(self.financial_data) #効率的フロンティアの作成 ef = EfficientFrontier(mu, S) weights = ef.min_volatility() cleaned_weights = ef.clean_weights() weight_keys = ["未選択", "未選択", "未選択", "未選択"] weight_values = ["ー", "ー", "ー", "ー"] count = 0 for k, v in dict(cleaned_weights).items(): weight_keys[count] = k weight_values[count] = v count += 1 #最適ポートフォリオの投資比率の出力, リターン・リスク・シャープレシオの出力 return weight_keys, weight_values, ef.portfolio_performance( verbose=False)
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 GetPort( ): #tickers = ['BSX','AES','BRK-B','SEE','QQQ','SPY'], first = 0, funds = 10000): ticks = request.args.get('tickers') tickers = list(ticks.split(" ")) first = request.args.get('first') funds = request.args.get('Funds') thelen = len(tickers) price_data = [] for ticker in range(thelen): prices = web.DataReader(tickers[ticker], start='2015-01-01', end='2020-10-17', data_source='yahoo') price_data.append(prices.assign(ticker=ticker)[['Adj Close']]) df_stocks = pd.concat(price_data, axis=1) df_stocks.columns = tickers mu = expected_returns.mean_historical_return(df_stocks) Sigma = risk_models.sample_cov(df_stocks) if int(first) == 1: ef = EfficientFrontier(mu, Sigma, weight_bounds=(0, 1)) else: ef = EfficientFrontier(mu, Sigma, weight_bounds=(-1, 1)) sharpe_pfolio = ef.max_sharpe() cleaned_weights = ef.clean_weights() latest_prices = get_latest_prices(df_stocks) da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value=int(funds)) allocation, leftover = da.lp_portfolio() new_alloc = {} for key in allocation: new_alloc[key] = str(allocation[key]) allocjson = json.dumps(new_alloc) return jsonify(allocation=new_alloc, leftover=leftover)
def generate_portfolio(starting_investment, stock_price_history): # Reset the date as the index stock_price_history = stock_price_history.set_index( pd.DatetimeIndex(stock_price_history['Date'].values)) #Remove the Date column stock_price_history.drop(columns=['Date'], axis=1, inplace=True) stock_price_history.dropna(axis=1, inplace=True) # Optimize the portfolio from pypfopt.efficient_frontier import EfficientFrontier from pypfopt import risk_models from pypfopt import expected_returns # Calculate the expected annualized returns and the annualized sample covariance matrix of the daily asset returns mu = expected_returns.mean_historical_return(stock_price_history) S = risk_models.sample_cov(stock_price_history) # Optimize for the maximal Sharpe ratio ef = EfficientFrontier(mu, S) # Creates the Efficient Frontier Object weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() #print(cleaned_weights) ef.portfolio_performance(verbose=True) # Get the descret allocation of each share per stock from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices latest_prices = get_latest_prices(stock_price_history) weights = cleaned_weights da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=starting_investment) allocation, leftover = da.lp_portfolio() print("Discrete allocation:", allocation) print("Funds Remaining: $", leftover) return (allocation, leftover)
def calculateInvestment(limit=10, count=10, write_to_file=True, show_cla=False, tpv=20000): symbols = getSymbolsFromDatabase() prices = createDataFrame(symbols[:limit], count) mu = expected_returns.mean_historical_return(prices) S = risk_models.CovarianceShrinkage(prices).ledoit_wolf() ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) ef.add_objective(objective_functions.L2_reg) ef.min_volatility() c_weights = ef.clean_weights() if write_to_file == True: ef.save_weights_to_file("weights.txt") if show_cla == True: cla = CLA(mu, S) ef_plot(cla) ef.portfolio_performance(verbose=True) latest_prices = disc_alloc.get_latest_prices(prices) allocation_minv, leftover = disc_alloc.DiscreteAllocation( c_weights, latest_prices, total_portfolio_value=tpv).lp_portfolio() return allocation_minv, leftover
def min_volatility(stocks_in_portfolio): stock_data = web.DataReader(stocks_in_portfolio,data_source='yahoo',start=start_date,end=end_date)['Adj Close'] stock_data.sort_index(inplace=True) mu = expected_returns.mean_historical_return(stock_data) S = risk_models.sample_cov(stock_data) lower_bound=0.30/len(stocks_in_portfolio) # Optimise for maximal Sharpe ratio with no contraints ef = EfficientFrontier(mu,S,weight_bounds=(lower_bound,1)) #Need to change the risk free rate raw_weights = ef.min_volatility() cleaned_weights = ef.clean_weights() cleaned_weights_df=pd.DataFrame.from_dict(cleaned_weights, orient='index') #remove weights with 0% cleaned_weights_df=cleaned_weights_df.loc[(cleaned_weights_df!=0).any(1)] #print("Portfolio having maximal sharpie ratio and with no contraints\n" ) # print(cleaned_weights) final_return= ef.portfolio_performance(verbose=True) index=['Expected Annual Return','Expected Annual Volatility','Sharpe Ratio'] final_return_df = pd.DataFrame(final_return,index=index) final_df=pd.concat([cleaned_weights_df,final_return_df]) return final_df
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 test_lp_portfolio_allocation(): df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da = DiscreteAllocation(w, latest_prices, short_ratio=0.3) allocation, leftover = da.lp_portfolio() # Gives differnt answers on different machines # assert allocation == { # "AMD": 1, # "GOOG": 1, # "AAPL": 4, # "FB": 12, # "BABA": 4, # "BBY": 1, # "MA": 20, # "PFE": 54, # "SBUX": 1, # } or allocation == { # "GOOG": 1, # "AAPL": 4, # "FB": 12, # "BABA": 4, # "BBY": 1, # "MA": 20, # "PFE": 54, # "SBUX": 1, # } total = 0 for ticker, num in allocation.items(): total += num * latest_prices[ticker] np.testing.assert_almost_equal(total + leftover, 10000, decimal=4)
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
def test_rmse_decreases_with_value(): # As total_portfolio_value increases, rmse should decrease. df = get_data() mu = mean_historical_return(df) S = sample_cov(df) ef = EfficientFrontier(mu, S) w = ef.max_sharpe() latest_prices = get_latest_prices(df) da1 = DiscreteAllocation(w, latest_prices, total_portfolio_value=10000) da1.greedy_portfolio() rmse1 = da1._allocation_rmse_error(verbose=False) da2 = DiscreteAllocation(w, latest_prices, total_portfolio_value=100000) da2.greedy_portfolio() rmse2 = da2._allocation_rmse_error(verbose=False) assert rmse2 < rmse1 da3 = DiscreteAllocation(w, latest_prices, total_portfolio_value=10000) da3.lp_portfolio() rmse3 = da3._allocation_rmse_error(verbose=False) da4 = DiscreteAllocation(w, latest_prices, total_portfolio_value=100000) da4.lp_portfolio() rmse4 = da4._allocation_rmse_error(verbose=False) assert rmse4 < rmse3
def asset_allocation(tickers, start_date): today = pd.datetime.today() if start_date == '1y': delta = today - pd.DateOffset(years=1) delta = delta.date() delta = delta.strftime('%Y-%m-%d') elif start_date == '3y': delta = today - pd.DateOffset(years=3) delta = delta.date() delta = delta.strftime('%Y-%m-%d') elif start_date == '5y': delta = today - pd.DateOffset(years=5) delta = delta.date() delta = delta.strftime('%Y-%m-%d') elif start_date == '10y': delta = today - pd.DateOffset(years=10) delta = delta.date() delta = delta.strftime('%Y-%m-%d') elif start_date == 'max': delta = today - pd.DateOffset(years=30) delta = delta.date() delta = delta.strftime('%Y-%m-%d') prices = ffn.get(tickers, start=delta) mu = expected_returns.mean_historical_return(prices) S = risk_models.sample_cov(prices) ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() latest_prices = discrete_allocation.get_latest_prices(prices) da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value=amount) allocation, leftover = da.lp_portfolio() st.subheader('Asset Allocation breakdown: ') st.write(allocation) st.write("Funds remaining: ${:.2f}".format(leftover))
def __get_ef_allocation(self, portfolio_size, portfolio_value): """Method that returns optimal allocation based on Markowitz Portfolio theory.""" df_hist = query_quotes_history() df = self.__get_momentum(df_hist) date = df.date.max() df_top = df.loc[df['date'] == date] df_top = df_top.sort_values(by='momentum', ascending=False).head(portfolio_size) universe = df_top['tickr'].tolist() df_u = df.loc[df['tickr'].isin(universe)] df_u = df_u.pivot_table(index='date', columns='tickr', values='close', aggfunc='sum') # Calculate expected returns and covariance mu = expected_returns.mean_historical_return(df_u) S = risk_models.sample_cov(df_u) # Optimise the portfolio for maximal Sharpe ratio # with regularization ef = EfficientFrontier(mu, S, gamma=1) ef.max_sharpe() cleaned_weights = ef.clean_weights() latest_prices = get_latest_prices(df_u) # Generate allocation da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value=portfolio_value) allocations = pd.Series(da.lp_portfolio()[0], name='allocation') return allocations
def test_cdar_example_weekly(): beta = 0.90 df = get_data() df = df.resample("W").first() mu = expected_returns.mean_historical_return(df, frequency=52) historical_rets = expected_returns.returns_from_prices(df).dropna() cd = EfficientCDaR(mu, historical_rets, beta=beta) cd.efficient_return(0.21) np.testing.assert_allclose( cd.portfolio_performance(), (0.21, 0.045085), rtol=1e-4, atol=1e-4, ) cdar = cd.portfolio_performance()[1] portfolio_rets = historical_rets @ cd.weights cum_rets = portfolio_rets.cumsum(0) drawdown = cum_rets.cummax() - cum_rets dar_hist = drawdown.quantile(beta) cdar_hist = drawdown[drawdown > dar_hist].mean() np.testing.assert_almost_equal(cdar_hist, cdar, decimal=3)
def test_portfolio_allocation(): df = get_data() e_ret = mean_historical_return(df) cov = sample_cov(df) ef = EfficientFrontier(e_ret, cov) w = ef.max_sharpe() latest_prices = discrete_allocation.get_latest_prices(df) allocation, leftover = discrete_allocation.portfolio(w, latest_prices) assert allocation == { "MA": 14, "FB": 12, "PFE": 51, "BABA": 5, "AAPL": 5, "AMZN": 0, "BBY": 9, "SBUX": 6, "GOOG": 1, } total = 0 for ticker, num in allocation.items(): total += num * latest_prices[ticker] np.testing.assert_almost_equal(total + leftover, 10000)
def test_mean_historical_returns_frequency(): df = get_data() mean = expected_returns.mean_historical_return(df) mean2 = expected_returns.mean_historical_return(df, frequency=52) np.testing.assert_array_almost_equal(mean / 252, mean2 / 52)
def test_ema_historical_return_limit(): df = get_data() sma = expected_returns.mean_historical_return(df) ema = expected_returns.ema_historical_return(df, span=1e10) np.testing.assert_array_almost_equal(ema.values, sma.values)
import pandas as pd import numpy as np from pypfopt.efficient_frontier import EfficientFrontier from pypfopt import risk_models from pypfopt import expected_returns from pypfopt.hierarchical_risk_parity import hrp_portfolio from pypfopt.value_at_risk import CVAROpt from pypfopt import discrete_allocation # Reading in the data; preparing expected returns and a risk model df = pd.read_csv("tests/stock_prices.csv", parse_dates=True, index_col="date") returns = df.pct_change().dropna(how="all") 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 = discrete_allocation.get_latest_prices(df) allocation, leftover = discrete_allocation.portfolio(weights, latest_prices) 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: {'MA': 14, 'FB': 12, 'PFE': 51, 'BABA': 5, 'AAPL': 5,