def calc(stockStartTime, stockEndTime): #calculating 2 years prior of the start date tempdate = dt.datetime.fromisoformat(stockStartTime) tempdate = tempdate - dt.timedelta(weeks=104) prices = ffn.get('pfe,ibm,wmt,msft,cat', start=tempdate.strftime('%Y-%m-%d'), end=stockStartTime) # Expected returns and sample covariance mu = expected_returns.mean_historical_return(prices) S = risk_models.sample_cov(prices) #Minimum volatility. May be useful if you're trying to get an idea of how low the volatility could be, #but in practice it makes a lot more sense to me to use the portfolio that maximises the Sharpe ratio. # Optimise portfolio for maximum Sharpe Ratio to serve as benchmark ef = EfficientFrontier(mu, S) raw_weights = ef.min_volatility() #ef.max_sharpe() cleaned_weights = ef.clean_weights() print("Cleaned weights:\n", cleaned_weights) print("Portfolio Performance:\n", ef.portfolio_performance(verbose=True)) #To achieve beta neutrality ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) print(" Weights: ", ef.efficient_return(target_return=0.15, market_neutral=True)) weights = ef.efficient_return(target_return=0.2, market_neutral=True) weight_sum = sum(w for w in weights.values() if w > 0) #normalised_weights = {k:v/weight_sum for k,v in weights.items()} #print("Normalized weights: ",normalised_weights) #We then need to convert these weights into an actual allocation, telling you how many shares of each asset you should purchase. latest_prices = get_latest_prices(prices) da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=1000000) allocation, leftover = da.lp_portfolio() #print(allocation) print("") for key, val in allocation.items(): print("Number of positions in ", key, " stock: ", val) print("") print("Funds remaining: ${:.2f}".format(leftover)) print("") prices2 = ffn.get('pfe,ibm,wmt,msft,cat', start=stockStartTime, end=stockEndTime) latest_prices2 = get_latest_prices(prices2) sum1 = 0 for key, val in allocation.items(): sum1 = sum1 - (latest_prices[key] * val) print("Value of Portfolio after short sales :\t", abs(sum1)) new = 0 for key, val in allocation.items(): new = new + (latest_prices2[key] * val) sum1 = sum1 + (latest_prices2[key] * val) print("Value at end of period :\t\t", new) print("Profit at end of time period :\t\t", sum1) return sum1
def test_weight_bounds_minus_one_to_one(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) assert ef.max_sharpe() assert ef.min_volatility() assert ef.efficient_return(0.05) assert ef.efficient_risk(0.05)
def markovitz(data, target_return): ''' Calculate markovitz portfolio for given historical/simulated returns for specified target rate of return Columns in data represent assets, rows represent simulated returns ''' ef = EfficientFrontier(data.mean(), data.cov(), weight_bounds=(0, 1)) proportions = ef.efficient_return(target_return) mean, std, sharpe = ef.portfolio_performance(risk_free_rate=0, verbose=False) return proportions, mean, std
def getPortfolio(assets, user_risk): priceDfFiltered = priceDf[assets] mu = expected_returns.mean_historical_return(priceDfFiltered) S = risk_models.sample_cov(priceDfFiltered) # Optimise for maximal Sharpe ratio ef = EfficientFrontier(mu, S) maxReturns = max(mu) portfoliosToReturn = {} raw_weights = ef.min_volatility() cleaned_weights = ef.clean_weights() for key in cleaned_weights: cleaned_weights[key] *= 100 portfolioResults = ef.portfolio_performance() portfolioResultsOrdered = { "Expected annual return": portfolioResults[0], "Annual volatility": portfolioResults[1], "Sharpe Ratio": portfolioResults[2] } portfoliosToReturn["Lowest Volatility"] = { "Weights": cleaned_weights, "Portfolio": portfolioResultsOrdered } minReturns = portfolioResults[0] raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() for key in cleaned_weights: cleaned_weights[key] *= 100 portfolioResults = ef.portfolio_performance() portfolioResultsOrdered = { "Expected annual return": portfolioResults[0], "Annual volatility": portfolioResults[1], "Sharpe Ratio": portfolioResults[2] } portfoliosToReturn["Best Portfolio"] = { "Weights": cleaned_weights, "Portfolio": portfolioResultsOrdered } userReturns = (maxReturns - minReturns) * user_risk + minReturns raw_weights = ef.efficient_return(userReturns) cleaned_weights = ef.clean_weights() for key in cleaned_weights: cleaned_weights[key] *= 100 portfolioResults = ef.portfolio_performance() portfolioResultsOrdered = { "Expected annual return": portfolioResults[0], "Annual volatility": portfolioResults[1], "Sharpe Ratio": portfolioResults[2] } portfoliosToReturn["User Risk"] = { "Weights": cleaned_weights, "Portfolio": portfolioResultsOrdered } return portfoliosToReturn
def optimize_efficient_returns(expected_returns_df, cov_matrix, target_return): EFOptimizer = EfficientFrontier(expected_returns_df, cov_matrix) weights_dict = EFOptimizer.efficient_return(target_return) return weights_dict # def optimize_max_sharpe(expected_returns_df, cov_matrix): # EFOptimizer = EfficientFrontier(expected_returns_df, cov_matrix) # weights_dict = EFOptimizer.max_sharpe() # return weights_dict
def test_efficient_return_market_neutral(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) w = ef.efficient_return(0.25, 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_almost_equal( ef.portfolio_performance(), (0.25, 0.20567621957479246, 1.1182624830289896)) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert long_only_sharpe > sharpe
def test_efficient_return_short(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(None, None)) w = ef.efficient_return(0.25) 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) np.testing.assert_allclose(ef.portfolio_performance(), (0.25, 0.1682647442258144, 1.3668935881968987)) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def test_efficient_return_market_neutral(): ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) w = ef.efficient_return(0.25, 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_almost_equal( ef.portfolio_performance(), (0.24999999999755498, 0.20567338787141307, 1.1087493060316183), ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert long_only_sharpe > sharpe
def test_efficient_return_short(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(None, None) ) w = ef.efficient_return(0.25) 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) np.testing.assert_allclose( ef.portfolio_performance(), (0.25, 0.168264744226909, 1.3640929002973508) ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def calculate_optimized_portfolio( tickers: Tuple[str], strategy: str, expected_return: str, risk_model: str, portfolio_value: float, risk_free: float, risk_aversion: float, target_risk: float, target_return: float, tiingo_api_key: Optional[str], verbose: bool, ) -> None: tiingo_api_key = tiingo_api_key or os.environ.get("TIINGO_API_KEY") if tiingo_api_key is None: raise RuntimeError( "Tiingo API key not found. Please pass in an api key or set the " "TIINGO_API_KEY environment variable") stock_data = get_stock_data(tickers, tiingo_api_key) expected_returns = EXPECTED_RETURN_METHODOLOGY[expected_return](stock_data) cov_matrix = RISK_MODELS[risk_model](stock_data) efficient_frontier = EfficientFrontier(expected_returns, cov_matrix) if strategy == "max_sharpe": raw_weights = efficient_frontier.max_sharpe(risk_free_rate=risk_free) elif strategy == "min_vol": raw_weights = efficient_frontier.min_volatility() elif strategy == "eff_risk": raw_weights = efficient_frontier.efficient_risk( target_risk=target_risk, risk_free_rate=risk_free) elif strategy == "eff_return": raw_weights = efficient_frontier.efficient_return( target_return=target_return) cleaned_weights = efficient_frontier.clean_weights() click.echo(cleaned_weights) latest_prices = get_latest_prices(stock_data) discrete_weights = DiscreteAllocation(cleaned_weights, latest_prices, portfolio_value) discrete_weights.lp_portfolio(verbose=verbose) efficient_frontier.portfolio_performance(verbose=True)
def test_efficient_return_market_neutral(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1) ) w = ef.efficient_return(0.25, 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_almost_equal( ef.portfolio_performance(), (0.25, 0.20567621957041887, 1.1087335497769277) ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert long_only_sharpe > sharpe
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)
from pypfopt import expected_returns from pypfopt.efficient_frontier import EfficientFrontier # Calculating expected returns mu mu = expected_returns.mean_historical_return(df) # Calculating the covariance matrix S Sigma = risk_models.sample_cov(df) # Obtaining the efficient frontier ef = EfficientFrontier(mu, Sigma) print(mu, Sigma) returns = df.pct_change() covMatrix = returns.cov() * 251 print(covMatrix) # Getting the minimum risk portfolio for a target return weights = ef.efficient_return(0.2) print(weights) l = list(df.columns) print(l) size = list(weights.values()) print(size) print(type(size)) plt.pie(size, labels=l, autopct='%1.1f%%') plt.title('Return=20%') plt.show() # Showing portfolio performance ef.portfolio_performance(verbose=True) # Calculating weights for the maximum Sharpe ratio portfolio raw_weights_maxsharpe = ef.max_sharpe() cleaned_weights_maxsharpe = ef.clean_weights()
from pypfopt import risk_models from pypfopt import expected_returns from pypfopt.efficient_frontier import EfficientFrontier from pypfopt.black_litterman import BlackLittermanModel prbr = pd.read_excel(r'C:\Users\Jhona\OneDrive\Área de Trabalho\PRBR11.xlsx', index_col='Data', parse_dates=['Data']) ###Expectativa de retornos de mu mu = expected_returns.mean_historical_return(prbr) ###Matrix de covariancia sigma = risk_models.sample_cov(prbr) ###Fronteira eficiente Max sharpe ef = EfficientFrontier(mu, sigma) weights = ef.max_sharpe() ef.efficient_risk(2.0) ef.efficient_return(1.5) cleaned_weights = ef.clean_weights() print(weights, cleaned_weights) ef.portfolio_performance(verbose=True, risk_free_rate=0.0225) ###Fronteira eficiente Min Vol ef = EfficientFrontier(mu, sigma) raw_weights = ef.min_volatility() cleaned_weights = ef.clean_weights() print(cleaned_weights) ef.portfolio_performance(verbose=True, risk_free_rate=0.02)
def main(): """ Runs the main descriptive stadistict about stocks and also get optimal portafolio """ t0 = dt.datetime.now() args = utils.get_args() all_config = yaml.safe_load(open(args.config_file_path, "r")) DATA = all_config['output']['data_folder'] input_data_path = all_config['stocks']['data'] logger = logger_utils.log_creator(all_config['output']['log_folder'], log_name='get_stats') start_date, end_date = utils.get_start_end(all_config) df_ticks_path = os.path.join('./src/data', input_data_path) logger.info("Reading tick and weights from %s" % df_ticks_path) weights = utils.get_ticks_data(df_ticks_path) data_path = utils.filename_maker('stocks_', DATA, start_date, end_date) data_sp_path = utils.filename_maker('sp500_', DATA, start_date, end_date) df = pd.read_csv(data_path) sp = pd.read_csv(data_sp_path) df['Date'] = pd.to_datetime(df['Date']) df.set_index('Date', inplace=True) df_pc = df.pct_change().dropna() sp['Date'] = pd.to_datetime(sp['Date']) sp.set_index('Date', inplace=True) sp_pc = sp.pct_change().dropna() weights_np = weights['WEIGHT'].to_numpy() anual_cov_matrix = df_pc.cov()*252 volatilidad_por_anual = np.sqrt(np.dot(weights_np.T, np.dot(anual_cov_matrix, weights_np))) logger.info("Anual portafolio volatility is %.2f" % volatilidad_por_anual) portafolio_anual_return = np.sum(df_pc.mean()*weights_np)*252 logger.info("Anual portafolio return is %.2f" % portafolio_anual_return) logger.info("Mean historical return for each stock %s" % round((df_pc.mean()*252),2)) logger.info("Anual volatility for each stock %s" % round(np.std(df_pc)*np.sqrt(252),2)) # np.sum(df_pc.mean()*weights['WEIGHT'].to_numpy())*252 ticks = weights['TICK'].to_list() skew_list = [] kurtosis_list = [] shapiro_list = [] annual_vol = [] annual_returns = [] for tk in ticks: skewness = np.round(df_pc[tk].skew(), 3) kurt = np.round(df_pc[tk].kurtosis() + 3, 3) shap = np.round(shapiro(df_pc[tk])[1], 3) vol = np.round(df_pc[tk].std()*np.sqrt(252), 3) rtn = np.round((df_pc[tk].mean()*252), 3) skew_list.append(skewness) kurtosis_list.append(kurt) shapiro_list.append(shap) annual_vol.append(vol) annual_returns.append(rtn) logger.info("This is the summary of the stocks regarding the anual return, anual volatility, kurtosis, shapiro and skew.") stocks_summary = pd.DataFrame({'STOCK': ticks, 'SKEW': skew_list, 'KURTOSIS': kurtosis_list, 'SHAPIRO': shapiro_list, 'ANNUAL_VOL': annual_vol, 'ANNUAL_RETURN': annual_returns}) stocks_summary.set_index('STOCK', inplace=True) logger.info(stocks_summary) logger.info("Lets now calculate the anual covariance between stoks") cov_matriz = df_pc.cov()*252 logger.info(cov_matriz) logger.info("Using Python Portafolio") mu = expected_returns.mean_historical_return(df) sigma = risk_models.sample_cov(df) ef = EfficientFrontier(mu, sigma) logger.info("Showing portafolio with max sharpe rate") raw_weights_maxsharpe = ef.max_sharpe() cleaned_weights_maxsharpe = ef.clean_weights() logger.info(cleaned_weights_maxsharpe) # Show portfolio performance logger.info(ef.portfolio_performance(verbose=True)) desire_return = 0.20 ef.efficient_return(desire_return) logger.info("Calculating portafolio which should bring a return of %s" % desire_return) logger.info(ef.clean_weights()) logger.info("Showing portafolio with lowest risk for a return of %s" % desire_return) raw_weights_minvol = ef.min_volatility() cleaned_weights_minvol = ef.clean_weights() logger.info(cleaned_weights_minvol) logger.info(ef.portfolio_performance(verbose=True)) t1 = dt.datetime.now()
shrink = risk_models.CovarianceShrinkage(df) S = shrink.ledoit_wolf() ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) weights = ef.efficient_risk(target_risk=0.10) ef.portfolio_performance(verbose=True) """ Expected annual return: 29.8% Annual volatility: 10.0% Sharpe Ratio: 2.77 """ # A market-neutral Markowitz portfolio finding the minimum volatility # for a target return of 20% ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) weights = ef.efficient_return(target_return=0.20, market_neutral=True) ef.portfolio_performance(verbose=True) """ Expected annual return: 20.0% Annual volatility: 16.5% Sharpe Ratio: 1.09 """ # Custom objective def utility_obj(weights, mu, cov_matrix, k=1): return -weights.dot(mu) + k * np.dot(weights.T, np.dot(cov_matrix, weights)) ef = EfficientFrontier(mu, S)