【Python量化】风险平价策略

一、风险平价策略

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

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

「全天候交易策略」

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

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

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

「第一步,选择底仓。」

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

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

定义资产对组合的边际风险贡献为组合波动率对权重的偏导数,资产对总风险的贡献为该资产权重与其边际风险贡献的乘积:

其中,表示资产权重,表示资产的协方差矩阵,衡量组合风险。

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

对于风险平价组合,资产对总风险的贡献水平相等,即:

权重求解本质上是二次优化问题,求资产对组合风险贡献差值的最小值,本文采用 Python中的 minimize 函数求解:

三、「风险平价组合的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.1 构建风险平价组合

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)**2for 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@cov@weights.T)[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,Nonefor 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 for Finance):【Python量化】风险平价策略

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/45693.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!