200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 【基金量化研究系列】大类资产配置研究(六)——多资产风险平价策略

【基金量化研究系列】大类资产配置研究(六)——多资产风险平价策略

时间:2020-12-16 12:55:52

相关推荐

【基金量化研究系列】大类资产配置研究(六)——多资产风险平价策略

文章目录

1. 引言1.1 前文回顾与问题提出1.2 数据收集与标的资产选取1.3 基本假设2. 风险平价策略简介2.1 模型的建立2.2 模型求解3. 风险平价策略实现伪代码4. 基于python的模型实现4.1 python代码4.2 实证结果5. 结论5.1 策略表现5.2 可能存在的问题及潜在处理方法免责声明写在最后

1. 引言

1.1 前文回顾与问题提出

在之前的文章中,我们介绍了马科维茨模型在中国市场资产配置中的应用。(详情请见【基金量化研究系列】大类资产配置研究(四)——基于马科维茨模型的资产配置研究)。但是,由于马科维茨模型中存在的诸多问题,资产配置的效果却不尽如人意。

我们之前的实证研究已经提到过:波动率与未来的收益率呈现出显著的负相关关系,因此我们可以以某类资产的波动率作为先行指标:当资产波动率不断上升时,资产收益的下行风险显著增加,在这种情况下我们应该对该类资产进行减仓。我们很自然地想到一种配置思路:如果让所有的风险资产对投资组合的总风险的贡献均有相同的比例(即风险平价),那这样一种策略会不会既稳健又有较高的收益率呢?

在这篇文章中,就让我们来验证一下这样的观点吧!

1.2 数据收集与标的资产选取

本文以开源的Choice数据库作为本文的数据来源。关于Choice数据库的使用方法及说明请参考:Choice数据量化接口产品手册。

对于标的资产的选择,我们仍以“易方达沪深300ETF(510310)”与“国泰上证5年国债ETF(511010)”作为股票市场与债券市场的基准可投标的,并以“华安黄金易ETF(518880)”和“七日深圳国债逆回购R-007(131801)”作为商品和无风险资产的基准可投资标的。这些标的均可以在券商账户中进行交易。

1.3 基本假设

本文仍延续前文的基本假设,规定:

(1)市场中不允许融资做多与融券做空;

(2)建仓调仓过程中不允许借款、参与国债回购;

(3)每日仅在收盘时间以收盘价格进行交易;

(4)未特别规定,忽略调、建仓手续费。

2. 风险平价策略简介

2.1 模型的建立

所谓风险平价(Risk Parity),即将投资组合的总风险平均分散入各资产,使得每一类资产贡献的风险相等。因此,首先要解决的问题,就是如何去衡量各类资产所贡献的风险大小。

首先,组合资产的波动率满足:

σp=(ωTΣω)12\sigma_p = (\omega^T \Sigma \omega )^{ \frac{1}{2}} σp​=(ωTΣω)21​

其中:

·σp 表示组合资产的标准差;

· Σ 表示风险资产的协方差矩阵;

·ω表示风险资产的权重列向量。

定义第i类资产的风险贡献率(Risk Contribution)RCi:

RCi=1σpωi∂σp∂ωi,i=1,2,...,N\text{RC}_i = \frac{1}{\sigma_p} \omega_i \frac{\partial\sigma_p}{\partial\omega_i}, \ i = 1, 2, ..., N RCi​=σp​1​ωi​∂ωi​∂σp​​,i=1,2,...,N

其中:

∂σp∂ωi=∂(ωTΣω)12∂ωi=(ωTΣ)iωTΣω,i=1,2,...,N\frac{\partial\sigma_p}{\partial\omega_i} = \frac{\partial(\omega^T \Sigma \omega )^{ \frac{1}{2}}}{\partial\omega_i} = \frac{(\omega^T\Sigma)_i }{\sqrt{\omega^T \Sigma \omega}} , \ i = 1, 2, ..., N ∂ωi​∂σp​​=∂ωi​∂(ωTΣω)21​​=ωTΣω​(ωTΣ)i​​,i=1,2,...,N

因此, RCi 可以变型为:

RCi=ωi(ωTΣ)iωTΣω,i=1,2,...,N\text{RC}_i = \frac{\omega_i(\omega^T\Sigma)_i }{\omega^T \Sigma \omega}, \ i = 1, 2, ..., N RCi​=ωTΣωωi​(ωTΣ)i​​,i=1,2,...,N

上式的分子项表示由第i类资产贡献的方差,分母则表示组合资产的总方差。

若想让每一类风险资产对组合的风险贡献率相等,对于任意的i,RCi 应满足:

RCi=ωi(ωTΣ)iωTΣω=1N,i=1,2,...,N\text{RC}_i = \frac{\omega_i(\omega^T\Sigma)_i }{\omega^T \Sigma \omega}= \frac{1}{N}, \ i = 1, 2, ..., N RCi​=ωTΣωωi​(ωTΣ)i​​=N1​,i=1,2,...,N

或者可以等价转换为一个N元非线性函数的零点问题:

f(ω)=∑i=1N(RCi−1N)2=∑i=1N(ωi−ωTΣωN(ωTΣ)i)2=0f(\omega) = \sum_{i=1}^{N}(\text{RC}_i - \frac{1}{N})^2 \\ = \sum_{i = 1}^{N} ( \omega_i - \frac{\omega^T \Sigma \omega}{N(\omega^T\Sigma)_i } )^2 = 0 f(ω)=i=1∑N​(RCi​−N1​)2=i=1∑N​(ωi​−N(ωTΣ)i​ωTΣω​)2=0

然而,除了风险平价的限制以外,我们还对各资产的权重有限制:我们要求各权重必须非负(不可做空),且权重的和必须为1(全部投资),而这些额外的限制条件很可能导致上述函数无实数解。一种退而求其次的方法则是将上述方程转化为下列约束优化问题:

minf(ω)=∑i=1N(ωi−ωTΣωN(ωTΣ)i)2\text{min} \ f(\omega) = \sum_{i = 1}^{N} ( \omega_i - \frac{\omega^T \Sigma \omega}{N(\omega^T\Sigma)_i } )^2 minf(ω)=i=1∑N​(ωi​−N(ωTΣ)i​ωTΣω​)2

s.t.

ωT1−1=0ωi≥0,i=1,...,N\omega^T\bold{1} - 1 = 0 \\ \omega_i ≥ 0,i= 1, ..., N ωT1−1=0ωi​≥0,i=1,...,N

也可以将上述优化问题的目标函数改写成矩阵形式:

f(ω)=[ω−ωTΣωNv]T[ω−ωTΣωNv]f(\omega) = [ \omega - \frac{\omega^T \Sigma \omega}{N}v ]^T [ \omega - \frac{\omega^T \Sigma \omega}{N}v ] f(ω)=[ω−NωTΣω​v]T[ω−NωTΣω​v]

其中,v为N阶列向量:

v=(vi)N×1=[1(ωTΣ)i]N×1v = (v_i)_{N\times1}= [\frac{1}{(\omega^T\Sigma)_i }] _{N\times1} v=(vi​)N×1​=[(ωTΣ)i​1​]N×1​

因此,对于风险平价策略,投资于各风险资产的权重修向量ω即为下列约束优化问题的解:

minf(ω)=[ω−ωTΣωNv]T[ω−ωTΣωNv]\text{min} f(\omega) = [ \omega - \frac{\omega^T \Sigma \omega}{N}v ]^T [ \omega - \frac{\omega^T \Sigma \omega}{N}v ] minf(ω)=[ω−NωTΣω​v]T[ω−NωTΣω​v]

s.t.

ωT1−1=0ω≥0\omega^T\bold{1} - 1 = 0 \\ \omega ≥ \bold0 \\ ωT1−1=0ω≥0

2.2 模型求解

由于上述问题仍然是有线性限制条件的优化问题,我们仍可延续马科维茨模型中的求解方法,使用Python的Scipy包中的minimize函数进行上述优化问题的求解。同样地,对于R语言使用者,可以使用alabama包中的constrOptim.nl函数进行求解。

3. 风险平价策略实现伪代码

风险平价策略得的伪代码如下:

Step 0:始化参数。规定调仓频率(本文以T= 30 即30个交易日作为调仓周期进行说明)。规定 t = 0,进入Step 1;

Step 1:根据前一周期的日收盘价格,计算该周期内除无风险资产以外的各类资产日收益率ri,t与日波动率σi,t,计算各类资产的风险平价权重wi,t;

Step 2:以当日收盘价格将各类资产比例调整至目标权重;

Step 3: 令t=t+ 1,重复Step 1直至回测结束。

4. 基于python的模型实现

4.1 python代码

由于风险平价策略在权重的优化求解方法上和形式上与马科维茨模型如出一辙,因此本文在马科维茨模块基础上进行了改进,只需要对模块函数内的目标函数进行修改即可。(请参考【基金量化研究系列】大类资产配置研究(四)——基于马科维茨模型的资产配置研究的4.1部分)。在运行时,可将下列代码块保存为python文件“Mean_Variance.py”。

# -*- coding: utf-8 -*-# author: Mikey_Sun time: 5/19/# all copyright belongs to the author. NO COPY ALLOWED.import mathfrom scipy.optimize import minimizeimport numpy as npimport pandas as pd########################## Module 1 MV框架模块 ##########################def M_V(R, rf, Sigma, output_type = 'Dict', print_out = False):''':param R: list格式,输入各收益序列:param rf: num格式或list格式,输入无风险利率:param Sigma: two-d list格式,输入各收益序列协方差矩阵:param output_type: Bool类型,True为打印结果,Flase为不打印结果:param : num格式或list格式:return: dataframe'''# Step 1: 初始化收入变量格式N = len(R) # 获取资产类别数R = np.array(R).reshape(N) # 格式化收益率序列rf = np.array(rf) # 格式化无风险利率Sigma = np.array(Sigma).reshape(N, N) # 格式化协方差矩阵# Step 2: 将无风险利率嵌入到收益率序列与协方差矩阵中(增广阵)R = np.r_[R, rf] # 增广收益率序列Sigma = np.c_[Sigma, np.zeros(N).reshape(N, 1)] # 增广协方差矩阵列Sigma = np.r_[Sigma, np.zeros(N+1).reshape(1, N+1)] # 增广协方差矩阵行# Step 3: 利用minimize函数进行模型求解:eps = 1e-10 # 找到一个非常接近0的值作为误差限w0 = np.ones(N+1) / (N+1) # 各类别资产权重参数初始化#fun = lambda w: 0.5 * math.log(np.dot(np.dot(w, Sigma), np.transpose(w))) - math.log(# np.dot(w, R - rf)) # 约束函数:最大化对数sharpe-ratiofun = lambda w: - np.dot(w, R - rf) / np.dot(np.dot(w, Sigma), np.transpose(w))**0.5 # 约束函数:最大化对数sharpe-ratiocons = ({'type': 'eq', 'fun': lambda w: np.sum(w) - 1}, # 限制条件一:全部投资{'type': 'ineq', 'fun': lambda w: w - eps}, # 限制条件二:不可做空)res = minimize(fun, w0, method='SLSQP', constraints=cons)# Step 4: 计算各指标w_op = res.x # 获取权重数据r_op = np.dot(res.x, R) # 计算收益率sigma_op = np.dot(np.dot(w_op, Sigma), np.transpose(w_op)) # 计算组合波动率SR = (r_op - rf) / sigma_op # 计算夏普比率# Step 5: 是否打印测试if print_out:print('''最优权重配比:{0:}最优收益率:{1:.2f}最优风险:{2:.2f}最优夏普比率:{3:.2f} '''.format(w_op, r_op, sigma_op, SR))# Step 6: 打印模块if str(output_type).upper() == 'DATAFRAME':return pd.DataFrame({'Weights':[w_op], 'Return':r_op, 'Sigma':sigma_op, 'SR':SR})elif str(output_type).upper() == 'DICT':return {'Weights':w_op, 'Return':r_op, 'Sigma':sigma_op, 'SR':SR}elif str(output_type).upper() == 'LIST':return [w_op, r_op, sigma_op, SR]else:return {'Weights':w_op, 'Return':r_op, 'Sigma':sigma_op, 'SR':SR}########################## Module 2 风险平价框架模块 ##########################def R_P(R, rf, Sigma, output_type = 'Dict', print_out = False):''':param R: list格式,输入各收益序列:param rf: num格式或list格式,输入无风险利率:param Sigma: two-d list格式,输入各收益序列协方差矩阵:param output_type: Bool类型,True为打印结果,Flase为不打印结果:param : num格式或list格式:return: dataframe'''# Step 1: 初始化收入变量格式N = len(R) # 获取资产类别数R = np.array(R).reshape(N) # 格式化收益率序列rf = np.array(rf) # 格式化无风险利率Sigma = np.array(Sigma).reshape(N, N) # 格式化协方差矩阵# Step 2: 利用minimize函数进行模型求解:eps = 1e-10 # 找到一个非常接近0的值作为误差限w0 = np.ones(N) / N # 各类别资产权重参数初始化fun = lambda w: np.dot(w - np.dot(np.dot(w, Sigma), np.transpose(w))/N / np.dot(w, Sigma),np.transpose(w - np.dot(np.dot(w, Sigma), np.transpose(w))/N / np.dot(w, Sigma) ))cons = ({'type': 'eq', 'fun': lambda w: np.sum(w) - 1}, # 限制条件一:全部投资{'type': 'ineq', 'fun': lambda w: w - eps}, # 限制条件二:不可做空)res = minimize(fun, w0, method='SLSQP', constraints=cons)# Step 4: 计算各指标w_op = res.x # 获取权重数据r_op = np.dot(res.x, R) # 计算收益率sigma_op = np.dot(np.dot(w_op, Sigma), np.transpose(w_op)) # 计算组合波动率SR = (r_op - rf) / sigma_op # 计算夏普比率# Step 5: 是否打印测试if print_out:print('''最优权重配比:{0:}最优收益率:{1:.2f}最优风险:{2:.2f}最优夏普比率:{3:.2f} '''.format(w_op, r_op, sigma_op, SR))# Step 6: 打印模块if str(output_type).upper() == 'DATAFRAME':return pd.DataFrame({'Weights':[w_op], 'Return':r_op, 'Sigma':sigma_op, 'SR':SR})elif str(output_type).upper() == 'DICT':return {'Weights':w_op, 'Return':r_op, 'Sigma':sigma_op, 'SR':SR}elif str(output_type).upper() == 'LIST':return [w_op, r_op, sigma_op, SR]else:return {'Weights':w_op, 'Return':r_op, 'Sigma':sigma_op, 'SR':SR}

下面是主函数模块代码块。其中引用的“Risk_Factor_Calculation”模块来自于本人自己开发的量化策略回测框架中的一部分,请参考:【基于python的量化策略回测框架搭建】策略表现衡量指标模块。

# -*- coding: utf-8 -*-# author: Mikey_Sun time: 5/26/# all copyright belongs to the author. NO COPY ALLOWED.import Risk_Factor_Calculation as RFimport Mean_Variance as MVfrom EmQuantAPI import * #使用chioce数据库。详细使用说明请查阅百度import numpy as npimport pandas as pdimport matplotlib.pyplot as plt################################### Module 1: 下载数据,并存储到本地 ###################################def download_data_from_choice():loginresult = c.start()codes = "510310.SH,511010.SH,518880.SH,131801.SZ" # 所需数据的代码。510310为沪深300ETF,511010为五年国债ETFindicators = "open,high,low,close" # 需要下载的数据指标startdate = "0729" # 回测起始时间,可自行修改enddate = "" # 回测结束时间,可自行修改data = c.csd(codes=codes, indicators=indicators, startdate=startdate, enddate=enddate,options=("Ispandas,1")) # 导入数据,以pd.DataFrame类型格式存储path = '你的数据储存地址' # 将数据保存到你的本地地址(需自行修改)data.to_excel(path, index=True, header=True)download_data_from_choice()path = '你的数据储存地址' # 运行时请修改为你的数据保存地址data = pd.read_excel(path) # 读取数据data.set_index(data["DATES"], inplace=True) #设置数据索引为交易日tickers = ["510310.SH","511010.SH","518880.SH",'131801.SZ']HS300ETF = pd.DataFrame(data[data["CODES"] == '510310.SH']["CLOSE"].astype(float)) #沪深300ETF专属数据结构。仅保留收盘价格GZ5yETF = pd.DataFrame(data[data["CODES"] == '511010.SH']["CLOSE"].astype(float)) #国债ETF专属数据结构。仅保留收盘价格GoldETF = pd.DataFrame(data[data["CODES"] == '518880.SH']["CLOSE"].astype(float)) #黄金ETF专属数据结构。仅保留收盘价格R_001 = pd.DataFrame(data[data["CODES"] == '131801.SZ']["CLOSE"].astype(float)) #黄金ETF专属数据结构。仅保留收盘价格td_dates = HS300ETF.index #记录交易日信息,方便以后进行查找n = len(td_dates)######################### Module2: 计算收益率 #########################pd.set_option('mode.chained_assignment', None)# 创建收益率序列HS300ETF['RETURN'] = 0 #创建收益率序列GZ5yETF['RETURN'] = 0 #创建收益率序列GoldETF['RETURN'] = 0 #创建收益率序列R_001['RETURN'] = 0HS300ETF['RETURN'].astype(float)#设定格式为浮点GZ5yETF['RETURN'].astype(float)#设定格式为浮点GoldETF['RETURN'].astype(float)#设定格式为浮点R_001['RETURN'].astype(float)#设定格式为浮点# 计算收益率HS300ETF["RETURN"][td_dates[1:]] = np.array(HS300ETF["CLOSE"][td_dates[1:]]) / np.array(HS300ETF["CLOSE"][td_dates[:-1]]) - 1 #计算HS300ETF日收益率GZ5yETF["RETURN"][td_dates[1:]] = np.array(GZ5yETF["CLOSE"][td_dates[1:]]) / np.array(GZ5yETF["CLOSE"][td_dates[:-1]]) - 1 #计算GZ5yETF日收益率GoldETF["RETURN"][td_dates[1:]] = np.array(GoldETF["CLOSE"][td_dates[1:]]) / np.array(GoldETF["CLOSE"][td_dates[:-1]]) - 1 #计算GZ5yETF日收益率R_001["RETURN"][td_dates[1:]] = np.array(R_001["CLOSE"][td_dates[1:]])/100/365# 将收益率序列单独存储至returnsreturns = pd.DataFrame({'510310.SH':HS300ETF["RETURN"], '511010.SH':GZ5yETF["RETURN"], '518880.SH':GoldETF["RETURN"], '131801.SZ':R_001["RETURN"]},index= td_dates)################################### Module 3: 计算策略权重 #######################################def weights_calculate_RP(T):weights_strategy_RP = []for t in range(T, n, T):R = []for i in range(3):R.append(np.mean(returns[tickers[i]][td_dates[t - T:t]]) * T)rf = np.mean(returns['131801.SZ'][td_dates[t - T:t]]) * TSigma = np.cov(returns[tickers[0:3]][t - T:t] * T, rowvar=False)outcome = MV.R_P(R=R, rf=rf, Sigma=Sigma)for i in range(T):weights_strategy_RP.append(outcome['Weights'])return weights_strategy_RPdef weights_calculate_MV(T):weights_strategy_MV = []for t in range(T, n, T):R = []for i in range(3):R.append(np.mean(returns[tickers[i]][td_dates[t - T:t]]) * T)rf = np.mean(returns['131801.SZ'][td_dates[t - T:t]]) * TSigma = np.cov(returns[tickers[0:3]][t - T:t] * T, rowvar=False)outcome = MV.M_V(R=R, rf=rf, Sigma=Sigma)for i in range(T):weights_strategy_MV.append(outcome['Weights'])return weights_strategy_MV################################### Module 4: 各策略净值与收益率计算 ###################################nv_HS300ETF = [1] #记录全仓股票策略净值nv_GZ5yETF = [1] #记录全仓债券策略净值nv_GoldETF = [1]nv_Cash = [1]r_HS300ETF = []r_GZ5yETF = []r_GoldETF = []r_Cash = []nv_strategy_MV = [1]r_strategy_MV = []nv_strategy_RP = [1]r_strategy_RP = []T = 30 # 设置调参周期长度weights_strategy_RP = weights_calculate_RP(T) # 计算风险平价策略权重序列weights_strategy_MV = weights_calculate_MV(T) # 计算马科维茨模型策略权重序列for i in range(T, n):nv_HS300ETF.append( nv_HS300ETF[i-T] *(1 + returns['510310.SH'][td_dates[i]]))nv_GZ5yETF.append( nv_GZ5yETF[i-T] *(1 + returns['511010.SH'][td_dates[i]]))nv_GoldETF.append( nv_GoldETF[i-T] *(1 + returns['518880.SH'][td_dates[i]]))nv_Cash.append( nv_Cash[i-T] *(1 + returns['131801.SZ'][td_dates[i]]))r_HS300ETF.append(returns['510310.SH'][td_dates[i]])r_GZ5yETF.append(returns['511010.SH'][td_dates[i]])r_GoldETF.append(returns['518880.SH'][td_dates[i]])r_Cash.append(returns['131801.SZ'][td_dates[i]])r_strategy_MV.append(weights_strategy_MV[i - T][0] * returns[tickers[0]][td_dates[i]] +weights_strategy_MV[i - T][1] * returns[tickers[1]][td_dates[i]] +weights_strategy_MV[i - T][2] * returns[tickers[2]][td_dates[i]] +weights_strategy_MV[i - T][3] * returns[tickers[3]][td_dates[i]])r_strategy_RP.append(weights_strategy_RP[i - T][0] * returns[tickers[0]][td_dates[i]] +weights_strategy_RP[i - T][1] * returns[tickers[1]][td_dates[i]] +weights_strategy_RP[i - T][2] * returns[tickers[2]][td_dates[i]])nv_strategy_MV.append(nv_strategy_MV[i-T] * (1 + r_strategy_MV[i-T]))nv_strategy_RP.append(nv_strategy_RP[i-T] * (1 + r_strategy_RP[i-T]))################################################### Module 5: 汇总各策略净值信息,并计算其风险及收益情况 ###################################################r_series = [r_HS300ETF, r_GZ5yETF, r_GoldETF, r_Cash, r_strategy_MV , r_strategy_RP]nv_series = [nv_HS300ETF, nv_GZ5yETF, nv_GoldETF, nv_Cash, nv_strategy_MV ,nv_strategy_RP]Period = 'D'Indicators = 'ALL'alpha = 0.05output_type = 'pd.DataFrame'strategy_names = ['沪深300', '债券ETF', '黄金ETF', '国债逆回购', '均值方差策略', '风险平价策略']# 进入风险值计算回测系统框架(该框架为自主创建,需要读取该文件)Risks = RF.Risk_Indicators(r_series, nv_series, Period = Period, Indicators= Indicators, alpha=alpha, output_type=output_type)Risks = pd.DataFrame(Risks.values.tolist(), index = strategy_names, columns = Risks.columns)#打印风险值情况print(Risks[Risks.columns[:4]])print(Risks[Risks.columns[4:]])################################## Module 6: 绘制各策略净值走势图 ##################################plt.plot(nv_HS300ETF, label = "nv_HS300ETF", color = "black")plt.plot(nv_GZ5yETF, label = "nv_GZ5yETF", color = "red")plt.plot(nv_GoldETF, label = "nv_GoldETF", color = "blue")plt.plot(nv_Cash, label="nv_Cash", color="purple")plt.plot(nv_strategy_MV, label="nv_strategy_MV", color="green")plt.plot(nv_strategy_RP, label="nv_strategy_RP", color="grey")plt.show()

:为节约时间,本文代码直接在马科维茨代码的基础上打了补丁,代码内容冗长,有待进一步优化,在此仅做实例展示。

4.2 实证结果

调仓周期为30个交易日时(设置T= 30),策略的运行结果如下:

ReturnSigma R/S MDD沪深300 0.121751 0.245480 0.495972 1.046858债券ETF 0.037404 0.028362 1.318794 0.056963黄金ETF 0.058866 0.126968 0.463625 0.216147国债逆回购 0.018584 0.000557 33.345747 0.000000均值方差策略 0.061792 0.106153 0.582107 0.338244风险平价策略 0.066728 0.060375 1.105237 0.102871MDD_R MDD_P VaRCVaR沪深300 0.456784 155.0 0.099732 0.099732债券ETF 0.049023 39.0 0.016768 0.016768黄金ETF 0.213716 461.0 0.046573 0.046573国债逆回购 0.000000 0.0 0.000000 0.000000均值方差策略 0.258140 17.0 0.065919 0.065919风险平价策略 0.084008 47.0 0.051322 0.051322Process finished with exit code 0

*数据来源:Choice数据库

图1 /09/09 - /05/15 期间各策略净值走势图(以9月8日为基日,定义净值为1。黑线为全股策略,红线为全债策略,蓝线为纯黄金策略,紫线为纯现金策略,绿线为马科维茨模型策略,灰线为风险平价策略)

调仓周期调整为60个交易日时(设置T= 60),策略的运行结果如下:

ReturnSigma R/S MDD沪深300 0.122891 0.246382 0.498783 1.041314债券ETF 0.038749 0.028488 1.360169 0.057206黄金ETF 0.064613 0.126399 0.511182 0.210307国债逆回购 0.018449 0.000546 33.792535 0.000000均值方差策略 0.051419 0.064649 0.795346 0.111822风险平价策略 0.107824 0.064947 1.660180 0.090008MDD_R MDD_P VaRCVaR沪深300 0.456784 155.0 0.099732 0.099732债券ETF 0.049023 39.0 0.016768 0.016768黄金ETF 0.203894 339.0 0.046573 0.046573国债逆回购 0.000000 0.0 0.000000 0.000000均值方差策略 0.088425 12.0 0.034050 0.034050风险平价策略 0.068778 53.0 0.023362 0.023362Process finished with exit code 0

*数据来源:Choice数据库

图2 /10/30 - /5/15 期间各策略净值走势图(以10月29日为基日,定义净值为1。黑线为全股策略,红线为全债策略,蓝线为纯黄金策略,紫线为纯现金策略,绿线为马科维茨模型策略,灰线为风险平价策略)

5. 结论

5.1 策略表现

策略表现上来看,调仓频率不论是每30个交易日一次还是每60个交易日一次,风险平价策略都相比于马科维茨策略拥有较低的风险水平较高的夏普比率。从尾部风险角度来看,风险平价策略在相同置信度下的在险价值较低,而最大回撤比率也显著低于马科维茨策略。不过值得注意的是,风险平价策略的最大回撤周期远大于马科维茨策略,这意味着该策略将空间上的部分损失转化为时间上的损失,这可能要求组合管理人对连续的小阴跌要有较高的承受度。

还有一点值得注意的是,当调仓周期从30个交易日变更为60个交易日的时候,后者的收益率和夏普比率均明显高于前者,这可能意味着策略的表现对调仓周期较为敏感。在本文进一步的实证过程中,发现策略的表现随调仓频率的增加而呈现出明显的倒U型,这说明选择合适的调仓周期也是影响风险平价策略表现的重要因素

5.2 可能存在的问题及潜在处理方法

同时,我们也应该看到,调仓周期也是影响策略表现的一个重要因素。根据实证结果,调仓周期过短或过长,策略的表现均不理想。出现这一问题的原因可能有:

(1)估计量的有偏性。模型需要对各收益序列协方差矩阵进行估计,而样本长度会影响估计量的准确性。

(2)调仓信号的滞后性。当波动率在短期内发生重大变化时,调仓频率的滞后性会导致在短时间内仓位发生重大偏离。

对于第一种可能存在的问题,我们已经在马科维茨模型中给出了几种可能的解决方法,在此不做赘述。对于第二个问题,一种处理方法就是对调仓方式从周期性静态调仓变更为动态再平衡(Dynamic Rebalance)。例如,每日或每周监控各风险资产的风险贡献率,若某资产风险贡献率超越某一阈值(例如超越基准比率的10%)后则立即进行再平衡调仓。当然,也可以借鉴机器学习的办法,将调仓周期T作为策略的调整参数(Tuning Parameter),通过设置目标函数(如夏普比率)以寻找最优的调仓周期。

此外,本文规定调仓周期与模型参数估计的样本窗口期长度相等(即以过去T个交易日的历史数据来计算未来T个交易日各资产所占的比例)。这一规定是经验性的,有兴趣的读者也可以在这一点上做进一步的研究。

免责声明

免责声明:本文内容及观点仅供参考,不构成任何投资建议,投资者据此操作,风险自担。一切有关本文涉及的数据均来自于第三方数据机构,使用时请查阅第三方数据平台的使用说明,本文不负有数据准确性的直接负责。本文所述策略表现均基于历史数据,不代表对未来的预期。投资有风险,入市需谨慎。

写在最后

若想查阅本系列全部文章,请参见目录页:系列文章目录索引。

欢迎感兴趣的小伙伴来跟作者一起挑刺儿~ 包括但不限于语言上的、排版上的和内容上的不足和疏漏~ 一起进步呀!

有任何问题,欢迎在本文下方留言,或者将问题发送至勘误邮箱: mikeysun_bugfix@

谢谢大家!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。