<代碼已經過期,其中爬蟲鏈接已經失效>
一:馬科維茨投資組合理論
投資組合(Portfolio)是由投資人或金融機構所持有的股票、債券、衍生金融產品等組成的集合。投資組合的目的在於分散風險,投資組合按粗略的分類有三種不同的模式可供運用,即積極的、中庸的和保守的。
投資組合理論[1]:若干種證券組成的投資組合,其收益是這些證券收益的加權平均數,但是其風險不是這些證券風險的加權平均風險,投資組合能降低非系統性風險。人們進行投資,本質上是在不確定性的收益和風險中進行選擇。投資組合理論用均值-方差來刻畫這兩個關鍵因素。其中均值是指投資組合的期望收益率,它是單只證券的期望收益率的加權平均,權重為相應的投資比例。方差是指投資組合的收益率的方差。我們把收益率的標准差稱為波動率,它刻畫了投資組合的風險。
那么在證券投資決策中應該怎樣選擇收益和風險的組合呢?投資組合理論主要通過研究"理性投資者"優化投資組合。所謂理性投資者:是指在給定期望風險水平下對期望收益進行最大化,或者在給定期望收益水平下對期望風險進行最小化。
二:求解最優投資組合過程
本文最優投資組合思想是:在給定期望收益水平下對期望風險進行最小化的投資。利用的是馬克維茨的均值-方差模型:
本文實現最優投資組合的主要步驟:
1:得到夏普比率最大時的期望收益
2:得到標准差最小時的期望收益
3:根據1,2所得的期望收益,獲取預估期望收益范圍,在預估期望收益范圍內取不同值,獲取其最小方差,得到預估期望收益與最小方差的關系即獲得最小方差邊界。
4:最小方差邊界位於最小方差資產組合上方為有效邊界
5;獲取最小方差邊界上最大夏普比率,繪出CML
6:得到最小方差邊界上最大夏普比率處各股票權重
三:實證數據用例:
1:獲取10股股票歷史收盤價記錄(2014.07.01—2017.07.01)(附件:stocks.xlsx)
stocks=['601166', #興業銀行
'600004', #白雲機場
'300099', #精准信息
'601328', #交通銀行
'601318', #中國平安
'601398', #中設股份
'000333', #美的集團
'600036', #招商銀行
'600016', #民生銀行
'601818'] #光大銀行
1.1:股票歷史收盤價趨勢折線圖如下:
2:計算預期收益率:連續復利收益率即對數收益率(附件:stock_revs.xlsx)
revs=np.log(data/data.shift(1))
3: 用蒙特卡洛模擬產生大量隨機組合,得到隨機權重投資組合散點圖如下:
4:最優投資組合步驟:
4.1:得到夏普比率最大時的期望收益
def max_sharpe(weights):
return -getPortfolioInformation(weights)[2]
opts=sco.minimize(max_sharpe,numb * [1. / numb,], method='SLSQP',bounds=bnds, constraints=cons)
getPortfolioInformation(opts['x']).round(4) #opts['x'] : 得到夏普比率最大時的權重,收益率,標准差,夏普比率
#此時權重:[ 3.21290938e-01 5.00704152e-02 8.67642540e-02 0.00000000e+00 5.41874393e-01 0.00000000e+00 0.00000000e+00 0.00000000e+00
0.00000000e+00 5.15579333e-16]
# [收益率= 0.478 標准差=0.251 夏普比率=1.904]
4.2: minimize:優化,最小化風險:方差最小化
def min_variance(weights):
return getPortfolioInformation(weights)[1] ** 2
optv=sco.minimize(min_variance, numb * [1. / numb,],method='SLSQP', bounds=bnds,constraints=cons)
#此時權重:[ 1.18917047e-01 1.00755105e-01 1.04406546e-01 4.08438380e-02 4.53999968e-02 0.00000000e+00 0.00000000e+00 9.16150836e-18 5.89677468e-01 1.52059355e-17]
# [收益率= 0.309 標准差= 0.22 夏普比率=1.405]
4.3:獲取有效邊界
4.3.1:獲取最小方差邊界曲線圖,最小方差資產組合,隨機組合散點圖:
指定收益率范圍 [0.1545, 0.5736 ],求最小方差:
def min_sd(weights):
return getPortfolioInformation(weights)[1]
tvols = []
infor_min_sd=[]
#獲取在指定期望收益下的最小標准差:
for tret in trets:
cons = ({'type': 'eq', 'fun': lambda x: getPortfolioInformation(x)[0] - tret},
{'type': 'eq', 'fun': lambda x: np.sum(x)-1})
res = sco.minimize(min_sd, numb * [1. / numb,], method='SLSQP',bounds=bnds, constraints=cons)
infor_min_sd.append(res) # tret 唯一的
tvols.append(res['fun']) #獲取函數返回值,即最小標准差
tvols = np.array(tvols)
ind_min_sd = np.argmin(tvols) #最小方差組合處進行划分,分兩段
evols = tvols[:ind_min_sd]
erets = trets[:ind_min_sd]
tck = sci.splrep(erets,evols ) #B-Spline樣條曲線函數 #前一個必須是唯一
y2 = np.linspace(np.min(erets), np.max(erets), 100)
x2 = sci.splev(y2, tck)
evols = tvols[ind_min_sd:]
erets = trets[ind_min_sd:]
tck = sci.splrep(evols, erets)
x3 = np.linspace(np.min(evols), np.max(evols), 100)
y3 = sci.splev(x3, tck)
plt.figure(figsize=(10, 8))
plt.scatter(pvols, prets, c=prets/pvols,s=5, marker='.')
plt.plot(x2, y2,'g',label=u"最小方差邊界")
plt.plot(x3, y3,'g',label=u"最小方差邊界")
plt.axhline(y=rev_min_variance,color='b',label=u"最小方差資產組合") #最小方差資產組合
plt.plot(getPortfolioInformation(opts['x'])[1], getPortfolioInformation(opts['x'])[0],'r*', markersize=5.0)#最大夏普比率
plt.plot(getPortfolioInformation(optv['x'])[1], getPortfolioInformation(optv['x'])[0],'y*', markersize=5.0)#最小方差
plt.grid(True)
plt.xlabel('Expect Volatility')
plt.ylabel('Expect Return')
plt.show()
結果顯示如下
4.3.2:獲取有效邊界曲線圖:
plt.figure(figsize=(10, 8))
plt.scatter(pvols, prets, c=prets/pvols,s=5, marker='.')
plt.plot(x3, y3,'g',label=u"有效邊界")
plt.plot(getPortfolioInformation(opts['x'])[1], getPortfolioInformation(opts['x'])[0],'r*', markersize=8.0)#最大夏普比率
plt.plot(getPortfolioInformation(optv['x'])[1], getPortfolioInformation(optv['x'])[0],'y*', markersize=8.0)#最小方差
plt.grid(True)
plt.xlabel('Expect Volatility')
plt.ylabel('Expect Return')
plt.show()
5: 獲取最小方差邊界上最大夏普比率,繪出CML
5.1: B-Spline樣條曲線的參數
tck = sci.splrep(evols, erets)
5.2: B-Spline樣條曲線函數
def f(x):
return sci.splev(x, tck, der=0)
5.3: B-Spline樣條曲線函數一階導數
def df(x):
return sci.splev(x, tck, der=1)
5.4: 構造非線性函數,使函數fun(x)無限逼近0向量, risk_free_return:無風險收益,默認為0.00
def fun(x, risk_free_return=0.00):
e1 = risk_free_return - x[0]
e2 = risk_free_return + x[1] * x[2] - f(x[2])
e3 = x[1] - df(x[2])
return e1, e2, e3
5.5 利用最小二乘法 無限逼近0, 無風險收益率:0,斜率:0.5,初始自變量:zone
X = sco.fsolve(fun, [0.00, 0.50, zone])
plt.figure(figsize=(12, 6))
#圓點為隨機資產組合
plt.scatter(pvols, prets,c=prets/ pvols,s=5, marker='.')#隨機組合散點集
plt.plot(x3, y3,'g',label=u"有效邊界")
plt.plot(getPortfolioInformation(opts['x'])[1], getPortfolioInformation(opts['x'])[0],'g*', markersize=5.0)#最大夏普比率
plt.plot(getPortfolioInformation(optv['x'])[1], getPortfolioInformation(optv['x'])[0],'y*', markersize=5.0)#最小方差
#設定資本市場線CML的x范圍從0到1.5最大夏普利率時標准差值
x = np.linspace(0.0, 1.5*zone)
#帶入公式a+b*x求得y,作圖
plt.plot(x, X[0] + X[1] * x, lw=1.5)
#標出資本市場線與有效邊界的切點,綠星處
plt.plot(X[2], f(X[2]), 'r*', markersize=5.0)
plt.grid(True)
plt.axhline(0, color='k', ls='--', lw=2.0)
plt.axvline(0, color='k', ls='--', lw=2.0)
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.colorbar(label='Sharpe ratio')
plt.show()
#最大夏普比率點: (0.251241778282 ,0.478266895458)
#切點: (0.251147161667, 0.4781282509275755)
結果圖如下:
6: 得到最小方差邊界上最大夏普比率處各股票權重:
根據收益率差絕對值最小選取權重進行投資:
rev_result=f(X[2])
flag=0
temp=abs(trets[0]-rev_result)
length=len(trets)
for i in range(1,length):
if abs(trets[i]-rev_result)<temp:
temp=trets[i]-rev_result
flag=i
weight_result=infor_min_sd[flag]['x']
all=0 #最終為 1.0
for i in range(10):
all=all+weight_result[i]
print('{:.5f}'.format(weight_result[i]))
# weight_result=[ 0.00000 0.04802 #白雲機場
0.00000 0.85880 #交通銀行 0.00000 0.00000 0.00000 0.00000 0.09318 #民生銀行 0.00000 ]
故最終投資股票是:
0.04802 #白雲機場
0.85880 #交通銀行
0.09318 #民生銀行