点到飞
研究目的:
本文参考天风证券研报《基于半衰主成分风险平价模型的全球资产配置策略研究》和《引入衰减加权和趋势跟踪的主成分风险平价模型研究》,对研报中的结果进行分析,研究了主成分风险平价模型在全球大类资产配置领域中的应用,通过比较基于风险因子的风险平价模型和基于资产本身的风险平价模型,实证主成分风险平价模型的优点。
研究内容:
资产配置的目的在于实现高分散低风险的投资组合,以期获得稳定的财富增值。当下资产配置实践中采用较多的是风险平价模型。传统的风险平价模型会对所有资产分配投资权重,忽略了资产之间的相关性。主成分风险平价模型对原资产进行线性变换形成互不相关的主成分组合,再通过传统风险平价模型确定主成分组合的投资权重,最终反变换为原资产的投资权重,从而较好的解决了传统风险平价模型处理高相关资产配置问题的弱点。
本篇报告关注了如下几方面问题:
(1)通过主成分分析法,将资产组合变换为主成分因子组合,在传统风险平价模型求解方法的基础上构建基于主成分风险因子的风险平价模型求解方法。
(2)引入资产预期风险估计和预期走势估计,演示了如何对资产配置模型做出进一步改进。
研究结论:
(1)本文资产配置的资产池包括全球主要股票市场、国内债券、国内外商品等。在2010.1-2018.10期间,主成分风险平价模型的年化收益为5.43%,高于传统风险平价模型的4.63%。最大回撤方面,主成分风险平价模型为2.02%,也要低于传统风险平价模型的3.37%。
(2)主成分风险平价模型旨在确保主成分风险因子上的等比例风险贡献。由于投资组合中有一半的资产都是权益类资产,因此传统风险平价模型中权益类资产提供了50%的风险贡献,而计算结果表明,主成分风险平价模型中权益类资产只提供了远小于50%的风险贡献,从而使得主成分风险平价模型组合的风险要低于传统风险平价模型组合。这体现了PCRP模型在高相关资产组合配置中的优势。
(3)在战术资产配置层面,将一个简单的风险预估和走势预估模型引入资产配置模型中,使得波动率与回撤指标得到改善,加强了模型的风险控制能力。
研究耗时:
(1)数据准备部分:约3分钟 (2)主成分风险平价模型介绍部分:约2分钟 (3)主成分风险平价模型应用实证部分:约30分钟 (4)预期风险估计和预期走势估计部分:约35分钟
编者按: 研报及本文中的复现过程没有考虑手续费,部分资产指数可能没有相应基金产品,另外也没有考虑资产的申购赎回周期。研报中的通过走势预估模型引入资产的月度择时,但是相应收益率的提升可能会无法覆盖手续费成本。总之本文主要目的在于实证一种新的风险平价理论:即基于风险因子的配置,而非基于资产本身的配置。主成分风险平价模型若要真正应用于投资实践,在资产挑选和战术资产配置层面还需进一步斟酌优化。
相关研报和数据下载地址:链接: https://pan.baidu.com/s/1CssR53H41Kki2K6J7ZSNJw 提取码: qy3h
引言¶
资产配置的目的在于实现高分散低风险的投资组合,以期获得稳定的财富增值。当下资产配置实践中采用较多的是风险平价模型。传统的风险平价模型会对所有资产分配投资权重,忽略了资产之间的相关性。主成分风险平价模型对原资产进行线性变换形成互不相关的主成分组合,再通过传统风险平价模型确定主成分组合的投资权重,最终反变换为原资产的投资权重,从而较好的解决了传统风险平价模型处理高相关资产配置问题的弱点。本文参考天风证券研报《基于半衰主成分风险平价模型的全球资产配置策略研究》和《引入衰减加权和趋势跟踪的主成分风险平价模型研究》(作者:吴先兴)对研报中的结果进行分析,实证了主成分风险平价模型在配置高相关资产方面的优势。
总耗时70分钟左右
1 数据准备¶
该部分耗时 3分钟
本文资产配置的资产池包括:沪深300、中证500、恒生指数、标普500、纳斯达克指数、富时100、法国CAC50、德国DAX、日经225、上证5年国债、上证企债、中信沪金商品指数、中信沪铜商品指数、中信玉米商品指数、中信郑棉商品指数、中信白糖商品指数、南华商品指数、布伦特原油共18类资产,涵盖全球主要股票市场、国内债券、国内外商品等。选取2009年1月至2018年9月期间上述指数的收盘价数据,并统一以A股市场交易日为准。为方便数据处理,将上述资产的收盘价数据保存为'全球资产指数行情序列.xlsx',并放在研究环境根目录下。
'全球资产指数行情序列.xlsx'可从压缩包中获取。
import numpy as np
import pandas as pd
from scipy.optimize import minimize
import datetime as dt
from six import StringIO
from dateutil.parser import parse
import cPickle as pickle
import seaborn as sns
import matplotlib as mpl
读取全球资产指数行情序列,并查看一下。
body=read_file('全球资产指数行情序列.xlsx')
prices=pd.read_excel(StringIO(body))
# print prices.columns
columns =[u'沪深300',u'中证500',u'恒生指数',u'标普500',u'纳斯达克指数',u'富时100',u'法国CAC40',u'德国DAX',u'日经225',\
u'上证5年国债(全)',u'上证企债',u'中信沪金商品指数',u'中信沪铜商品指数',u'中信玉米商品指数',\
u'中信郑棉商品指数', u'中信白糖商品指数',u'南华商品指数',u'布伦特原油']
prices.set_index(u'时间',inplace=True)
prices = prices[columns]['2008-12-31':]
prices.head().append(prices.tail())
绘制全球各类资产指数的净值走势图
通过mpl.rcParams定义绘图中的字体和负号,否则可能出现中文乱码。
mpl.rcParams['font.family']='serif'
mpl.rcParams['axes.unicode_minus']=False # 处理负号
(prices/prices.iloc[0]).plot(figsize=(15,8),grid='on')
pct_daily = prices.pct_change()
计算各类资产的相关矩阵,并以热点图形式展示。热点图表明沪深300与中证500的相关性极高,标普500和纳斯达克指数的相关性极高,富时100、法国CAC40和德国DAX的相关性极高。可见投资组合中上述三组资产可分别视作一组资产。
fig = plt.figure(figsize= (15,10))
ax = fig.add_subplot(111)
ax = sns.heatmap(pct_daily.corr(),annot=True,annot_kws={'size':9,'weight':'bold'})
风险再平衡调仓时间为每季度末,回测区间为2010年1月1日至2018年9月30日,取出调仓节点日期及回测期间交易日。
#获取指定周期的日期列表 'W、M、Q'
def get_period_date(peroid,start_date, end_date):
#设定转换周期period_type 转换为周是'W',月'M',季度线'Q',五分钟'5min',12天'12D'
stock_data = get_price('000001.XSHE',start_date,end_date,'daily',fields=['close'])
#记录每个周期中最后一个交易日
stock_data['date']=stock_data.index
#进行转换,周线的每个变量都等于那一周中最后一个交易日的变量值
period_stock_data=stock_data.resample(peroid,how='last')
date=period_stock_data.index
pydate_array = date.to_pydatetime()
date_only_array = np.vectorize(lambda s: s.strftime('%Y-%m-%d'))(pydate_array )
date_only_series = pd.Series(date_only_array)
start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
start_date=start_date-datetime.timedelta(days=1)
start_date = start_date.strftime("%Y-%m-%d")
date_list=date_only_series.values.tolist()
date_list.insert(0,start_date)
return date_list
def get_near_tradingday(date):
return (get_price('000001.XSHG',end_date=date,count=1).index[0])
date_list = (get_period_date('Q','2010-01-01', '2018-10-01'))
# type(date_list[0])
tradingday_list_tot = pct_daily.index.tolist()
tradingday_list = [date for date in pct_daily.index.tolist() if ((date)>=get_near_tradingday(date_list[0]) \
and (date)<=get_near_tradingday(date_list[-1]))]
np.array(date_list)
# tradingday_list
2 主成分风险平价模型¶
该部分耗时 2分钟
主成分风险平价模型本质上是对资产组合的主成分风险因子进行风险平价配置,因此先对传统风险平价模型做个简单介绍。 主成分分析是一种基于降维思想把多个资产利用数学变换转化为少数几个主成分(即综合变量)的多元统计分析方法,这些主成分能够反映原始资产的大部分信息,更具有现实意义,通常表现为原始资产的线性组合,为使得这些主成分所包含的信息互不重叠,要求各主成分之间互不相关。本报告模型的基本思路是运用主成分分析对投资组合中的标的资产进行旋转,提取所有不相关的资产进行风险平价模型分析,最后反推确定原资产的投资权重。
get_smart_weight函数中参数cov_adjusted代表是否对协方差矩阵的估计做出修正,从而对预估风险做出修正,本文的后续将对此进行讨论。
get_smart_weight函数中的的fun1用来求解传统风险平价模型,fun2用来求解主成分风险平价模型。
a为资产收益率协方差矩阵的特征值,b为对应的特征向量。
def get_smart_weight(pct, method='risk parity', cov_adjusted=False, wts_adjusted=False):
if cov_adjusted == False:
#协方差矩阵
cov_mat = pct.cov()
else:
#调整后的半衰协方差矩阵
cov_mat = pct.iloc[:len(pct)/4].cov()*(1/10.) + pct.iloc[len(pct)/4+1:len(pct)/2].cov()*(2/10.) +\
pct.iloc[len(pct)/2+1:len(pct)/4*3].cov()*(3/10.) + pct.iloc[len(pct)/4*3+1:].cov()*(4/10.)
if not isinstance(cov_mat, pd.DataFrame):
raise ValueError('cov_mat should be pandas DataFrame!')
omega = np.matrix(cov_mat.values) # 协方差矩阵
a, b = np.linalg.eig(np.array(cov_mat)) #a为特征值,b为特征向量
a = matrix(a)
b = matrix(b)
# 定义目标函数
def fun1(x):
tmp = (omega * np.matrix(x).T).A1
risk = x * tmp/ np.sqrt(np.matrix(x) * omega * np.matrix(x).T).A1[0]
delta_risk = [sum((i - risk)**2) for i in risk]
return sum(delta_risk)
def fun2(x):
tmp = (b**(-1) * omega * np.matrix(x).T).A1
risk = (b**(-1)*np.matrix(x).T).A1 * tmp/ np.sqrt(np.matrix(x) * omega * np.matrix(x).T).A1[0]
delta_risk = [sum((i - risk)**2) for i in risk]
return sum(delta_risk)
# 初始值 + 约束条件
x0 = np.ones(omega.shape[0]) / omega.shape[0]
bnds = tuple((0,None) for x in x0)
cons = ({'type':'eq', 'fun': lambda x: sum(x) - 1})
options={'disp':False, 'maxiter':1000, 'ftol':1e-20}
if method == 'risk parity':
res = minimize(fun1, x0, bounds=bnds, constraints=cons, method='SLSQP', options=options)
elif method == 'pc risk parity':
res = minimize(fun2, x0, bounds=bnds, constraints=cons, method='SLSQP', options=options)
else:
raise ValueError('method error!!!')
# 权重调整
if res['success'] == False:
# print res['message']
pass
wts = pd.Series(index=cov_mat.index, data=res['x'])
if wts_adjusted == True:
wts[wts < 0.0001]=0.0
wts = wts / wts.sum()
elif wts_adjusted == False:
wts = wts / wts.sum()
else:
raise ValueError('wts_adjusted should be True/False!')
risk = pd.Series(wts * (omega * np.matrix(wts).T).A1 / np.sqrt(np.matrix(wts) * omega * np.matrix(wts).T).A1[0],index = cov_mat.index)
risk[risk<0.0] = 0.0
return wts,risk
pct_daily_new = pct_daily.reindex(tradingday_list) #回测期间的资产收益率
pct_daily_new.head().append(pct_daily_new.tail())
3 主成分风险模型的应用实证¶
该部分耗时 30分钟
使用风险平价模型和主成分风险平价模型对前述资产组合进行回测检验。每季度末进行资产风险再平衡。
资产收益率协方差矩阵根据历史240个交易日进行估计。
计算过程中将每个调仓节点的资产权重(weight)和风险贡献(risk)保存下来。
def get_near_tradingday(date):
return (get_price('000001.XSHG',end_date=date,count=1).index[0])
exchange_day = map(get_near_tradingday,date_list)
np.array(exchange_day)
weight_rp_df = pd.DataFrame()
risk_rp_df = pd.DataFrame()
weight_pcrp_df = pd.DataFrame()
risk_pcrp_df = pd.DataFrame()
t1=dt.datetime.now()
for date in date_list[:]:
t2=dt.datetime.now()
print ('计算到%s,已耗时%s秒'%(date,(t2-t1).seconds))
date_pre_y = tradingday_list_tot[tradingday_list_tot.index(get_near_tradingday(date))-240]
weight_and_risk_rp = get_smart_weight(pct_daily.loc[date_pre_y:get_near_tradingday(date)],method='risk parity', cov_adjusted=0, wts_adjusted=1)#.reindex(pct_daily.columns).fillna(0)
weight_rp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_rp[0]
risk_rp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_rp[1]
weight_and_risk_pcrp = get_smart_weight(pct_daily.loc[date_pre_y:get_near_tradingday(date)],method='pc risk parity', cov_adjusted=0, wts_adjusted=1)#.reindex(pct_daily.columns).fillna(0)
weight_pcrp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_pcrp[0]
risk_pcrp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_pcrp[1]
weight_rp_df= weight_rp_df.T.reindex(tradingday_list).fillna(method='ffill')#风险平价模型的资产权重
weight_rp_df.head()
weight_pcrp_df= weight_pcrp_df.T.reindex(tradingday_list).fillna(method='ffill')#主成分风险平价模型的资产权重
weight_pcrp_df.head()
risk_rp_df= risk_rp_df.T.reindex(tradingday_list).fillna(method='ffill')#风险平价模型的资产风险贡献权重
risk_rp_df.head()
risk_pcrp_df= risk_pcrp_df.T.reindex(tradingday_list).fillna(method='ffill')#主成分风险平价模型的资产风险贡献权重
risk_pcrp_df.head()
pct_daily = pct_daily.reindex(tradingday_list)
pct_daily.head()
根据历史资产权重及日收益率,分别绘制风险平价(RP)模型和主成分风险平价(PCRP)模型的净值曲线图。
可以看出PCRP模型的净值曲线波动明显低于RP模型,收益率也要优于RP模型。
net_value=pd.DataFrame()
net_value['rp'] = (weight_rp_df*(pct_daily_new+1)).sum(axis=1).cumprod()
net_value['pcrp'] = (weight_pcrp_df*(pct_daily_new+1)).sum(axis=1).cumprod()
net_value['rp'] = ((weight_rp_df*pct_daily_new).sum(axis=1)+1).cumprod()
net_value['pcrp'] = ((weight_pcrp_df*pct_daily_new).sum(axis=1)+1).cumprod()
net_value[['rp','pcrp']].plot(figsize=(15,6),grid='on',rot=60)
下面分析RP模型和PCRP模型的资产权重分布图和风险贡献分布图。
资产权重方面: RP模型在国债和企债上的投资比例相对均衡,而PCRP模型主要投资于企债指数,在各资产上的投资权重变化速度也要明显高于RP模型。
风险贡献方面: RP模型中各类资产对投资组合的风险贡献比例相等,事实上RP模型各类资产的投资权重是由风险贡献比例相等反推确定的。PCRP模型旨在确保主成分风险因子上的等比例风险贡献。由于投资组合中有一半的资产都是权益类资产,因此RP模型中权益类资产提供了50%的风险贡献,而风险贡献图中表明大部分情况下PCRP模型中权益类资产只提供了远小于50%的风险贡献,从而使得PCRP组合的风险要低于RP组合。这体现了PCRP模型在高相关资产组合配置中的优势。
weight_pcrp_df.reindex(exchange_day).plot(figsize=(15,8),rot=60,kind='area',ylim=(0,1))#PCRP模型资产权重图
risk_pcrp_df.reindex(exchange_day).plot(figsize=(15,8),rot=60,kind='area')#PCRP模型资产风险贡献图,坐标轴rotation,kind图形种类area面积图
weight_rp_df.reindex(exchange_day).plot(figsize=(15,8),rot=60,kind='area',ylim=(0,1))#RP模型资产权重图
risk_rp_df.reindex(exchange_day).plot(figsize=(15,8),rot=60,kind='area')#RP模型资产风险贡献图
4 预期风险估计和预期走势估计¶
该部分耗时 35分钟
4.1 引入预期风险估计¶
相比资产收益率的难预测性,资产的波动率具有较好的可预测性。资产波动率具有比较明显的自相关性,同时资产波动率的自相关性会呈现衰减性。
以沪深300波动率为例,随着滞后阶数的增加,沪深300月波动率的分布越发分散,同时回归模型的拟合优度也在逐渐降低。
绝大多数资产的波动率都存在着明显的自相关性,以及自相关性随着滞后阶数的增加具有明显的衰减性。
基于资产波动率的聚集性还衰减性,可以改进对资产预期风险的估计。具体的,以60个交易日为分界,计算过去240个交易日的4个阶段协方差($\Sigma_1,\Sigma_2,\Sigma_3,\Sigma_4$),以衰退的权重($w_1,w_2,w_3,w_4$)估计预期的协方差$\Sigma = w_1\Sigma_1+w_2\Sigma_2+w_3\Sigma_3+w_4\Sigma_4$。
本文中的风险衰减系数设置为($w_1=0.4,w_2=0.3,w_3=0.2,w_4=0.1$)。
下面根据改进的预期风险估计方法对每期的协方差进行估计,形成衰减加权的风险平价(wdc_RP)模型和衰减加权的主成分风险平价(wdc_PCRP)模型。(wdc for weight decayed)
pct_daily = prices.pct_change()
weight_wdc_rp_df=pd.DataFrame()
risk_wdc_rp_df=pd.DataFrame()
weight_wdc_pcrp_df=pd.DataFrame()
risk_wdc_pcrp_df=pd.DataFrame()
t1=dt.datetime.now()
for date in date_list[:]:
t2=dt.datetime.now()
print ('计算到%s,已耗时%s秒'%(date,(t2-t1).seconds))
date_pre_y = tradingday_list_tot[tradingday_list_tot.index(get_near_tradingday(date))-240]
weight_and_risk_wdc_rp = get_smart_weight(pct_daily.loc[date_pre_y:get_near_tradingday(date)],method='risk parity', cov_adjusted=1, wts_adjusted=1)
#衰减加权的风险平价(wdc_RP)模型资产权重
weight_wdc_rp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_wdc_rp[0]
#衰减加权的风险平价(wdc_RP)模型风险贡献比例
risk_wdc_rp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_wdc_rp[1]
weight_and_risk_wdc_pcrp = get_smart_weight(pct_daily.loc[date_pre_y:get_near_tradingday(date)],method='pc risk parity', cov_adjusted=1, wts_adjusted=1)
#衰减加权的主成分风险平价(wdc_PCRP)模型资产权重
weight_wdc_pcrp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_wdc_pcrp[0]
#衰减加权的主成分风险平价(wdc_PCRP)模型风险贡献权重
risk_wdc_pcrp_df.loc[:,get_near_tradingday(date)] = weight_and_risk_wdc_pcrp[1]
weight_wdc_rp_df= weight_wdc_rp_df.T.reindex(tradingday_list).fillna(method='ffill')
weight_wdc_pcrp_df= weight_wdc_pcrp_df.T.reindex(tradingday_list).fillna(method='ffill')
引入预期风险估计的资产配置模型与传统资产配置模型相比,虽然年化收益率没有提升,但是使得模型的年化波动率和最大回撤降低,从而在一定程度上提升投资组合的收益风险比。
衰减加权的风险平价(wdc_RP)模型净值¶
net_value['wdc_rp'] = ((weight_wdc_rp_df*pct_daily_new).sum(axis=1)+1).cumprod()
衰减加权的主成分风险平价(wdc_PCRP)模型净值¶
net_value['wdc_pcrp'] = ((weight_wdc_pcrp_df*pct_daily_new).sum(axis=1)+1).cumprod() net_value[['wdc_pcrp','pcrp']].plot(figsize=(15,6),grid='on',rot=60)
4.2 引入预期走势估计¶
趋势跟踪是一种利用在不同市场交易的长期变化进行投资的交易技术,可应用于所有时间交易模型。其基本假设是市场会保持上涨或者下跌的趋势,即在上涨时做多,在下跌时做空,并预期这种趋势会继续保持。本文以简单的均线法为例,测算预期走势估计对资产配置模型的改进作用。具体的,当资产价格上穿周期移动平均线时,可以判断为买入信号;当资产价格下穿周期移动平均线时,可以判断为卖出信号。
$$w^{'}_{t,i}=logical(p_{t,i}-MA(n)_{t,i})\times{w_{t,i}}$$其中$logical(x)$为逻辑函数,$logical(x\geq0)=1$;$logical(x\leq0)=0$。
虽然移动平均线所反映的信息存在一定的时滞性,但移动平均线是对历史趋势的有效呈现, 在一定程度上可以降低噪音对市场趋势判断的负面影响。
本文以月末资产价格为代理变量进行研究,均线窗口期为3个月,当预期走势看空时,选择卖出该资产,并以无风险资产(日收益率简化为1.25%%)进行替代。
#按月末价格进行重采样
prices_M = prices.resample('M',how='last')
#根据价格与均线关系判断择时信号
TF=(prices_M>pd.rolling_mean(prices_M,3)).shift(1)
#将择时信号与交易日进行对齐
TF['near_date']=map(get_near_tradingday,TF.index)
#根据择时信号调整资产权重(若该资产看多:仓位为100%或看空:仓位为0%)
weight_adjusted=(TF.set_index('near_date').reindex(tradingday_list).fillna(method='ffill'))
#无风险收益率
pct_norisk = 1.25e-4
#引入预期走势估计的RP模型净值,等式右边第二项为用无风险资产替换看空仓位部分的收益
net_value['TF_rp']=((weight_adjusted*weight_rp_df*pct_daily_new).sum(axis=1)+\
(1-(weight_adjusted*weight_rp_df).sum(axis=1))*pct_norisk+1).cumprod()
#引入预期走势估计的PCRP模型净值,等式右边第二项为用无风险资产替换看空仓位部分的收益
net_value['TF_pcrp']=((weight_adjusted*weight_pcrp_df*pct_daily_new).sum(axis=1)+\
(1-(weight_adjusted*weight_pcrp_df).sum(axis=1))*pct_norisk+1).cumprod()
#引入预期走势估计的wdc_RP模型净值,等式右边第二项为用无风险资产替换看空仓位部分的收益
net_value['TF_wdc_rp']=((weight_adjusted*weight_wdc_rp_df*pct_daily_new).sum(axis=1)+\
(1-(weight_adjusted*weight_wdc_rp_df).sum(axis=1))*pct_norisk+1).cumprod()
#引入预期走势估计的wdc_PCRP模型净值,等式右边第二项为用无风险资产替换看空仓位部分的收益
net_value['TF_wdc_pcrp']=((weight_adjusted*weight_wdc_pcrp_df*pct_daily_new).sum(axis=1)+\
(1-(weight_adjusted*weight_wdc_pcrp_df).sum(axis=1))*pct_norisk+1).cumprod()
net_value[['TF_rp','rp']].plot(figsize=(15,6),grid='on',rot=60)
net_value[['TF_pcrp','pcrp']].plot(figsize=(15,6),grid='on',rot=60)
绘制衰减加权的风险平价(wdc_RP)模型的资产权重图
weight_wdc_rp_df.reindex(exchange_day).plot(figsize=(15,8),rot=60,kind='area',ylim=(0,1))
绘制引入预期走势估计的衰减加权风险平价(TF_wdc_RP)模型的资产权重图。可见在引入预期走势后,模型在大致预判各类资产未来走势的同时, 大幅度降低投资组合的风险,例如股灾期间对权益类资产的看空,避免了组合的较大回撤。
(weight_adjusted*weight_wdc_rp_df).reindex(exchange_day).plot(figsize=(15,8),rot=60,kind='area',ylim=(0,1))
为了方便后续对数据进行处理,将数据保存为pkl文件,数据类型为dict,key为数据种类,value为相应数据的时间序列。
#使用pickle模块将数据对象保存到文件
save_data={}
save_data['weight_rp'] = weight_rp_df
save_data['weight_pcrp'] = weight_pcrp_df
save_data['weight_wdc_rp'] = weight_wdc_rp_df
save_data['weight_wdc_pcrp'] = weight_wdc_pcrp_df
save_data['risk_rp'] = risk_rp_df
save_data['risk_pcrp'] = risk_pcrp_df
save_data['risk_wdc_rp'] = risk_wdc_rp_df
save_data['risk_wdc_pcrp'] = risk_wdc_pcrp_df
save_data['net_value'] = net_value
content = pickle.dumps(save_data)
write_file('save_data_v4.pkl', content, append=False)
pkl_file_read = read_file('save_data_v4.pkl')
load_data = pickle.load(StringIO(pkl_file_read))
net_value = load_data['net_value']
weight_rp_df = load_data['weight_rp']
weight_pcrp_df = load_data['weight_pcrp']
weight_wdc_rp_df = load_data['weight_wdc_rp']
weight_wdc_pcrp_df = load_data['weight_wdc_pcrp']
4.3 改进的主成分风险平价模型收益风险指标汇总¶
class backtest_result():
def __init__(self,data):
self.data = data
self.total_returns = data.iloc[-1]-1
self.annualized_returns = data.iloc[-1]**(250./len(data))-1
self.annualized_volatility = data.pct_change().std()*(250.**0.5)
def Max_Drawback(self):
net_value=self.data
max_value=0
df_tmp=pd.DataFrame(net_value)
df_tmp.columns=['value']
for j in range(0,len(net_value),1):
max_value=max(max_value,df_tmp.ix[j,'value'])
df_tmp.ix[j,'drawback']=1-df_tmp.ix[j,'value']/max_value
drawback=df_tmp['drawback'].max()
return drawback
def Sharpe(self):
net_value=self.data
bench_pct=0.03
df_tmp=pd.DataFrame(net_value)
df_tmp.columns=['value']
df_tmp['pct']=df_tmp['value'].pct_change()
annual_pct = df_tmp.ix[-1,'value']**(250./len(df_tmp))-1
sharpe = (annual_pct-bench_pct)/(df_tmp['pct'].std()*250**0.5)
return sharpe
def Calmar(self):
clamar = self.annualized_returns/self.Max_Drawback()
return clamar
results=pd.DataFrame()
for c in ['rp','pcrp','wdc_rp','wdc_pcrp','TF_pcrp','wdc_pcrp','TF_wdc_pcrp']:
nv = net_value[c]
results.loc['累计收益率',c]=backtest_result(nv).total_returns
results.loc['年化收益率',c]=backtest_result(nv).annualized_returns
results.loc['年化波动率',c]=backtest_result(nv).annualized_volatility
results.loc['最大回撤',c]=backtest_result(nv).Max_Drawback()
results.loc['夏普比率',c]=backtest_result(nv).Sharpe()
results.loc['Calmar比率',c]=backtest_result(nv).Calmar()
results
5 总结¶
主成分风险平价模型关注的是资产背后的主成分风险因子,因此在收益和风险等诸多方面相对于传统风险平价模型均具有明显的优势。
引入风险预估和走势预估后,波动率与回撤指标得到改善,加强了模型的风险控制能力。当然,不同类型资产的风险预估和走势预估存在一定的差异性,本文在此仅是简单的统一处理,还有许多可改进的空间。