【Python量化】风险平价策略

文章目录

  • 一、风险平价策略
  • 二、风险平价组合的构建步骤
    • 第一步,选择底仓。
    • 第二步,计算资产对组合的风险贡献。
    • 第三步,优化组合风险贡献,计算资产权重。
  • 三、风险平价组合的Python实现
    • 3.1 数据概况
    • 3.2 构建风险平价组合

本文章首发于公众号:Python for Finance

链接:https://mp.weixin.qq.com/s/9FkCgVhygWDFWTBVhy-Spw

一、风险平价策略

磐安(Pan Agora)基金的首席投资官钱恩平(Edward Qian)博士提出了著名的风险平价(Risk Parity)策略。后来,这一模型被桥水(Bridge Water)基金运用于实际投资中并一度大获成功。

该策略提倡配置风险,而不是配置资产。传统模型希望可以控制整个投资组合的波动性,而风险平价控制的是相对风险,让各资产风险相对平衡。由于组合的风险达到了平衡,所以理论上可以抵御各类风险,也就是所谓的全天候(All Weather)策略。

全天候交易策略

全天候交易策略的理念是:无论在什么市场环境下,投资组合都可以获得较高的风险调整收益。从名字也能看得出来,不管天气是狂风暴雨,还是晴空万里,我自岿然不动,笑看风云。

风险平价投资组合原则是通过分配资金,使每一项资产对整个投资组合风险的 贡献相等来确定资产配置。从根本上说,这一概念反映了经典的 1/n 投资组合,即资 金在所有资产中平均分配。因此,风险均等投资组合有时被称为 ERC 投资组合。

二、风险平价组合的构建步骤

第一步,选择底仓。

钱恩平博士在《Risk Parity Fundamentals》(2016)中指出,资产背后的风险溢价分为三种,权益风险溢价、利率风险溢价和通胀风险溢价。从理论上看,选择相关性较低、资产属性差别较大、流动性较好的资产,有助于完善风险平价的配置图谱。

第二步,计算资产对组合的风险贡献。

定义资产对组合的边际风险贡献为组合波动率对权重的偏导数,资产对总风险的贡献为该资产权重与其边际风险贡献的乘积:
M R C i = ∂ σ p ∂ w i = c o v ( r i , r p ) σ p T R C i = w i ∂ σ p ∂ w i = w i c o v ( r i , r p ) σ p MRC_i=\frac{\partial\sigma_p}{\partial w_i}=\frac{cov(r_i,r_p)}{\sigma_p}\\TRC_i=w_i\frac{\partial\sigma_p}{\partial w_i}=w_i\frac{cov(r_i,r_p)}{\sigma_p} MRCi=wiσp=σpcov(ri,rp)TRCi=wiwiσp=wiσpcov(ri,rp)
其中, w i w_i wi表示资产权重, θ \theta θ表示资产的协方差矩阵, σ p = w θ w T \sigma_p=\sqrt{w\theta w^T} σp=wT 衡量组合风险。

第三步,优化组合风险贡献,计算资产权重。

对于风险平价组合,资产对总风险的贡献水平相等,即:
T R C i = T R C j TRC_i=TRC_j TRCi=TRCj
权重求解本质上是二次优化问题,求资产对组合风险贡献差值的最小值,本文采用 Python中的 minimize 函数求解:
m i n ∑ i = 1 n ∑ j = 1 n ( T R C i − T R C j ) 2 s . t . ∑ w i = 1 , w i ∈ [ 0 , 1 ] min\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}(TRC_i-TRC_j)^2\\ s.t.\sum w_i=1,w_i\in[0,1] mini=1nj=1n(TRCiTRCj)2s.t.wi=1,wi[0,1]

三、风险平价组合的Python实现

假设有一投资组合,含有5支股票:中国平安(000001)、格力电器(000651)、爱尔眼科(300015)、贵州茅台(600519)、长安汽车(000625),构建风险平价组合。

3.1 数据概况

在计算之前,首先需要获取到5支股票的历史股价数据,这里我们使用 AKShare包。它是一个免费、开源的 Python 财经数据接口包。AKShare返回的绝大部分的数据格式都是 pandas DataFrame 类型,非常便于用 pandas/ NumPy/ Matplotlib 进行数据分析和可视化。

获取历史股价数据后,我们计算其对数收益率,并获得方差协方差矩阵。

import pandas as pd
import numpy as np
import akshare as ak
from scipy.optimize import minimize

# 读入5支股票 2015-01-01 到 2021-12-31 日收盘价数据,并计算对数收益率
def get_ret(code):
    data = ak.stock_zh_a_hist(symbol=code, period="daily", start_date="20150101", end_date='20211231', adjust="")
    data.index = pd.to_datetime(data['日期'],format='%Y-%m-%d') #设置日期索引
    close = data['收盘'] #日收盘价
    close.name = code
    ret = np.log(close/close.shift(1)) #日收益率
    return ret

codes=['000001','000651','300015','600519','000625']
ret = pd.DataFrame()
for code in codes:
	ret_ = get_ret(code)
	ret = pd.concat([ret,ret_],axis=1)
ret = ret.dropna()

R_cov = ret.cov() #计算协方差
cov= np.array(R_cov)

3.2 构建风险平价组合

def risk_budget_objective(weights,cov):
    weights = np.array(weights) #weights为一维数组
    sigma = np.sqrt(np.dot(weights, np.dot(cov, weights))) #获取组合标准差   
    #sigma = np.sqrt(weights@cov@weights)
    MRC = np.dot(cov,weights)/sigma  #MRC = cov@weights/sigma
    #MRC = np.dot(weights,cov)/sigma
    TRC = weights * MRC
    delta_TRC = [sum((i - TRC)**2) for i in TRC]
    return sum(delta_TRC)

'''
#若将权重weights转化为二维数组的形式,则编制函数如下:
def risk_budget_objective(weights,cov):
    weights = np.matrix(weights) #weights为二维数组
    sigma = np.sqrt(np.dot(weights, np.dot(cov, weights.T))[0,0]) #获取组合标准差   
    #sigma = np.sqrt((weights@[email protected])[0,0])   
    MRC = np.dot(cov,weights.T).A1/sigma
    #MRC = np.dot(weights,cov).A1/sigma
    TRC = weights.A1 * MRC
    delta_TRC = [sum((i - TRC)**2) for i in TRC]
    return sum(delta_TRC)
'''

def total_weight_constraint(x):
    return np.sum(x)-1.0
     
x0 = np.ones(cov.shape[0]) / cov.shape[0]
bnds = tuple((0,None) for x in x0)
cons = ({'type': 'eq', 'fun': total_weight_constraint})
#cons = ({'type':'eq', 'fun': lambda x: sum(x) - 1})
options={'disp':False, 'maxiter':1000, 'ftol':1e-20} 

solution = minimize(risk_budget_objective, x0,args=(cov), bounds=bnds, constraints=cons, method='SLSQP', options=options)

# 求解出权重
final_weights = solution.x #权重
for i in range(len(final_weights)):
    print(f'{final_weights[i]:.1%}投资于{R_cov.columns[i]}')

求解结果为:

24.3%投资于000001
16.7%投资于000651
16.1%投资于300015
24.8%投资于600519
18.1%投资于000625

参考资料:https://thequantmba.wordpress.com/2016/12/14/risk-parityrisk-budgeting-portfolio-in-python/

你可能感兴趣的:(Python量化,python,开发语言)