原文: https://github.com/tthustla/efficient_frontier/blob/master/Efficient%20_Frontier_implementation.ipynb
優化函數: https://blog.csdn.net/qcyfred/article/details/77115739
Modern Portfolio Theory
根據1952年由Harry Markowitz發表的投資組合理論Modern Portfolio Theory (MPT)建立投資組合.天下沒有白吃的午餐,"There Ain't No Such Thing As A Free Lunch".追求報酬率越高的商品必須付出越大的風險.但若兩個商品的投資報酬率相同,但風險有差異,投資人會選擇風險較低的商品.以美股ETF為例,VTI(美股)和VB(美國小型股)的年化投資報酬率相同,大約都是9%,但VB的年化波動率為23%,而VTI的年化波動率為20%,因此投資人傾向選擇VTI.
配置投資組合的目的是在組合出一組雞尾酒ETF,他的波動率比相同年化率的單一商品還要低.因為個別投資商品之間的相關係數有所差異,若投資組合中搭配相關係數掉低的商品,則可以讓投資組合的波動率降低,但是長期的年化報酬率卻保持一樣.
我們將利用pandas_datareader讀取美股ETF歷史資料:
股票型
世界指數 Vanguard Total World Stock Inde (VT) 年配息 平均年化報酬率: 10.47% 年化配息率: 2.41%
美股 Vanguard Total Stock Market ETF (VTI) 年配息 平均年化報酬率: 9.44% 年化配息率: 2%
美國以外的已開發市場 Vanguard FTSE Developed Markets(VEA) 年配息 平均年化報酬率: 2.52% 年化配息率: 2.92%
美國小型股 Small Cap ETF (VB) 年配息 平均年化報酬率: 9.66% 年化配息率: 1.54
新興市場 Emerging Markets ETF (VWO) 平均年化報酬率: 10.12% 年化配息率: 2.45
原物料
黃金 SPDR Gold Trust(GLD) 平均年化報酬率: 9.86%
債卷型
全球債卷 Vanguard Total Bond Market ETF (BND) 月配息 平均年化報酬率: 3.77% 年化配息率: 3.1%
REITs Vanguard Real Estate ETF (VNQ) 年配息 平均年化報酬率: 9.2% 年化配息率: 3.1%
長期債券 Vanguard Long-Term Bond ETF(BLV) 月配息 平均年化報酬率: 6.5% 年化配息率: 4.6%
可轉債 Bloomberg Barclays Convertible Securities ETF(CWB) 年配息 平均年化報酬率: 3.75% 年化配息率: 4.6%
高收益債 High Yield Corporate Bond ETF (HYG) 年配息 平均年化報酬率:7.8% 年化配息率: 5.9%
新興市場債 Vanguard Emerging Markets Government Bond ETF (VWOB) 月配息 平均年化報酬率: 3.22% 年化配息率: 4.29%
美國政府中期債 iShares 3-7 Year Treasury Bond ETF (IEI) 年配息 平均年化報酬率: 2.91%, 年化配息率: 1.61%
以下我們將用兩種不同的方法(隨機亂數法, 函數優化法)找出3種投資組合分別是適用於積極型, 穩健型, 和保守型投資人
積極型:投資報酬率最高的投資組合
穩健型:夏普值最大的投資組合
保守型:風險最低的投資組合
In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import pandas_datareader as web
import scipy.optimize as sco
import seaborn as sns
In [2]:
symbols = ['VT','VTI','VEA','VB','VWO','GLD','BND','VNQ','BLV','HYG','VWOB','IEI']
num_symbols = len(symbols)
In [3]:
price_data = web.get_data_yahoo(symbols,start = '2008-08-16',end = '2019-08-15')
table = price_data.Close
plt.figure(figsize=(14, 7))
for c in table.columns.values:
plt.plot(table.index, table[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper left', fontsize=12)
plt.ylabel('price in $')
/Users/laihunglai/anaconda3/envs/py35/lib/python3.5/site-packages/pandas/plotting/_converter.py:129: FutureWarning: Using an implicitly registered datetime converter for a matplotlib plotting method. The converter was registered by pandas on import. Future versions of pandas will require you to explicitly register matplotlib converters.
To register the converters:
>>> from pandas.plotting import register_matplotlib_converters
>>> register_matplotlib_converters()
warnings.warn(msg, FutureWarning)
Out[3]:
Text(0,0.5,'price in $')
In [4]:
# 計算變化百分比 看波動率
returns = table.pct_change()
plt.figure(figsize=(14, 7))
for c in returns.columns.values:
plt.plot(returns.index, returns[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper right', fontsize=12)
plt.ylabel('daily returns')
Out[4]:
Text(0,0.5,'daily returns')
隨機亂數法找投資組合
In [5]:
#計算一年的回報率(return)和波動率(volatility),取252天為一年
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
In [6]:
# 對每個投資商品產生隨機的權重
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(num_symbols)
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
#計算sharp值:(投資組合報酬率-無風險報酬率)/投資組合std
results[2,i] = (portfolio_return - risk_free_rate) / portfolio_std_dev
return results, weights_record
In [7]:
returns = table.pct_change()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_portfolios = 50000 #產生多少了亂數的投資組合
risk_free_rate = 0.0178
In [8]:
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)
#找出sharp值最大的投資組合
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
#找出報酬率最高的投資組合
max_ret_idx = np.argmax(results[1])
sdp_max, rp_max = results[0,max_ret_idx], results[1,max_ret_idx]
max_ret_allocation = pd.DataFrame(weights[max_ret_idx],index=table.columns,columns=['allocation'])
max_ret_allocation.allocation = [round(i*100,2)for i in max_ret_allocation.allocation]
max_ret_allocation = max_ret_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 ("."*80)
print ("Maximum Sharpe Ratio Portfolio Allocation\n")
print ("Annualised Return:", round(rp,2))
print ("Annualised Volatility:", round(sdp,2))
print ("\n")
print (max_ret_allocation)
#畫出pie圖
max_sharpe_record=max_sharpe_allocation[max_sharpe_allocation>0]
max_sharpe_record.T.plot.pie(y='allocation', figsize=(5, 5), autopct='%1.0f%%')
title='夏普值最高 年報酬:'+str(np.round(rp,2))+' 風險:'+str(np.round(sdp,2))
plt.title(title, fontproperties="PMingLiU", fontsize=20)
plt.show()
print ("."*80)
print ("Maximum Return Portfolio Allocation\n")
print ("Annualised Return:", round(rp_max,2))
print ("Annualised Volatility:", round(sdp_max,2))
print ("\n")
print (max_sharpe_allocation)
#畫出pie圖
max_return_record=max_ret_allocation[max_ret_allocation>0]
max_return_record.T.plot.pie(y='allocation', figsize=(5, 5), autopct='%1.0f%%')
title='報酬最高 年報酬:'+str(np.round(rp_max,2))+' 風險:'+str(np.round(sdp_max,2))
plt.title(title, fontproperties="PMingLiU", fontsize=20)
plt.show()
print ("."*80)
print ("Minimum Volatility Portfolio Allocation\n")
print ("Annualised Return:", round(rp_min,2))
print ("Annualised Volatility:", round(sdp_min,2))
print ("\n")
print (min_vol_allocation)
#畫出pie圖
min_vol_record=min_vol_allocation[min_vol_allocation>0]
min_vol_record.T.plot.pie(y='allocation', figsize=(5, 5), autopct='%1.0f%%')
title='風險最低 年報酬:'+str(np.round(rp_min,2))+' 風險:'+str(np.round(sdp_min,2))
plt.title(title, fontproperties="PMingLiU", fontsize=20)
plt.show()
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_max,rp_max,marker='*',color='b',s=500, label='Maximum Return')
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)
In [9]:
display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)
................................................................................
Maximum Sharpe Ratio Portfolio Allocation
Annualised Return: 0.05
Annualised Volatility: 0.08
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO \
allocation 1.56 5.85 24.66 2.35 0.27 19.76 8.09 3.3 3.3 23.93 6.33
Symbols VWOB
allocation 0.61
................................................................................
Maximum Return Portfolio Allocation
Annualised Return: 0.07
Annualised Volatility: 0.15
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI \
allocation 28.99 10.35 9.13 0.34 2.01 11.88 2.14 2.22 0.12 18.52
Symbols VWO VWOB
allocation 2.1 12.21
................................................................................
Minimum Volatility Portfolio Allocation
Annualised Return: 0.03
Annualised Volatility: 0.05
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI \
allocation 18.77 15.47 6.75 6.72 18.1 3.21 0.13 0.51 1.35 10.98
Symbols VWO VWOB
allocation 0.26 17.76
函數優化法找投資組合
用scipy.optimize找出優化的投資組合, 找出給定目標報酬率下風險最低的投資組合
需要符合以下幾個條件:
-
權重加總=1, 使用constraints
-
權重介於[0,1]之間, 使用bound
scipy.optimize.sco.minimize()只能找出優化的最小值不能找出最大值,所以如果要找出sharp ratio最大值的權重就必須先把sharp ratio取負號,換成找(-sharp ratio)的最小值所對應的權重
sco.minimize(想要優化的函數, 初始化權重參數, 已知的參數(報酬, 風險, 無風險報酬), 方法, bound參數束縛條件, constraints函數限制嫖件)
這裡使用Sequential quadratic programming(SLSQP)來方法來做optimize.https://en.wikipedia.org/wiki/Sequential_quadratic_programming
sco.minimize()回傳優化的權重儲存在result['x'],在用portfolio_annualised_performance(result['x'], mean_returns, cov_matrix),算出這個以sharp ratio優化後的投資組合報酬率和風險.
權重加總=1, 使用constraints
權重介於[0,1]之間, 使用bound
計算效率前緣 Efficient Frontiner:
效率前緣指的是在相同風險下,最有效率的投資組合,可以想像是給定風險下找出投資報酬最高的投資組合,因此不同的風險會對應出一個效率前緣報酬率和投資組合.
In [10]:
def neg_sharpe_ratio(weights, mean_returns, cov_matrix, risk_free_rate):
p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, cov_matrix) #要optimized的參數是權重
return -(p_ret - risk_free_rate) / p_var
def max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate):
num_assets = len(mean_returns)
args = (mean_returns, cov_matrix, risk_free_rate) #已知的參數
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bound = (0.0,1.0)
bounds = tuple(bound for asset in range(num_assets))
result = sco.minimize(neg_sharpe_ratio, num_assets*[1./num_assets,], args=args,
method='SLSQP', bounds=bounds, constraints=constraints)
return result
In [11]:
def portfolio_return(weights, mean_returns, cov_matrix):
return -portfolio_annualised_performance(weights, mean_returns, cov_matrix)[1]
def max_return(mean_returns, cov_matrix):
num_assets = len(mean_returns)
args = (mean_returns, cov_matrix)
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bound = (0.0,1.0)
bounds = tuple(bound for asset in range(num_assets))
result = sco.minimize(portfolio_return, num_assets*[1./num_assets,], args=args,
method='SLSQP', bounds=bounds, constraints=constraints)
return result
In [12]:
def portfolio_volatility(weights, mean_returns, cov_matrix):
return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[0]
def min_variance(mean_returns, cov_matrix):
num_assets = len(mean_returns)
args = (mean_returns, cov_matrix)
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bound = (0.0,1.0)
bounds = tuple(bound for asset in range(num_assets))
result = sco.minimize(portfolio_volatility, num_assets*[1./num_assets,], args=args,
method='SLSQP', bounds=bounds, constraints=constraints)
return result
In [13]:
# 給定報酬率target下算出風險最低的優化投資組合
def efficient_return(mean_returns, cov_matrix, target):
num_assets = len(mean_returns)
args = (mean_returns, cov_matrix)
def portfolio_return(weights):
return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[1] #報酬率
#多了portfolio_return(x) - target的限制條件(報酬率要等於目標報酬率)
constraints = ({'type': 'eq', 'fun': lambda x: portfolio_return(x) - target},
{'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bounds = tuple((0,1) for asset in range(num_assets))
#優化portfolio_volatility風險最低低投資組合權重,並回傳到result['x']
result = sco.minimize(portfolio_volatility, num_assets*[1./num_assets,], args=args, method='SLSQP', bounds=bounds, constraints=constraints)
return result
# 找出報酬率array所對應的優化投資組合array
def efficient_frontier(mean_returns, cov_matrix, returns_range):
efficients = []
for ret in returns_range:
efficients.append(efficient_return(mean_returns, cov_matrix, ret))
return efficients
In [14]:
def display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
results, _ = random_portfolios(num_portfolios,mean_returns, cov_matrix, risk_free_rate)
#找出最大sharp ratio的投資組合權重
max_sharpe = max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate)
sdp, rp = portfolio_annualised_performance(max_sharpe['x'], mean_returns, cov_matrix)
max_sharpe_allocation = pd.DataFrame(max_sharpe.x,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
#找出最大報酬的權重
max_ret = max_return(mean_returns, cov_matrix)
sdp_max, rp_max = portfolio_annualised_performance(max_ret['x'], mean_returns, cov_matrix)
max_ret_allocation = pd.DataFrame(max_ret.x,index=table.columns,columns=['allocation'])
max_ret_allocation.allocation = [round(i*100,2)for i in max_ret_allocation.allocation]
max_ret_allocation = max_ret_allocation.T
#找出最小風險的權重
min_vol = min_variance(mean_returns, cov_matrix)
sdp_min, rp_min = portfolio_annualised_performance(min_vol['x'], mean_returns, cov_matrix)
min_vol_allocation = pd.DataFrame(min_vol.x,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 ("."*80)
print ("Maximum Sharpe Ratio Portfolio Allocation\n")
print ("Annualised Return:", round(rp,2))
print ("Annualised Volatility:", round(sdp,2))
print ("\n")
print (max_sharpe_allocation)
print ("."*80)
print ("Maximum Return Portfolio Allocation\n")
print ("Annualised Return:", round(rp_max,2))
print ("Annualised Volatility:", round(sdp_max,2))
print ("\n")
print (max_ret_allocation)
print ("."*80)
print ("Minimum Volatility Portfolio Allocation\n")
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_max,rp_max,marker='*',color='b',s=500, label='Maxinum Return')
plt.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')
target = np.linspace(rp_min, 0.15, 50)
efficient_portfolios = efficient_frontier(mean_returns, cov_matrix, target)
plt.plot([p['fun'] for p in efficient_portfolios], target, linestyle='-.', color='black', label='efficient frontier')
plt.title('Calculated Portfolio Optimization based on Efficient Frontier')
plt.xlabel('annualised volatility')
plt.ylabel('annualised returns')
plt.legend(labelspacing=0.8)
In [15]:
display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)
................................................................................
Maximum Sharpe Ratio Portfolio Allocation
Annualised Return: 0.06
Annualised Volatility: 0.09
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO VWOB
allocation 41.36 0.0 22.43 0.0 0.0 2.71 0.0 0.0 0.0 33.5 0.0 0.0
................................................................................
Maximum Return Portfolio Allocation
Annualised Return: 0.1
Annualised Volatility: 0.23
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO VWOB
allocation 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0
................................................................................
Minimum Volatility Portfolio Allocation
Annualised Return: 0.02
Annualised Volatility: 0.03
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO VWOB
allocation 0.0 0.0 0.0 3.82 76.93 0.0 0.0 0.0 0.0 6.07 0.0 13.17
In [16]:
def display_ef_with_selected(mean_returns, cov_matrix, risk_free_rate):
max_sharpe = max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate)
sdp, rp = portfolio_annualised_performance(max_sharpe['x'], mean_returns, cov_matrix)
max_sharpe_allocation = pd.DataFrame(max_sharpe.x,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
max_sharpe_allocation
max_ret = max_return(mean_returns, cov_matrix)
sdp_max, rp_max = portfolio_annualised_performance(max_ret['x'], mean_returns, cov_matrix)
max_ret_allocation = pd.DataFrame(max_ret.x,index=table.columns,columns=['allocation'])
max_ret_allocation.allocation = [round(i*100,2)for i in max_ret_allocation.allocation]
max_ret_allocation = max_ret_allocation.T
min_vol = min_variance(mean_returns, cov_matrix)
sdp_min, rp_min = portfolio_annualised_performance(min_vol['x'], mean_returns, cov_matrix)
min_vol_allocation = pd.DataFrame(min_vol.x,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
an_vol = np.std(returns) * np.sqrt(252)
an_rt = mean_returns * 252
portfolio_list=[]
print ("."*80)
print ("Maximum Sharpe Ratio Portfolio Allocation\n")
print ("Annualised Return:", round(rp,2))
print ("Annualised Volatility:", round(sdp,2))
print ("\n")
print (max_sharpe_allocation)
portfolio_list.append(max_sharpe_allocation)
print ("."*80)
print ("Maximum Return Portfolio Allocation\n")
print ("Annualised Return:", round(rp_max,2))
print ("Annualised Volatility:", round(sdp_max,2))
print ("\n")
print (max_ret_allocation)
portfolio_list.append(max_ret_allocation)
print ("."*80)
print ("Minimum Volatility Portfolio Allocation\n")
print ("Annualised Return:", round(rp_min,2))
print ("Annualised Volatility:", round(sdp_min,2))
print ("\n")
print (min_vol_allocation)
portfolio_list.append(min_vol_allocation)
record = [rp,sdp,rp_max,sdp_max,rp_min,sdp_min]
print ("."*80)
print ("Individual Stock Returns and Volatility\n")
for i, txt in enumerate(table.columns):
print (txt,":","annuaised return",round(an_rt[i],2),", annualised volatility:",round(an_vol[i],2))
print ("."*80)
fig, ax = plt.subplots(figsize=(10, 7))
ax.scatter(an_vol,an_rt,marker='o',s=200)
for i, txt in enumerate(table.columns):
ax.annotate(txt, (an_vol[i],an_rt[i]), xytext=(10,0), textcoords='offset points')
ax.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio')
ax.scatter(sdp_max,rp_max,marker='*',color='b',s=500, label='Maximum return')
ax.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')
target = np.linspace(rp_min, 0.15, 50)
efficient_portfolios = efficient_frontier(mean_returns, cov_matrix, target)
ax.plot([p['fun'] for p in efficient_portfolios], target, linestyle='-.', color='black', label='efficient frontier')
ax.set_title('Portfolio Optimization with Individual Stocks')
ax.set_xlabel('annualised volatility')
ax.set_ylabel('annualised returns')
ax.legend(labelspacing=0.8)
return portfolio_list,record
In [17]:
portfolio_list = display_ef_with_selected(mean_returns, cov_matrix, risk_free_rate)
................................................................................
Maximum Sharpe Ratio Portfolio Allocation
Annualised Return: 0.06
Annualised Volatility: 0.09
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO VWOB
allocation 41.36 0.0 22.43 0.0 0.0 2.71 0.0 0.0 0.0 33.5 0.0 0.0
................................................................................
Maximum Return Portfolio Allocation
Annualised Return: 0.1
Annualised Volatility: 0.23
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO VWOB
allocation 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0
................................................................................
Minimum Volatility Portfolio Allocation
Annualised Return: 0.02
Annualised Volatility: 0.03
Symbols BLV BND GLD HYG IEI VB VEA VNQ VT VTI VWO VWOB
allocation 0.0 0.0 0.0 3.82 76.93 0.0 0.0 0.0 0.0 6.07 0.0 13.17
................................................................................
Individual Stock Returns and Volatility
BLV : annuaised return 0.04 , annualised volatility: 0.1
BND : annuaised return 0.01 , annualised volatility: 0.04
GLD : annuaised return 0.07 , annualised volatility: 0.18
HYG : annuaised return 0.0 , annualised volatility: 0.12
IEI : annuaised return 0.02 , annualised volatility: 0.04
VB : annuaised return 0.1 , annualised volatility: 0.23
VEA : annuaised return 0.03 , annualised volatility: 0.23
VNQ : annuaised return 0.09 , annualised volatility: 0.33
VT : annuaised return 0.06 , annualised volatility: 0.21
VTI : annuaised return 0.09 , annualised volatility: 0.2
VWO : annuaised return 0.04 , annualised volatility: 0.29
VWOB : annuaised return 0.0 , annualised volatility: 0.05
................................................................................
函數優化法設計出三種優化後的投資組合:
-
夏普值最高
-
回報率最高
-
風險最低
In [19]:
rec=np.round(portfolio_list[1],2)*100
title='夏普值最高 年報酬:'+str(rec[0])+'% 風險:'+str(rec[1])+'%'
filter=portfolio_list[0][0]>0
portfolio_short=portfolio_list[0][0][filter]
portfolio_short_=portfolio_short.dropna(axis=1)
portfolio_short_.T.plot.pie(y='allocation', figsize=(5, 5), autopct='%1.0f%%')
plt.title(title, fontproperties="PMingLiU", fontsize=20)
plt.show()
title='報酬率最高 年報酬:'+str(rec[2])+'% 風險:'+str(rec[3])+'%'
filter=portfolio_list[0][1]>0
portfolio_short=portfolio_list[0][1][filter]
portfolio_short_=portfolio_short.dropna(axis=1)
portfolio_short_.T.plot.pie(y='allocation', figsize=(5, 5), autopct='%1.0f%%')
plt.title(title, fontproperties="PMingLiU", fontsize=20)
plt.show()
title='風險最低 年報酬:'+str(rec[4])+'% 風險:'+str(rec[5])+'%'
filter=portfolio_list[0][2]>0
portfolio_short=portfolio_list[0][2][filter]
portfolio_short_=portfolio_short.dropna(axis=1)
portfolio_short_.T.plot.pie(y='allocation', figsize=(5, 5), autopct='%1.0f%%')
plt.title(title, fontproperties="PMingLiU", fontsize=20)
plt.show()
夏普值最高
回報率最高
風險最低