python實(shí)現(xiàn)資產(chǎn)配置(2)--Blacklitterman 模型

1. Black-Litterman模型簡(jiǎn)介

python實(shí)現(xiàn)資產(chǎn)配置(1)----Markowitz 投資組合模型中, 我們已經(jīng)見過如何使用Markowitz求得最優(yōu)資產(chǎn)配比. 這是一種在已知未來各資產(chǎn)的概率分布,然后再求解的方法.

Markowitz模型輸入?yún)?shù)包括歷史數(shù)據(jù)法和情景分析法兩種方法,情景分析法的缺點(diǎn)是主觀因素,隨意性太強(qiáng),因此使用歷史數(shù)據(jù)法, 將資產(chǎn)的均值和協(xié)方差輸入模型是比較常見的作法. 不過, 不足之處很明顯: 未來的資產(chǎn)收益率分布不一定與過去相同. 此外, Markowitz 模型結(jié)果對(duì)輸入?yún)?shù)過于敏感.

Black-Litterman模型就是基于此的改進(jìn). 其核心思想是將投資者對(duì)大類資產(chǎn)的觀點(diǎn) (主觀觀點(diǎn)) 與市場(chǎng)均衡收益率 (先驗(yàn)預(yù)期收益率)相結(jié)合,從而形成新的預(yù)期收益率(后驗(yàn)預(yù)期收益率). 這里的先驗(yàn)預(yù)期收益率的分布可以是貝葉斯推斷中的先驗(yàn)概率密度函數(shù)的多元正態(tài)分布形式,投資者的主觀觀點(diǎn)就是貝葉斯推斷中的似然函數(shù)(可以看作新的信息, 因?yàn)樽龀鲋饔^判斷必然是從外界獲取得到了這些資產(chǎn)的收益率變化信息), 而相應(yīng)的, 后驗(yàn)預(yù)期收益率也可以從后驗(yàn)概率密度函數(shù)中得到. 具體的推導(dǎo)可以看我的這篇文章:從貝葉斯定理到貝葉斯推斷.

BL模型的求解步驟包括下面幾步:

(1) 使用歷史數(shù)據(jù)估計(jì)預(yù)期收益率的協(xié)方差矩陣作為先驗(yàn)概率密度函數(shù)的協(xié)方差.

(2) 確定市場(chǎng)預(yù)期之收益率向量, 也就是先驗(yàn)預(yù)期收益之期望值. 作為先驗(yàn)概率密度函數(shù)的均值. 或者使用現(xiàn)有的期望值和方差來反推市場(chǎng)隱含的均衡收益率(Implied Equilibrium Return Vector), 不過在使用這種方法時(shí), 需要知道無風(fēng)險(xiǎn)收益率R_f的大小.

(3) 融合投資人的個(gè)人觀點(diǎn),即根據(jù)歷史數(shù)據(jù)(看法變量的方差)和個(gè)人看法(看法向量的均值)

(4) 修正后驗(yàn)收益.
\mu^{BL} = [(\tau\Sigma)^{-1}+(P^T\Omega^{-1}P)]^{-1}[(\tau\Sigma)^{-1}\Pi+P^T\Omega^{-1}Q] \\ \Sigma^{BL} = \Sigma+[(\tau\Sigma)^{-1}+(P^T\Omega^{-1}P)]^{-1}
\tau是均衡收益率協(xié)方差的調(diào)整系數(shù),可以根據(jù)信心水平來判斷. \Sigma是歷史資產(chǎn)收益率的協(xié)方差矩陣, P是投資者的觀點(diǎn)矩陣,\Omega是似然函數(shù)(即投資者觀點(diǎn)函數(shù))中的協(xié)方差矩陣,其值為P^T(\tau\Sigma)P的對(duì)角陣, \Pi是先驗(yàn)收益率的期望值.

(5) 投資組合優(yōu)化: 將修正后的期望值與協(xié)方差矩陣即\mu^{BL}, \Sigma^{BL}重新代入Markowitz投資組合模型求解.

2. Black-litterman 模型的python實(shí)現(xiàn)

(1)定義求解函數(shù),輸入為投資者觀點(diǎn)P,Q以及目前資產(chǎn)的市場(chǎng)收益率矩陣,輸出為后驗(yàn)的市場(chǎng)收益率和協(xié)方差矩陣.

import numpy as np
import baostock as bs
import pandas as pd
from numpy import  linalg
def blacklitterman(returns,tau,P,Q):
    mu = returns.mean()
    sigma = returns.cov()
    pil = np.expand_dims(mu,axis = 0).T
    ts = tau * sigma
    ts_1 = linalg.inv(ts)
    Omega = np.dot(np.dot(P,ts), P.T)* np.eye(Q.shape[0])
    Omega_1 = linalg.inv(Omega)
    er = np.dot(linalg.inv(ts_1 + np.dot(np.dot(P.T,Omega_1),P)),(np.dot(ts_1 ,pil)+np.dot(np.dot(P.T,Omega_1),Q)))
    posterirorSigma = linalg.inv(ts_1 + np.dot(np.dot(P.T,Omega_1),P))
    return [er, posterirorSigma]

(2) 實(shí)列分析
我們繼續(xù)研究python實(shí)現(xiàn)資產(chǎn)配置(1)----Markowitz 投資組合模型中的五支股票: 白云機(jī)場(chǎng), 福建高速, 華夏銀行, 生益科技和浙能電力. 假設(shè)現(xiàn)在分析師的觀點(diǎn)為:

  • 白云機(jī)場(chǎng), 華夏銀行, 浙能電力, 生益科技四只股票的日均收益率均值為0.3%
  • 白云機(jī)場(chǎng)和福建高速的日均收益率均值高于浙能電力0.1%
    則投資者觀點(diǎn)矩陣P為:
    \begin{bmatrix} 1 & 0 & 1&1&1 \\ 0.5 & 0.5 &0&0&-1 \\ \end{bmatrix}
    Q 為:
    \begin{bmatrix} 0.012 \\ 0.001 \\ \end{bmatrix}
    則獲取后驗(yàn)收益率和協(xié)方差的代碼為:
pick1 = np.array([1,0,1,1,1])
q1 = np.array([0.003*4])
pick2 = np.array([0.5,0.5,0,0,-1])
q2 = np.array([0.001])
P = np.array([pick1,pick2])
Q = np.array([q1,q2])

獲取股票數(shù)據(jù), 并且獲得后驗(yàn)的均值和方差:

def get_stock_data(t1,t2,stock_name):
    lg = bs.login()
    print('login respond error_code:' + lg.error_code)
    print('login respond  error_msg:' + lg.error_msg)

    #### 獲取滬深A(yù)股歷史K線數(shù)據(jù) ####
    # 詳細(xì)指標(biāo)參數(shù),參見“歷史行情指標(biāo)參數(shù)”章節(jié)
    rs = bs.query_history_k_data(stock_name,
                                 "date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST",
                                 start_date=t1, end_date=t2,
                                 frequency="d", adjustflag="3")
    print('query_history_k_data respond error_code:' + rs.error_code)
    print('query_history_k_data respond  error_msg:' + rs.error_msg)

    #### 打印結(jié)果集 ####
    data_list = []
    while (rs.error_code == '0') & rs.next():
        # 獲取一條記錄,將記錄合并在一起
        data_list.append(rs.get_row_data())
    result = pd.DataFrame(data_list, columns=rs.fields)
    print(result)

    #### 結(jié)果集輸出到csv文件 ####
    result.to_csv("D:\stockdata\history_A_stock_k_data.csv", index=False)
    print(result)

    #### 登出系統(tǒng) ####
    bs.logout()
    result['date'] = pd.to_datetime(result['date'])
    result.set_index("date", inplace=True)
    return result

byjc = get_stock_data('2014-1-1','2015-1-1','sh.600004')
hxyh = get_stock_data('2014-1-1','2015-1-1','sh.600015')
zndl = get_stock_data('2014-1-1','2015-1-1','sh.600023')
fjgs = get_stock_data('2014-1-1','2015-1-1','sh.600033')
sykj = get_stock_data('2014-1-1','2015-1-1','sh.600183')


by = byjc['pctChg']
by.name = 'byjc'
by = pd.DataFrame(by,dtype=np.float)/100


hx = hxyh['pctChg']
hx.name = 'hxyh'
hx = pd.DataFrame(hx,dtype=np.float)/100

zn = zndl['pctChg']
zn.name = 'zndl'
zn = pd.DataFrame(zn,dtype=np.float)/100

fj = fjgs['pctChg']
fj.name = 'fjgs'
fj = pd.DataFrame(fj,dtype=np.float)/100

sy = sykj['pctChg']
sy.name = 'sykj'
sy = pd.DataFrame(sy,dtype=np.float)/100

sh_return = pd.concat([by,fj,hx,sy,zn],axis=1)
res = blacklitterman(sh_return,0.1,P,Q)
p_mean = pd.DataFrame(res[0],index = sh_return.columns, columns = ['posterior_mean'])
p_cov = res[1]
print(p_mean)
print(p_cov)

這時(shí)候,已經(jīng)可以使用Markowitz模型進(jìn)行資產(chǎn)的配置. 定義新的函數(shù)blminVar以求解資產(chǎn)配置權(quán)重. 該函數(shù)的輸入變量為blacklitterman函數(shù)的輸出結(jié)果, 以及投資人的目標(biāo)收益率goalRet.假設(shè)目標(biāo)收益率為年化70%,則goalRet = 0.7:

def blminVar(blres, goalRet):
    covs = np.array(blres[1],dtype=float)
    means = np.array(blres[0],dtype=float)
    L1 = np.append(np.append(covs.swapaxes(0,1),[means.flatten()],axis=0),
                   [np.ones(len(means))],axis=0).swapaxes(0,1)

    L2 = list(np.ones(len(means)))
    L2.extend([0,0])
    L3 = list(means)
    L3.extend([0,0])
    L4 = np.array([L2,L3],dtype=float)
    L = np.append(L1,L4,axis=0)
    results = linalg.solve(L,np.append(np.zeros(len(means)),[1,goalRet]))

    return pd.DataFrame(results[:-2],columns = ['p_weight'])

blresult = blminVar(res,0.70/252)
print(blresult)

輸出結(jié)果為:


0-5分別對(duì)應(yīng)上面的五只股票.

參考文獻(xiàn)

  • 蔡立耑:量化投資——以python為工具. 電子工業(yè)出版社
  • 華泰證券: 周期輪動(dòng)下的BL資產(chǎn)配置策略
  • 中信建投:基于Black-Litterman的多資產(chǎn)配置策略
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容