當前位置:股票大全官網 - 股票投資 - 如何用python優化Markowitz的投資組合

如何用python優化Markowitz的投資組合

0.導入所需的包作為pd導入熊貓。

將numpy作為np導入

將statsmodels.api作為sm #統計操作導入

將scipy.stats作為scs #科學計算導入

導入mapplotlib.pyplot asplt #繪圖

1.選擇幾只感興趣的股票。

000413徐東光電,00063中興通訊,002007華蘭生物,00001平安銀行,000002萬科a

並對比數據(2015-01-01至2015-12-31)。

在[1]中:

stock_set = ['000413。XSHE ',' 000063。XSHE ',' 002007。XSHE ',' 000001。XSHE ',' 000002。XSHE']

noa = len(stock_set)

df = get_price(stock_set,start _ date = ' 2015-01-01 ',end _ date = ' 2015-12-31 ','每日',['收盤'])

data = df['close']

#標準化時間序列數據

(data/data.ix[0]*100)。plot(figsize = (8,5))

Out[1]:

2.計算不同證券的均值和協方差。

壹年252個交易日,用日收益得出年化收益。計算投資資產的協方差是構建投資組合過程的核心部分。使用pandas內置方法產生協方差矩陣。

在[2]中:

returns = NP . log(data/data . shift(1))

returns.mean()*252

Out[2]:

000413.XSHE 0.184516

000063.XSHE 0.176790

002007.XSHE 0.309077

000001.XSHE -0.102059

000002.XSHE 0.547441

在[3]中:

returns.cov()*252

Out[3]:

3.隨機為不同的資產分配初始權重。

由於a股不允許建立空倉,所以所有的權重系數都在0-1之間。

在[4]中:

權重= np.random.random(noa)

權重/= np.sum(權重)

砝碼

Out[4]:

數組([ 0.37505798,0.21652754,0.31590981,0.06087709,0.03162758])

4.計算投資組合的預期年化回報、投資組合方差和投資組合標準差。

在[5]中:

NP . sum(returns . mean()* weights)* 252

Out[5]:

0.21622558669017816

在[6]中:

np.dot(權重。t,np.dot(returns.cov()*252,weights))

Out[6]:

0.23595133640121463

在[7]中:

np.sqrt(np.dot(權重。t,np.dot(returns.cov()* 252,權重)))

Out[7]:

0.4857482232609962

5.蒙特卡羅模擬產生大量的隨機組合。

此時,我們最想知道的是,對於給定的股票池(投資組合),如何找到風險和收益的平衡點。

接下來,通過蒙特卡羅模擬,產生大量隨機權重向量,並記錄隨機組合的期望收益和方差。

在[8]中:

port_returns = []

port_variance = []

對於範圍內的p(4000):

權重= np.random.random(noa)

權重/=np.sum(權重)

port _ returns . append(NP . sum(returns . mean()* 252 * weights))

port _ variance . append(NP . sqrt(NP . dot(weights。t,np.dot(returns.cov()*252,weights))))

端口返回= np.array(端口返回)

端口差異= np.array(端口差異)

#無風險利率設定為4%

無風險= 0.04

plt.figure(figsize = (8,4))

plt.scatter(port_variance,port_returns,c =(port _ returns-risk _ free)/port _ variance,marker = 'o ')

plt.grid(真)

plt.xlabel('例外波動率')

plt.ylabel('預期回報')

plt.colorbar(label = '夏普比率')

Out[8]:

6.投資組合優化1-夏普最大值

建立統計功能,記錄重要的投資組合統計數據(收益、方差和夏普比率)。

通過求解約束優化問題,得到最優解。約束條件是總權重為1。

在[9]中:

定義統計(重量):

權重= np.array(權重)

port _ returns = NP . sum(returns . mean()* weights)* 252

port _ variance = NP . sqrt(NP . dot(weights。t,np.dot(returns.cov()*252,權重)))

return NP . array([端口返回,端口變化,端口返回/端口變化])

#最優投資組合的推導是壹個約束優化問題。

將scipy.optimize導入為sco

#最小化夏普指數的負值

def min_sharpe(權重):

返回-統計(權重)[2]

#約束是所有參數(權重)之和為1。這可以用最小化函數的約定來表示,如下所示

cons = ({'type':'eq ',' fun ':lambda x:NP . sum(x)-1 })

#我們還將參數值(權重)限制在0到1之間。這些值作為由多個元組組成的元組被提供給最小化函數。

bnds = tuple((0,1) for x in range(noa))

#優化函數調用中唯壹忽略的輸入是起始參數列表(權重的初始猜測)。我們簡單地使用平均分布。

opts = sco.minimize(min_sharpe,noa*[1。/noa,],方法= 'SLSQP ',界限= bnds,約束= cons)

選擇

Out[9]:

狀態:0

成功:真的

njev: 4

非正規教育:28

好玩:-1.1623048291871221

x:數組([ -3.60840218e-16,2.24626781e-16,1.63619563 e-01,-2.27085639e-16,8.36380437 e-06537

消息:“優化成功終止。”

江淮:數組([1.81575805 e-01,5.40387481e-01,8.18073750e-05,1.03137662e+00,-1.6003847467

nit: 4

獲得的最佳組合權重向量是:

在[10]:

opts['x']。回合(3)

Out[10]:

數組([-0。, 0., 0.164, -0., 0.836])

夏普的三個統計數據的最大組合是:

在[11]:

#預期收益率、預期波動率和最優夏普指數

統計數據(opts['x'])。回合(3)

Out[11]:

數組([ 0.508,0.437,1.162])

7.投資組合優化2-最小方差

接下來,我們通過最小化方差來選擇最佳投資組合。

在[12]:

#但是我們定義了壹個函數來最小化方差。

定義最小方差(權重):

返回統計數據(權重)[1]

optv = sco.minimize(min_variance,noa*[1。/noa,],方法= 'SLSQP ',界限= bnds,約束= cons)

optv

Out[12]:

狀態:0

成功:真的

njev: 7

非正規教育:50

樂趣:0.3842969450547221

x:數組([1.14787640 e-01,3.28089742e-17,2.09584008e-01,3.53487044e-01,3.22141307 e-0654338

消息:“優化成功終止。”

jac:數組([ 0.3851725,0.43591119,0.3861807,0.3849672,0.38553924,0。])

nit: 7

方差最小的最優組合權向量和組合的統計數據分別為:

在[13]:

optv['x']。回合(3)

Out[13]:

數組([ 0.115,0。, 0.21 , 0.353, 0.322])

在[14]:

#獲得預期收益率、波動率和夏普指數。

統計數據(optv['x'])。回合(3)

Out[14]:

數組([ 0.226,0.385,0.587])

8.組合的有效前沿

有效邊界由在給定目標收益率下具有最小差異的投資組合組成。

優化中采用了兩個約束,1。給定目標收益率,2。投資組合權重之和為1。

在[15]:

定義最小方差(權重):

返回統計數據(權重)[1]

#當不同的目標回報水平(target_returns)循環時,最小化的壹個約束條件將改變。

target_returns = np.linspace(0.0,0.5,50)

target_variance = []

對於target_returns中的tar:

cons = ({'type':'eq ',' fun ':lambda x:statistics(x)[0]-tar },{'type':'eq ',' fun ':lambda x:NP . sum(x)-1 })

res = sco.minimize(min_variance,noa*[1。/noa,],方法= 'SLSQP ',界限= bnds,約束= cons)

target _ variance . append(RES[' fun '])

目標方差= np.array(目標方差)

下面是優化結果的演示。

交叉:曲線是有效前沿(目標收益率下的最優投資組合)

紅星:夏普最大的投資組合

黃興:最小方差投資組合

在[16]:

plt.figure(figsize = (8,4))

#圓圈:蒙特卡羅隨機組合分布

plt.scatter(port_variance,port_returns,c = port_returns/port_variance,marker = 'o ')

#交叉:有效邊界

plt.scatter(target_variance,target_returns,c = target _ returns/target _ variance,marker = 'x ')

#紅星:標誌最高夏普組合

PLT . plot(statistics(opts[' x '])[1],statistics(opts['x'])[0],' r* ',markersize = 15.0)

#黃星:標記的最小方差組合

PLT . plot(statistics(optv[' x '])[1],statistics(optv['x'])[0],' y* ',markersize = 15.0)

plt.grid(真)

plt.xlabel('預期波動率')

plt.ylabel('預期回報')

plt.colorbar(label = '夏普比率')