风险平价组合(risk parity)理论与实践

风险平价
标签: #<Tag:0x00007f5be8742250>

(iQuant) #1

本文介绍了风险平价组合的理论与实践;后续文章将对risk parity组合进行更深入探讨以及引入预期收益后的资产配置实战策略。

前言

  • 资产配置是个很广泛的话题,在投资中是一个非常重要的话题

  • 从使用场景分类上来看,资产配置可以是宏观的资产配置,比如货币类、债券类、权益类之间的配置;当然也可以是某一大类资产下的配置,比如在沪深300成分股不同标的之间的权重配置

  • 但不管怎么说,从方法层面上看,对于不同场景下的使用都是一致的,只不过需要注意不同场景使用下的一些特殊处理

  • 本篇作为资产配置研究系列,理论结合实践,深入浅出,可直接使用

  • 后续会根据时间安排,逐步介绍资产配置领域的相关理论与实践

摘要

  • 介绍了风险平价理论知识
  • 介绍了怎样做到风险平价
  • 风险平价实践的Python代码

简介

  • 资产配置在投资中是非常重要的过程,经典的资产配置方式就是马格维茨的均值-方差模型。目标是在给定预期收益率下最小化方差(风险),或给定风险水平下最大化收益,通过拉格朗日乘子法,可以计算出一个有效前沿,我们可以根据有效前沿来配置资产。但在实践过程中,我们常常发现计算的结果是某几个资产的权重特别大,收益和风险都集中在了这些资产上

  • 也有许多对均值方差进行优化的方法,比如加入风险厌恶系数考虑效用函数的最大化,或者加入个性化条件,要求每一大类的配置比例都不得超过35%等,还有从统计的角度出发,找一些更好的估计协方差阵的方法

  • 基于均值方差模型的不足,PanAgora基金的首席投资官Edward Qian博士提出了著名的风险平价(Risk Parity)策略,这一思想被Bridgewater基金运用于实际投资中,本贴将详细介绍风险平价配置方法的理论与实践

克隆策略

理论介绍

风险平价投资组合是一种资产配置,其重点是配置风险,而不是配置资产。例如,典型的债券40%、股票60%投资组合中,股票风险很大。风险平价(等同风险)是这样一种投资组合:单个资产(在这种情况下为债券和股票)对整体投资组合总风险具有相同的风险贡献。该理论在过去几十年中得到普及和发展,基于风险的资产配置理念已被用于许多策略,如管理期货策略和着名的桥水全天候基金。有研究表明,这种资产配置策略比基于资产的配置策略提供更好的风险调整回报。

我将讨论风险平价的一个非常基本的例子,以及如何构建简单的风险平价(相等风险)投资组合,并将其扩展到风险预算组合(目标风险分配)的具体实现。

首先将资产j的边际风险贡献($MRC_j$)定义为:

$$MRC_j = \frac{\partial \sigma_p}{\partial w_j} = \frac{(V*w)_j}{\sigma_p}$$

其中:

$w_j$表示第j个资产的权重

$V$表示资产的协方差矩阵

$\sigma_p = \sqrt{w*V*w^T}$ 表示组合风险

然后,资产j对总投资组合的风险贡献($RC_j$)为:

$$RC_j = w*MRC_j = \frac{{w_j(V*w)}_j}{\sigma_p}$$

风险平价投资组合是所有资产中每个资产的$RC$相等的投资组合。

计算风险平价组合的权重,本质上属于一个二次优化问题。

让投资组合资产$RC$的平方误差的总和为(优化问题的目标函数):

$$J(x)=(\sum_{i=1}^n\sum_{j=1}^n(w_i(V*w))_i-w_j(V*w)_j)^2$$

优化问题的约束条件为:

$$minJ(x)$$$$s.t.\sum_iw_i = 1 $$

$$1 \geq wi \geq 0$$

代码实现

  • 假设组合有四项资产
  • 资产收益率为$R$
  • 资产协方差为$V$
In [1]:
# 协方差矩阵和收益率向量
from scipy.optimize import minimize
V = np.matrix('123 37.5 70 30; 37.5 122 72 13.5; 70 72 321 -32; 30 13.5 -32 52')/100  # covariance
R = np.matrix('14; 12; 15; 7')/100 # return
In [2]:
 # 风险预算优化
def calculate_portfolio_var(w,V):
    # 计算组合风险的函数
    w = np.matrix(w)
    return (w*V*w.T)[0,0]

def calculate_risk_contribution(w,V):
    # 计算单个资产对总体风险贡献度的函数
    w = np.matrix(w)
    sigma = np.sqrt(calculate_portfolio_var(w,V))
    # 边际风险贡献
    MRC = V*w.T
    # 风险贡献
    RC = np.multiply(MRC,w.T)/sigma
    return RC

def risk_budget_objective(x,pars):
    # 计算组合风险
    V = pars[0]# 协方差矩阵
    x_t = pars[1] # 组合中资产预期风险贡献度的目标向量
    sig_p =  np.sqrt(calculate_portfolio_var(x,V)) # portfolio sigma
    risk_target = np.asmatrix(np.multiply(sig_p,x_t))
    asset_RC = calculate_risk_contribution(x,V)
    J = sum(np.square(asset_RC-risk_target.T))[0,0] # sum of squared error
    return J

def total_weight_constraint(x):
    return np.sum(x)-1.0

def long_only_constraint(x):
    return x
In [3]:
# 根据资产预期目标风险贡献度来计算各资产的权重
def calcu_w(x):
    w0 = [0.2, 0.2, 0.2, 0.6] 
#     x_t = [0.25, 0.25, 0.25, 0.25] # 目标是让四个资产风险贡献度相等,即都为25%
    x_t = x 
    cons = ({'type': 'eq', 'fun': total_weight_constraint},
    {'type': 'ineq', 'fun': long_only_constraint})
    res= minimize(risk_budget_objective, w0, args=[V,x_t], method='SLSQP',constraints=cons, options={'disp': True})
    w_rb = np.asmatrix(res.x)
    return w_rb
In [4]:
# 将各资产风险贡献度绘制成柱状图
def plot_rc(w):
    rc = calculate_risk_contribution(w, V)
    rc = rc.tolist()
    rc = [i[0] for i in rc]
    rc = pd.DataFrame(rc,columns=['rick contribution'],index=[1,2,3,4])
    T.plot(rc, chart_type='column', title = 'Contribution to risk')
    
In [5]:
# 假设四个资产的风险贡献度相等
w_rb = calcu_w([0.25, 0.25, 0.25, 0.25])
print('各资产权重:', w_rb)
plot_rc(w_rb)
Optimization terminated successfully.    (Exit mode 0)
            Current function value: 3.925640895972104e-09
            Iterations: 6
            Function evaluations: 38
            Gradient evaluations: 6
各资产权重: [[ 0.19537778  0.21532757  0.16250521  0.42678944]]
In [6]:
# 假设风险贡献度依次为0.3,0.3,0.1,0.3
w = calcu_w([0.3, 0.3 ,0.1,0.3])
print('各资产权重:', w)
plot_rc(w)
Optimization terminated successfully.    (Exit mode 0)
            Current function value: 2.8381885095817227e-07
            Iterations: 8
            Function evaluations: 51
            Gradient evaluations: 8
各资产权重: [[ 0.2277006   0.25093779  0.08862556  0.43273605]]

社区干货与精选整理(持续更新中...)
BigQuant上是否有关于MPT投资组合的策略,比如。。。
(rk92yy) #4

这一行里应该return RC/sigma吧。我们要的是风险贡献占总风险的比重,而不是风险贡献的值。


(iQuant) #5
# 计算总风险
sigma = np.sqrt(calculate_portfolio_var(w,V))
# 边际风险贡献
MRC = V*w.T
# 风险贡献
RC = np.multiply(MRC,w.T)/sigma

sigma应该是组合总风险,np.multiply(MRC,w.T)/sigma 除了下总风险就是风险占比了吧,风险贡献也是以风险占比来衡量的。这样解释是不是好理解一些?


(chaoskey) #6

学习了.


(WoodSun) #7

是代码错了,上面的文字介绍公式是对的,MRC少除以sigma,RC多除了sigma,虽然结果正确但确实写错了。您的回复应该不对,返回的值是风险贡献而不是风险贡献占比。


(Quantman) #8

初始值w0的设置有什么讲究?


(Richard_Wang) #9

初值设置做变化时,会出现风险差异很大的情况。111