【資產配置】第三代資產配置理論:Black-Litterman
介紹Black-Litterman模型,一個能結合分析師主觀觀點和市場數據的資產定價模型。從核心想法出發,接著推倒數學模型,最後工程實踐。
原創不易,若轉載請先告知,本人保有法律追訴權
警語:本文為學術目的探討,不表示任何實質投資建議,本部落格也不為投資損益負責,投資人須自負盈虧。
Abstract
BL模型認為對未來的預期報酬應為市場隱含報酬(implied return)和投資者對於未來需求報酬(requied return)的線性組合。其修正了Mean-Variance對於參數太過敏感難以應用的缺點,並且能將分析師的主觀預期納入模型進行評估。
Black-Letterman Model
Idea of model
BL模型認為對未來的預期報酬應由市場隱含報酬(implied return)和投資者對於未來需求報酬(requied return)兩者共同決定,至於要如何決定呢?敝人有幸於課堂上聽過國內基金管理大師,任職於國立中正大學財務金融學系的黃介良博士的講解,黃博士對此模型有一個深入解出的解釋:就用最naive的方法各給他們一個權重然後加權平均,數學上來說,就是兩者的線性組合:
其中A,B分別代表市場隱含報酬率和主觀預期的權重,tau常量為比例系数介於0–1之間,如果越接近0代表市場隱含波動率越不重要
Implied Return
市場隱含報酬率主要由MV定價模型的一階條件F.O.C.所得來,以下假設我們有N筆資產
- lambda 為純量風險係數,可用Sharpe ratio
- Sigma 是NxN共變異數矩陣
- w 為 Nx1的行向量
接下來我們令,表示市場的隱含報酬率,要注意的是tau值
required return
接著假設我們對N個資產共有k個主觀預期的想法,則我們主觀預期報酬率Q會由主觀想法P和CAPM預期收益E(r)所構成,其中預期誤差服從iid常態分配,因此會滿足以下均衡
- P : KxN 觀點矩陣
- E( r ): Nx1收益向量
- Q: Kx1 對於預期報酬的看法向量
- Omega : KxK 共變異矩陣,表預期報酬看法的不確定性
接著我們要估計收益向量 E(r),即為給定主觀預期P情況下能達到預期報酬率Q的收益水準,因此可用OLS做Q對P的回歸取出係數,或是直接用下方的closed form:
Combine all
最終一樣透過最佳化求解權重:
Implement
台灣對於金融/經濟的教育對工程實踐的部分著墨不深,所幸筆者在學時大量修習工學院和理學院的課程,接下來以python針對T=15期, N=5筆資產, K=3種view的naive case做工程實踐,以下為模擬出的時間序列。
class BL_Model:
def __init__(self, K, N, tau, lamb, w0, P, Q, ret):
# dimension
self.K = K
self.N = N
# parameter
self.tau = tau
self.lamb = lamb
self.w = w0
###------------ investor's view ------------###
self.P = self.test_P(P, self.K, self.N)
self.Q = self.test_Q(Q, self.K)
###------------ implied return ------------###
self.sigma = self.get_sigma(ret)
self.pi = self.get_pi(self.lamb, self.sigma, self.w)
self.A = self.get_A(self.tau, self.sigma)
###------------ required return ------------###
self.omega = self.get_omega(self.tau, self.P, self.sigma)
self.B = self.get_B(self.P, self.omega)
self.expRet = self.get_expRet(self.A, self.B, self.pi, self.omega, self.P, self. Q)
def test_P(self, P, k, n):
P = np.array(P)
assert P.shape[0] == k, "[Error]: Row dimension of P should be {0}, but {1}".format(k, P.shape[0])
assert P.shape[1] == n, "[Error]: Col dimension of P should be {0}, but {1}".format(n, P.shape[1])
sum_over_vec = np.apply_along_axis(np.sum, axis=1, arr=P)
assert sum_over_vec.sum() == 0, "Sum over each vector should be zero, but received {}".format(sum_over_vec)
return P
def test_Q(self, Q, k):
Q = np.array(Q).reshape(3, 1)
assert Q.shape[0] == k, "[Error]: Row dimension of Q should be {0}, but {1}".format(k, Q.shape[0])
assert Q.shape[1] == 1, "[Error]: Col dimension of Q should be 1, but {}".format(Q.shape[1])
return Q
def get_expRet(self, A, B, pi, omega, P, Q):
"""Expected return to optimal
"""
denom = inv(A+B)
nom = (A@pi + P.T @ inv(omega) @ Q )
obj = denom@nom
assert obj.shape[0] == self.N, "[Error]: Row dimension of obj should be {0}, but {1}".format(self.N, obj.shape[0])
assert obj.shape[1] == 1, "[Error]: Col dimension of obj should be {0}, but {1}".format(1, obj.shape[1])
return obj
def get_A(self, tau, sigma):
return inv(tau*sigma)
def get_B(self, P, omega):
return P.T @ np.linalg.inv(omega) @ P
###------------ implied return ------------###
def get_pi(self, lamb, sigma, w):
pi = (lamb * sigma @ w).reshape(-1, 1)
assert pi.shape[0] == self.N, "[Error]: Row dimension of pi should be {0}, but {1}".format(self.N, pi.shape[0])
assert pi.shape[1] == 1, "[Error]: Col dimension of pi should be {0}, but {1}".format(1, pi.shape[1])
return pi
def get_sigma(self, ret):
return np.cov(ret, rowvar=False)
###------------ required return ------------###
def get_omega(self, tau, P, sigma):
omega = tau * P @ sigma @ P.T
assert omega.shape[0] == self.K, "[Error]: Row dimension of omega should be {0}, but {1}".format(self.K, omega.shape[0])
assert omega.shape[1] == self.K, "[Error]: Col dimension of omega should be {0}, but {1}".format(self.K, omega.shape[1])
return omega
Example of P, Q
There are 5 assets A, B, C, D, E, and 3 view:
- Return of A > B by 10%
- Return of C > A by 0.5%
- Return of A > D,E by 3%
這邊要注意每一個row vector是一個view
P = [[1, -1, 0, 0, 0], # view one
[-1, 0, 1, 0, 0], # view thwo
[1, 0, 0, -0.5, -0.5] # view three
]
Q = [0.1, 0.005, 0.03]
w0 = np.array([1/N] * N)
BL = BL_Model(K, N, tau, lamb, w0, P, Q, mk_rets)
BL.expRet
Optimal Function
這裡需要導入autograd模組的自動微分引擎幫助計算jacobian矩陣,最佳化算法採用SLSQP,原因是限制式為線性不等式。
from autograd import jacobian, hessian
class BLM_Optim(BL_Model):
def __init__(self, K, N, tau, lamb, w0, P, Q, ret, w_min=0, w_max=1):
super().__init__(K, N, tau, lamb, w0, P, Q, ret)
self.w_min = w_min
self.w_max = w_max
##### import from autograd module
self.jacb_func = jacobian(self.obj)
self.hess_func = hessian(self.obj)
##### for optimal
self.constraints = [
{'type': 'eq', 'fun': self.total_weight_equal_one_constraint},
{'type': 'ineq', 'fun': self.long_only_constraint}
]
self.bound = self.get_bound()
def obj(self, w):
self.pi = self.get_pi(self.lamb, self.sigma, w)
self.expRet = self.get_expRet(self.A, self.B, self.pi, self.omega, self.P, self.Q)
return -w@self.expRet
def total_weight_equal_one_constraint(self, w):
return np.sum(w)-1.0
def long_only_constraint(self, w):
return w
def get_bound(self):
return tuple((self.w_min, self.w_max) for i in range(self.N))
def jacb_val(self, w):
return self.jacb_func(w).flatten()
def hess_val(self, w):
return self.hess_func(w)
tau = 0.5
lamb = 0.5
w0 = np.array([1/N] * N)
BLM = BLM_Optim(K, N, tau, lamb, w0, P, Q, mk_rets, w_min=0, w_max=1)
res = minimize(fun=BLM.obj,
x0 = w0,
#args = (lamb, sigma, omega, A, B, P, Q),
method = "SLSQP",
constraints = BLM.constraints,
bounds = BLM.bound,
tol = 1e-8
)
print("Optimal function value : {}".format(res.fun))
print("Sum of weights : {}".format(np.sum(res.x)))
print("Optimal weights: \n{}".format(res.x))
得出的函數最佳值為-27,筆者試過其他最佳化算法,也是得出這個結果,或許文獻中有能滿足K.K.T.條件的更好最佳化算法,不過筆者暫無涉略。
Optimal function value : -27.442331840888727
Sum of weights : 1.0000000000000338
Optimal weights:
[3.36952688e-14 0.00000000e+00 0.00000000e+00 1.00000000e+00
0.00000000e+00]
Conclusion
- BL模型認為對未來的預期報酬應為市場隱含報酬(implied return)和投資者對於未來需求報酬(requied return)的線性組合。
- 優點:其修正了Mean-Variance對於參數太過敏感難以應用的缺點,並且能將分析師的主觀預期納入模型進行評估
- 缺點:不具備風控效果,由於其未能將風險因子納入模型,用此模型做資產定價仍然過於主觀
- 工程實現:對於有沒有最佳化算法能夠在這個問題上找到全局最佳解,需要再去文獻中找答案
Reference
1: 中正大學財務金融學系,黃介良博士的Power Point
2: Black Fischer and Robert Litterman (1992) Global Portfolio Optimization, Financial Analysts Journal 48, pp.28–43.
3: Christodoulakis, George A (2002) Bayesian Optimal Portfolio Selection: the Black-Litterman Approach, Working paper.