基于收益率的基金绩效归因
目的
使用Python和Tushare数据,基于基金净值分析基金选股、择时能力。
常用绩效归因模型
- CAPM模型
- TM模型
- HM模型
- CL模型
- TM-FF3模型
- HM-FF3模型
- CL-FF3模型
模型分析及程序实现
使用到的库
#t导入ushare库
import tushare as ts
pro = ts.pro_api('your token')
#导入统计库
import statsmodels.api as sm
#导入pandas
import pandas as pd
#统一起见,无风险收益率设为年化3%
rf=1.03**(1/250)-1
通用函数
获取指数日收益率序列
def get_index_price(code,start_date,end_date):"""功能:获取指定指数一定时间段内日收益率序列输入:code:指数代码start_date:开始日期end_date:结束日期返回:DataFrame,index=日期,columns='close'"""#使用tushare获取数据。df=pro.index_daily(**{"ts_code":code,"start_date":start_date,"end_date":end_date},fields=["trade_date","close"])#设置日期为索引df.set_index('trade_date',inplace=True)#按升序排列df.sort_index(ascending=True,inplace=True)#计算每日收益率result=df/df.shift(1)-1#去掉空值result.dropna(inplace=True)#返回数据return result['close']
获取基金日收益率序列
def get_fund_netvalue(code,start_date,end_date):"""功能:获取指定基金一定时间段内每日收益率序列输入:code:基金代码start_date:开始日期end_date:结束日期返回:Series,index=日期"""df=pro.fund_nav(**{"ts_code":code,"start_date":start_date,"end_date":end_date},fields=["nav_date","accum_nav"])df.set_index('nav_date',inplace=True)df.sort_index(ascending=True,inplace=True)result=df/df.shift(1)-1result.dropna(inplace=True)return result['accum_nav']
CAPM模型
公式:
R−Rf=α+β(Rm−Rf)+ϵR-R_f=\alpha+\beta(R_m-R_f)+\epsilonR−Rf=α+β(Rm−Rf)+ϵ
解读:
β说明在市场风险上的暴露,α代表选股能力。α>0代表有正向选股能力\beta说明在市场风险上的暴露,\alpha代表选股能力。\alpha>0代表有正向选股能力β说明在市场风险上的暴露,α代表选股能力。α>0代表有正向选股能力
每个参数对应的p值代表结果是否显著,p<0.05表示显著每个参数对应的p值代表结果是否显著,p<0.05表示显著每个参数对应的p值代表结果是否显著,p<0.05表示显著
#CAPM模型计算
def CAPM(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:Series,基金日收益率序列index_rtn:Series,指数日收益率序列输出:字典,key=alpha,beta,p_alpha,p_beta"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx=data['index_rtn']-rf#添加约束x=sm.add_constant(x)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['alpha']=(1+cal_result.params['const'])**250-1#年化alpharesult['beta']=cal_result.params['index_rtn']result['p_alpha']=cal_result.pvalues['const']result['p_beta']=cal_result.pvalues['index_rtn']result['R2']=cal_result.rsquaredreturn result
TM模型
公式
R−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)2+ϵR-R_f=\alpha+\beta_1(R_m-R_f)+\beta_2(R_m-R_f)^2+\epsilonR−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)2+ϵ
解读
α显著大于0说明有选股能力,β1表示在市场风险的暴露,β2显著大于0说明有择时能力\alpha显著大于0说明有选股能力,\\ \beta_1表示在市场风险的暴露,\beta_2显著大于0说明有择时能力α显著大于0说明有选股能力,β1表示在市场风险的暴露,β2显著大于0说明有择时能力
def TM(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:基金日收益率序列index_rtn:指数日收益率序列输出:字典,key=alpha,beta1,beta2,p_alpha,p_beta1,p_beta2,R2"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx1=data['index_rtn']-rfx2=x1**2#整合rm数据x_data=pd.DataFrame()x_data['rm1']=x1x_data['rm2']=x2#添加约束x=sm.add_constant(x_data)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['alpha']=(1+cal_result.params['const'])**250-1result['beta1']=cal_result.params['rm1']result['beta2']=cal_result.params['rm2']result['p_alpha']=cal_result.pvalues['const']result['p_beta1']=cal_result.pvalues['rm1']result['p_beta2']=cal_result.pvalues['rm2']result['R2']=cal_result.rsquaredreturn result
HM模型
公式
R−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)D+ϵR-R_f=\alpha+\beta_1(R_m-R_f)+\beta_2(R_m-R_f)D+\epsilonR−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)D+ϵ
其中:
当Rm−Rf>0时D=1,否则D=0当R_m-R_f>0时D=1,否则D=0当Rm−Rf>0时D=1,否则D=0
α,β含义与TM相同\alpha,\beta含义与TM相同α,β含义与TM相同
def HM(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:基金日收益率序列index_rtn:指数日收益率序列输出:字典,key=alpha,beta1,beta2,p_alpha,p_beta1,p_beta2,R2"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx1=data['index_rtn']-rfx2=x1.copy()x2[x2<=0]=0#整合rm数据x_data=pd.DataFrame()x_data['rm1']=x1x_data['rm2']=x2#添加约束x=sm.add_constant(x_data)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['alpha']=(1+cal_result.params['const'])**250-1result['beta1']=cal_result.params['rm1']result['beta2']=cal_result.params['rm2']result['p_alpha']=cal_result.pvalues['const']result['p_beta1']=cal_result.pvalues['rm1']result['p_beta2']=cal_result.pvalues['rm2']result['R2']=cal_result.rsquaredreturn result
CL模型
公式
R−Rf=α+β1×min(0,Rm−Rf)+β2×max(0,Rm−Rf)D+ϵR-R_f=\alpha+\beta_1\times min(0,R_m-R_f)+\beta_2\times max(0,R_m-R_f)D+\epsilonR−Rf=α+β1×min(0,Rm−Rf)+β2×max(0,Rm−Rf)D+ϵ
解读
β1代表空头市场β,β2代表多头市场β,β2−β1>0说明有择时能力\beta_1代表空头市场\beta,\beta_2代表多头市场\beta,\beta_2-\beta_1>0说明有择时能力β1代表空头市场β,β2代表多头市场β,β2−β1>0说明有择时能力
def CL(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:基金日收益率序列index_rtn:指数日收益率序列输出:字典,key=alpha,beta1,beta2,beta,p_alpha,p_beta1,p_beta2,R2。其中beta=beta2-beta1代表择时能力"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx1=data['index_rtn']-rfx2=x1.copy()#计算beta1对应的收益率,当收益率大于0时为0x1[x1>0]=0#计算beta2对应的收益率,当收益率小于0时为0x2[x2<=0]=0#整合rm数据x_data=pd.DataFrame()x_data['rm1']=x1x_data['rm2']=x2#添加约束x=sm.add_constant(x_data)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['alpha']=(1+cal_result.params['const'])**250-1result['beta1']=cal_result.params['rm1']result['beta2']=cal_result.params['rm2']result['beta']=result['beta2']-result['beta1']result['p_alpha']=cal_result.pvalues['const']result['p_beta1']=cal_result.pvalues['rm1']result['p_beta2']=cal_result.pvalues['rm2']result['R2']=cal_result.rsquaredreturn result
FF3模型
前面的TM、HM、CL模型都只考虑了市场影响,而没有考虑基金在某种风格上的暴露。
Fama和French引入了公司规模因子(SMB)和账面市值因子(HML),就是常说的大盘、小盘、价值、成长风格,建立了TM-FF3、HM-FF3、CL-FF3模型。
SMB和HML因子收益率有很多方法,比如大中小盘用市值最大的前200只为大盘,200-500为中盘,501以后为小盘,然后每个市值分组中再按估值、利润增速、营收增速等综合打分确定价值成长风格,然后用不同分组收益率相减得到该风格收益率。这种方法需要的数据量太大(全市场数据),tushare上取得这些数据需要的积分太高,所以此处使用简化方法:SMB收益率用巨潮小盘指数-巨潮大盘指数收益率,HML收益率用国证成长指数-国证价值指数收益率代替。
TM-FF3模型
首先看TM-FF3模型
公式:
R−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)2+θ1SMB+θ2HML+ϵR-R_f=\alpha+\beta_1(R_m-R_f)+\beta_2(R_m-R_f)^2+\theta_1SMB+\theta_2HML+\epsilonR−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)2+θ1SMB+θ2HML+ϵ
其中θ1和θ2分别表示在大小盘风格、价值成长风格上的暴露\theta_1和\theta_2分别表示在大小盘风格、价值成长风格上的暴露θ1和θ2分别表示在大小盘风格、价值成长风格上的暴露
def TM_FF3(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:基金日收益率序列index_rtn:指数日收益率序列HML_rtn:价值成长指数日收益率序列SMB_rtn:大小盘指数日收益率序列输出:字典,key=alpha,beta1,beta2,p_alpha,p_beta1,p_beta2,R2"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx1=data['index_rtn']-rfx2=x1**2#整合rm数据x_data=pd.DataFrame()x_data['rm1']=x1x_data['rm2']=x2x_data['HML']=data['HML_rtn']x_data['SMB']=data['SMB_rtn']#添加约束x=sm.add_constant(x_data)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['alpha']=(1+cal_result.params['const'])**250-1result['beta1']=cal_result.params['rm1']result['beta2']=cal_result.params['rm2']result['theta1']=cal_result.params['SMB']result['theta2']=cal_result.params['HML']result['p_alpha']=cal_result.pvalues['const']result['p_beta1']=cal_result.pvalues['rm1']result['p_beta2']=cal_result.pvalues['rm2']result['p_theta1']=cal_result.pvalues['SMB']result['p_theta2']=cal_result.pvalues['HML']result['R2']=cal_result.rsquaredreturn result
HM-FF3模型
公式
R−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)D+θ1SMB+θ2HML+ϵR-R_f=\alpha+\beta_1(R_m-R_f)+\beta_2(R_m-R_f)D+\theta_1SMB+\theta_2HML+\epsilonR−Rf=α+β1(Rm−Rf)+β2(Rm−Rf)D+θ1SMB+θ2HML+ϵ
解读:
当Rm−Rf>0时D=1,否则D=0当R_m-R_f>0时D=1,否则D=0当Rm−Rf>0时D=1,否则D=0
def HM_FF3(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:基金日收益率序列index_rtn:指数日收益率序列HML_rtn:价值成长指数日收益率序列SMB_rtn:大小盘指数日收益率序列输出:字典,key=alpha,beta1,beta2,p_alpha,p_beta1,p_beta2,R2"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx1=data['index_rtn']-rfx2=x1.copy()x2[x2<=0]=0#整合rm数据x_data=pd.DataFrame()x_data['rm1']=x1x_data['rm2']=x2x_data['HML']=data['HML_rtn']x_data['SMB']=data['SMB_rtn']#添加约束x=sm.add_constant(x_data)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['theta1']=cal_result.params['SMB']result['theta2']=cal_result.params['HML']result['alpha']=(1+cal_result.params['const'])**250-1result['beta1']=cal_result.params['rm1']result['beta2']=cal_result.params['rm2']result['p_alpha']=cal_result.pvalues['const']result['p_beta1']=cal_result.pvalues['rm1']result['p_beta2']=cal_result.pvalues['rm2']result['p_theta1']=cal_result.pvalues['SMB']result['p_theta2']=cal_result.pvalues['HML']result['R2']=cal_result.rsquaredreturn result
CL-FF3模型
公式
R−Rf=α+β1×min(0,Rm−Rf)+β2×max(0,Rm−Rf)+θ1SMB+θ2HML+ϵR-R_f=\alpha+\beta_1\times min(0,R_m-R_f)+\beta_2\times max(0,R_m-R_f)+\theta_1SMB+\theta_2HML+\epsilonR−Rf=α+β1×min(0,Rm−Rf)+β2×max(0,Rm−Rf)+θ1SMB+θ2HML+ϵ
解读
β1代表空头市场β,β2代表多头市场β,β2−β1>0说明有择时能力\beta_1代表空头市场\beta,\beta_2代表多头市场\beta,\beta_2-\beta_1>0说明有择时能力β1代表空头市场β,β2代表多头市场β,β2−β1>0说明有择时能力
def CL_FF3(data):"""功能:使用CAPM模型计算选股能力输入:data:DataFrame,index=日期columns包括:fund_rtn:基金日收益率序列index_rtn:指数日收益率序列HML_rtn:价值成长指数日收益率序列SMB_rtn:大小盘指数日收益率序列输出:字典,key=alpha,beta1,beta2,beta,p_alpha,p_beta1,p_beta2,R2。其中beta=beta2-beta1代表择时能力"""#计算R-Rf,Rm-Rfy=data['fund_rtn']-rfx1=data['index_rtn']-rfx2=x1.copy()#计算beta1对应的收益率,当收益率大于0时为0x1[x1>0]=0#计算beta2对应的收益率,当收益率小于0时为0x2[x2<=0]=0#整合rm数据x_data=pd.DataFrame()x_data['rm1']=x1x_data['rm2']=x2x_data['HML']=data['HML_rtn']x_data['SMB']=data['SMB_rtn']#添加约束x=sm.add_constant(x_data)#回归计算cal_result=sm.OLS(y,x).fit()#取得结果result={}result['alpha']=(1+cal_result.params['const'])**250-1result['beta1']=cal_result.params['rm1']result['beta2']=cal_result.params['rm2']result['beta']=result['beta2']-result['beta1']result['theta1']=cal_result.params['SMB']result['theta2']=cal_result.params['HML']result['p_alpha']=cal_result.pvalues['const']result['p_beta1']=cal_result.pvalues['rm1']result['p_beta2']=cal_result.pvalues['rm2']result['p_theta1']=cal_result.pvalues['SMB']result['p_theta2']=cal_result.pvalues['HML']result['R2']=cal_result.rsquaredreturn result
测试
获取数据
fund_code='000628.OF'#基金代码,以大成高新技术产业股票型证券投资基金为例
base='000300.SH'#市场基准指数用沪深300
index_B='399314.SZ'#巨潮大盘指数
index_S='399316.SZ'#巨潮小盘指数
index_H='399371.SZ'#国证价值指数
index_L='399370.SZ'#国证成长指数
start_date='20160729'
end_date='20220601'
data=pd.DataFrame()
data['fund_rtn']=get_fund_netvalue(fund_code,start_date,end_date)
data['index_rtn']=get_index_price(base,start_date,end_date)
#SMB因子收益
data['SMB_rtn']=get_index_price(index_S,start_date,end_date)-get_index_price(index_B,start_date,end_date)
#HML因子收益
data['HML_rtn']=get_index_price(index_H,start_date,end_date)-get_index_price(index_L,start_date,end_date)
data.dropna(inplace=True)
不考虑风格因子
result={}
result['CAPM']=CAPM(data)
result['TM']=TM(data)
result['HM']=HM(data)
result['CL']=CL(data)
result=pd.DataFrame(result).T.applymap(lambda x:"{:.2%}".format(x)).replace('nan%','/')
result[['alpha','beta','beta1','beta2','p_alpha','p_beta','p_beta1','p_beta2','R2']]
此处以大成高新技术产业股票型证券投资基金为例。
测试结果:
alpha | beta | beta1 | beta2 | p_alpha | p_beta | p_beta1 | p_beta2 | R2 | |
---|---|---|---|---|---|---|---|---|---|
CAPM | 15.94% | 81.22% | / | / | 0.01% | 0.00% | / | / | 74.25% |
TM | 22.08% | / | 80.61% | -143.65% | 0.00% | / | 0.00% | 0.14% | 74.44% |
HM | 26.76% | / | 83.22% | -7.43% | 0.00% | / | 0.00% | 2.91% | 77.54% |
CL | 29.16% | -10.10% | 85.99% | 75.89% | 0.00% | / | 0.00% | 0.00% | 74.39% |
年化α几个模型都在20以上,且p值小于0.05,说明选股能力不错。TM、HM模型的β2为负数,且p值小于0.05,说明没有择时能力。年化\alpha几个模型都在20以上,且p值小于0.05,说明选股能力不错。\\ TM、HM模型的\beta2为负数,且p值小于0.05,说明没有择时能力。 年化α几个模型都在20以上,且p值小于0.05,说明选股能力不错。TM、HM模型的β2为负数,且p值小于0.05,说明没有择时能力。
考虑风格因子
result={}
result['TM']=TM_FF3(data)
result['HM']=HM_FF3(data)
result['CL']=CL_FF3(data)
result=pd.DataFrame(result).T.applymap(lambda x:"{:.2%}".format(x)).replace('nan%','/')
result[['alpha','beta','beta1','beta2','theta1','theta2','p_alpha','p_beta1','p_beta2','p_theta1','p_theta2','R2']]
测试结果:
alpha | beta | beta1 | beta2 | theta1 | theta2 | p_alpha | p_beta1 | p_beta2 | p_theta1 | p_theta2 | R2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
TM | 21.00% | / | 79.32% | -91.90% | 17.79% | -11.40% | 0.00% | 0.00% | 2.95% | 0.00% | 0.00% | 77.53% |
HM | 26.76% | / | 83.22% | -7.43% | 17.89% | -11.44% | 0.00% | 0.00% | 2.91% | 0.00% | 0.00% | 77.54% |
CL | 26.76% | -7.43% | 83.22% | 75.78% | 17.89% | -11.44% | 0.00% | 0.00% | 0.00% | 0.00% | 0.00% | 77.54% |
α结果与不考虑风格因子接近,β2也说明没有择时能力。θ1显著大于0,说明市值风格偏向大盘。θ2显著小于0,说明价值成长风格偏向成长。\alpha结果与不考虑风格因子接近,\beta2也说明没有择时能力。\\ \theta1显著大于0,说明市值风格偏向大盘。\\ \theta2显著小于0,说明价值成长风格偏向成长。 α结果与不考虑风格因子接近,β2也说明没有择时能力。θ1显著大于0,说明市值风格偏向大盘。θ2显著小于0,说明价值成长风格偏向成长。
注意事项
虽然本次测试效果较好,但是要注意净值归因的主要缺陷,回归统计有可能因为各因子的共线性存在误差,另外在混合基金尤其是灵活配置基金上,因为基金配置了债券,回归效果不好。
基于收益率的基金绩效归因相关推荐
- 【基金量化研究系列】基金绩效归因模型(三)——基于CAPM、T-M、H-M、C-L模型的基金绩效归因研究
文章目录 1. 引言 2. 模型介绍 2.1 CAPM模型 2.2 T-M模型 2.3 H-M模型 2.4 C-L模型 2.5 H-M模型 V.S. C-L模型 3. 实证分析 3.1 数据选择 3. ...
- 【基金量化研究系列】基金绩效归因模型——Brinson多期归因模型
文章目录 1. 引言 2. Brinson单期归因模型 2.1 模型框架 2.2 公式推导 3. Brinson多期归因模型 3.1 模型框架 3.2 公式推导 4. Brinson模型的应用场景 4 ...
- matlab 基金业绩归因,基金的绩效归因方法及应用.ppt
长江金工基金因子分析平台 资料来源:Wind, 长江证券研究所 图4: 行业指数最佳拟合点散点图 图5: 行业指数最佳拟合点指数走势 资料来源:Wind, 长江证券研究所 长江金工基金因子分析平台 使 ...
- matlab 基金业绩归因,基金专题报告:基于净值和持仓的基金业绩归因方法研究...
核心观点: 当前主流的基金业绩归因方法主要有两个方向:一是基于净值数据的时间序列回归方法,所需数据较少且操作简单,主要通过基金历史收益率与风险溢价因子收益率进行回归来分析,二是基于持仓数据的归因方法, ...
- 评价PE基金绩效的常用指标IRR、MIOC、DPI、TVPI意义
评价PE基金绩效的常用指标 作为信息系统,辅助管理层决策是重要的功能之一.前文介绍了PE基金管理系统的建设,对PE业务的运转有了一些了解,但没有介绍如何评价PE基金的绩效,而这是管理层作出重大决策的主 ...
- 基金绩效衡量指标_衡量绩效
基金绩效衡量指标 Clients care deeply about web performance and they depend on us to articulate and measure h ...
- matlab 基金业绩归因,基金从业知识点2017:业绩归因
基金从业知识点2017:业绩归因 引导语:业绩指完成的事业和建立的功劳.以下是百分网小编分享给大家的基金从业知识点2017:业绩归因,欢迎阅读!更多精彩内容请持续关注我们应届毕业生考试网! 业绩归因 ...
- 使用php进行财务统计,基于php的基金财务数据接口调用代码实例
代码描述:基于php的基金财务数据接口调用代码实例 关联数据:基金财务数据 接口地址:http://www.juhe.cn/docs/api/id/28 1.[代码][PHP]代码 // +----- ...
- 年化超额收益计算matlab,超额年化收益率的计算 看了一下雪球上一些雪友贴出的基金或大V的历年收益率,发现一些人统计的不对,想说一下: 1.超额收益率 某基金当年收益率为... - 雪球...
来源:雪球App,作者: Money_Ball,(https://xueqiu.com/1930958059/167803003) 看了一下雪球上一些雪友贴出的基金或大V的历年收益率,发现一些人统计的 ...
- java基金管理系统,基于JSP(java)基金管理系统的设计和实现 - 图文
论文是本团队帮同学做过的案例,需要毕业论文设计(论文+源程序+答辩PPT)的同学联系799523222 基于JSP基金管理系统的设计和实现 专 业: 年 级: 学 号: 作 者: 指导老师: I Th ...
最新文章
- 微信小程序使用npm 进行下载构建组价
- mysql 统计做饼状图_PHP+mysql+Highcharts实现饼状统计图
- java 计算移动平均线_基于Java语言开发的个性化股票分析技术:移动平均线(MA)...
- java 8中构建无限的stream
- 机器学习笔记III: 基于支持向量机的分类预测
- mysql字符集解释_MySQL字符集详解
- MVC应用程序JsonResult()的练习
- Java模拟文件管理器
- HTTP报文(这篇讲得比较详细)
- 北京邮电计算机课程表,(北邮通信工程本科专业课程表.doc
- 图相关论文阅读与总结
- face_recognition 人脸识别
- 全志平台Android开关核进程迁移导致游戏卡顿调试记录
- codeforces1100 F. Ivan and Burgers(线性基)
- 关于web前端大作业的HTML网页设计——我的班级网页HTML+CSS+JavaScript
- A19T三极管,A19T的规格书
- RS232接口转USB接口的通信方法
- LTE终端开机流程----同步和小区驻留
- 深度学习------pytorch,RNN:句子预测,股票预测
- Kafka实践(八):Kafka的控制器controller