TransWikia.com

Optimization problem: Given Beta Bounds Maximize sharpe

Data Science Asked by trapadulli on September 27, 2021

I would like to maximize a portfolio’s Sharpe Ratio while keeping Beta in bounds.
Could anyone supply a calculation please?

***************Starting Metrics**********************
symbols          : ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
Beta             : [ 0.09  1.2   2.1  -1.3   1.1   0.3   0.9   1.2 ]
Sharpe           : [-1.7  5.4 -0.3  0.8  0.4  2.7  0.9  1.9]
optimized weights: [x0, x1, x2, x3, x4, x5, x6, x7]

***************Unadjusted Portfolio**********************
AvgBeta unadjusted  : 0.69875
AvgSharpe unadjusted: 1.2625000000000002

***************Ajusted Portfolio**********************
Beta bounds: -.3 < x <.3
Maximize sharpe: X

One Answer

Well, you didn't give a whole lot of information, so I'm going to make some assumptions here, but I think this is pretty darn close to what you want. Keep in mind, Beta = (Covar/Var), so you need to calculate that with what's given below, and then you will have everything you need.

import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.optimize as sco
import datetime as dt
import math
from datetime import datetime, timedelta
from pandas_datareader import data as wb
from sklearn.cluster import KMeans
np.random.seed(777)


start = '2019-02-28'
end = '2020-02-28'
# N = 90
# start = datetime.now() - timedelta(days=N)
# end = dt.datetime.today()



tickers = ['MMM',
'ABT',
'ABBV',
'ABMD',
'ACN',
'ATVI',
'ADBE',
'AMD',
'AAP',
'AES',
'AMG',
'XEL',
'XRX',
'XLNX',
'XYL',
'YUM',
'ZBH',
'ZION',
'ZTS'] 

thelen = len(tickers)

price_data = []
for ticker in tickers:
    prices = wb.DataReader(ticker, start = start, end = end, data_source='yahoo')[['Adj Close']]
    price_data.append(prices.assign(ticker=ticker)[['ticker', 'Adj Close']])

df = pd.concat(price_data)
df.dtypes
df.head()
df.shape

pd.set_option('display.max_columns', 500)

df = df.reset_index()
df = df.set_index('Date')
table = df.pivot(columns='ticker')
# By specifying col[1] in below list comprehension
# You can select the stock names under multi-level column
table.columns = [col[1] for col in table.columns]
table.head()



###################################################


def portfolio_annualised_performance(weights, mean_returns, cov_matrix):
    returns = np.sum(mean_returns*weights ) *252
    std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) * np.sqrt(252)
    return std, returns

def random_portfolios(num_portfolios, mean_returns, cov_matrix, risk_free_rate):
    results = np.zeros((3,num_portfolios))
    weights_record = []
    for i in range(num_portfolios):
        weights = np.random.random(thelen)
        weights /= np.sum(weights)
        weights_record.append(weights)
        portfolio_std_dev, portfolio_return = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
        results[0,i] = portfolio_std_dev
        results[1,i] = portfolio_return
        results[2,i] = (portfolio_return - risk_free_rate) / portfolio_std_dev
    return results, weights_record


returns = table.pct_change()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_portfolios = 10000
risk_free_rate = 0.0178


###################################################


def display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
    results, weights = random_portfolios(num_portfolios,mean_returns, cov_matrix, risk_free_rate)

    max_sharpe_idx = np.argmax(results[2])
    sdp, rp = results[0,max_sharpe_idx], results[1,max_sharpe_idx]
    max_sharpe_allocation = pd.DataFrame(weights[max_sharpe_idx],index=table.columns,columns=['allocation'])
    max_sharpe_allocation.allocation = [round(i*100,2)for i in max_sharpe_allocation.allocation]
    max_sharpe_allocation = max_sharpe_allocation.T

    min_vol_idx = np.argmin(results[0])
    sdp_min, rp_min = results[0,min_vol_idx], results[1,min_vol_idx]
    min_vol_allocation = pd.DataFrame(weights[min_vol_idx],index=table.columns,columns=['allocation'])
    min_vol_allocation.allocation = [round(i*100,2)for i in min_vol_allocation.allocation]
    min_vol_allocation = min_vol_allocation.T

    print("-")
    print("Maximum Sharpe Ratio Portfolio Allocationn")
    print("Annualised Return:", round(rp,2))
    print("Annualised Volatility:", round(sdp,2))
    print("n")
    print(max_sharpe_allocation)
    print("-")
    print("Minimum Volatility Portfolio Allocationn")
    print("Annualised Return:", round(rp_min,2))
    print("Annualised Volatility:", round(sdp_min,2))
    print("n")
    print(min_vol_allocation)

    plt.figure(figsize=(10, 7))
    plt.scatter(results[0,:],results[1,:],c=results[2,:],cmap='YlGnBu', marker='o', s=10, alpha=0.3)
    plt.colorbar()
    plt.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio')
    plt.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')
    plt.title('Simulated Portfolio Optimization based on Efficient Frontier')
    plt.xlabel('annualised volatility')
    plt.ylabel('annualised returns')
    plt.legend(labelspacing=0.8)


display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

Result:

Maximum Sharpe Ratio Portfolio Allocation

Annualised Return: 0.2
Annualised Volatility: 0.16


             AAP  ABBV  ABMD   ABT   ACN  ADBE   AES    AMD   AMG   ATVI  
allocation  3.29  5.51  0.59  4.29  2.89  9.09  8.42  11.22  3.01  10.03   

             MMM    XEL  XLNX  XRX   XYL   YUM   ZBH  ZION   ZTS  
allocation  0.12  11.39  2.95  6.7  2.89  5.91  3.02  0.79  7.88  
-
Minimum Volatility Portfolio Allocation

Annualised Return: 0.05
Annualised Volatility: 0.13


             AAP  ABBV  ABMD   ABT   ACN  ADBE   AES   AMD   AMG  ATVI   MMM  
allocation  6.35  8.14  2.55  4.32  8.71  2.18  5.62  1.99  2.08  4.86  6.89   

             XEL  XLNX  XRX  XYL   YUM   ZBH  ZION   ZTS  
allocation  10.1  1.93  1.9  5.5  7.92  5.57  6.01  7.39  

enter image description here

Answered by ASH on September 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP