目录

1. 模型介绍

1.1 模型公式

1.2 模型使用

2. 实际案例

2.1 获取数据

2.2 线性回归

2.3 获取时序结果

2.4 完整代码

3. 模型评价

3.1 模型优点

3.2 模型缺点


免责声明:本文由作者参考相关资料,并结合自身实践和思考独立完成,对全文内容的准确性、完整性或可靠性不作任何保证。同时,文中提及的基金仅作为举例使用,不构成推荐;文中所有观点均不构成任何投资建议。请读者仔细阅读本声明,若读者阅读此文章,默认知晓此声明。

1. 模型介绍

1.1 模型公式

H_M模型是在CAPM模型,T_M模型的基础上,进行迭代的基金净值归因类模型,主要用于评价基金的选股收益和择时收益。T_M模型在CAPM的基础上增加了市场风险溢价的二次项,以二次项的回归系数(贝塔2)来判断投资经理的择时能力。H_M模型在T_M模型的基础上增加了二次项的虚拟变量,以引入虚拟变量后的二次项的回归系数(贝塔2)来判断投资经理的择时能力。而后续的C_L模型采取了双虚拟变量的回归方程,其本质上和H_M是等价的。H_M模型相比T_M模型有进一步的优化,在理解层面和表达式层面相对C_L模型简洁。因此,本文选择其作为介绍对象。

H_M模型表达式(二元线性回归方程)如下:

1.2 模型使用

截距项的阿尔法的值表示的是选股能力,这一点和CAPM模型一样。因此阿尔法的值越大,说明投资组合的选股能力越强;反之则越弱。

对于回归系数贝塔1和贝塔2,可以理解为:当市场下跌时,投资组合对应的贝塔值为贝塔1,;当市场上涨时,投资组合上调贝塔值,此时对应的贝塔值为贝塔1和贝塔2的和。因此,如果贝塔2的值大于零,说明投资组合在市场上涨的情况下加仓,是主动择时且表现,且值越大,择时能力体现的越强;反之若贝塔2的值小于零,说明择时能力较差。

值得注意的是,如果单看某一时间点的阿尔法值和贝塔2值,得出的结论相对是不准确的。因此需要观测二者的时序累计走势,提高评价的准确性。

2. 实际案例

2.1 获取数据

本文以一只500增强基金005965(后续简称a基金)作为案例,时间节点选择2022年整年。首先使用akshare开源api,获取中证500指数和a基金在2022年的日度收益率(百分比收益率)数据,假设无风险利率为年化1%,整体的代码如下:

import akshare as ak
import pandas as pd
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as pltdef get_data(index_code, fund_code, start_day, end_day):'''获取回归所需的变量----------index_code:str,指数代码,格式如'sh000905'fund_code:str,基金代码,格式如‘000001’start_day:str,开始日期,格式如'2022-12-01'end_day:str,结束日期,格式如'2022-12-01'Returns: DataFrame-------'''# 获取净值数据,合并表格index_df = ak.stock_zh_index_daily_em(symbol=index_code).sort_values(by=['date'], ascending=True)fund_df = ak.fund_open_fund_info_em(fund=fund_code, indicator="累计净值走势")fund_df['date'] = fund_df['净值日期'].apply(lambda x: pd.to_datetime(x).strftime("%Y-%m-%d"))new_index = index_df.loc[(index_df['date'] >= start_day) & (index_df['date'] <= end_day)]new_fund = fund_df.loc[(fund_df['date'] >= start_day) & (fund_df['date'] <= end_day)]me_df = pd.merge(new_index, new_fund, on='date', how='inner')# 计算收益率(第一行收益率为0,处理后需过滤),合成新的表格r_f = 0.01 / 365  # 无风险利率折算到每天me_df['index_re'] = me_df['close'].pct_change().fillna(0)me_df['fund_re'] = me_df['累计净值'].pct_change().fillna(0)new_me = me_df.iloc[1::]out_df = pd.DataFrame({'date': new_me['date'], 'rm': new_me['index_re'],'rp': new_me['fund_re']})# 合成线性回归所需表格out_df['(rm-rf)'] = out_df['rm'] - r_fout_df['(rp-rf)'] = out_df['rp'] - r_fout_df['(rm-rf)**2'] = out_df['(rm-rf)'].apply(lambda x: x ** 2 if x >= 0 else 0)return out_dfif __name__ == '__main__':index_code = 'sh000905'fund_code = '005965'start_day = '2021-12-31'end_day = '2022-12-30'test_data = get_data(index_code, fund_code, start_day, end_day)

得到的结果如图:

2.2 线性回归

在out_df的基础上,建立全量数据(日期从初始到终止)的回归方程,并得到对应的结果,代码如下:

def get_result(date, data_x, data_y):'''获取线性回归的结果----------终止日:str,开始日期,格式如'2022-12-01'data_x:ndarray, 自变量矩阵data_y:ndarray, 因变量矩阵Returns: DataFrame-------'''model = LinearRegression()new_model = model.fit(data_x, data_y)beta1 = new_model.coef_[0]beta2 = new_model.coef_[1]alpha = new_model.intercept_R = model.score(data_x, data_y)out_df = pd.DataFrame({'日期': [date], 'beta1': [round(beta1, 4)], 'beta2': [round(beta2, 4)],'alpha': [round(alpha, 4)], 'R^2': [round(R, 4)]})return out_dfif __name__ == '__main__':index_code = 'sh000905'fund_code = '005965'start_day = '2021-12-31'end_day = '2022-12-30'test_data = get_data(index_code, fund_code, start_day, end_day)data_x = np.array(test_data.loc[:, ['(rm-rf)', '(rm-rf)**2']])data_y = np.array(test_data['(rp-rf)'])result_df = get_result(end_day, data_x, data_y)

得到的结果如下图:

2.3 获取时序结果

前文例举了单个时间段的模型结果,由于单个时间段的结果存在不确定性,因此我们需要考虑多个时间段的时序结果。接下来,固定起始日,更换截止日,采用循环测算相应的时序结果,考虑到数据样本量对模型效果的影响,本文选择以4月初作为截止日的起点。代码如下:

if __name__ == '__main__':index_code = 'sh000905'fund_code = '005965'start_day = '2021-12-31'end_day = '2022-12-30'test_data = get_data(index_code, fund_code, start_day, end_day)last_df = pd.DataFrame()for num in range(66,len(test_data)+1):new_data = test_data.iloc[:num:]one_date = new_data['date'].max()data_x = np.array(new_data.loc[:, ['(rm-rf)', '(rm-rf)**2']])data_y = np.array(new_data['(rp-rf)'])one_result_df = get_result(one_date, data_x, data_y)last_df = last_df.append(one_result_df)

得到的结果如下:

R^2表示的是可决系数,从图中可以看出可决系数基本在95%左右,说明模型的拟合效果不错。接下来,对得到的数据进行可视化操作。代码如下:

if __name__ == '__main__':index_code = 'sh000905'fund_code = '005965'start_day = '2021-12-31'end_day = '2022-12-30'test_data = get_data(index_code, fund_code, start_day, end_day)last_df = pd.DataFrame()for num in range(66, len(test_data) + 1):new_data = test_data.iloc[:num:]one_date = new_data['date'].max()data_x = np.array(new_data.loc[:, ['(rm-rf)', '(rm-rf)**2']])data_y = np.array(new_data['(rp-rf)'])one_result_df = get_result(one_date, data_x, data_y)last_df = last_df.append(one_result_df)# 作图last_df['日期'] = pd.to_datetime(last_df['日期'])zt = plt.figure()plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']plt.rcParams['axes.unicode_minus'] = Falsename = last_df.columns.tolist()for num in range(1, len(name)):p = zt.add_subplot(2, 2, num)new_name = name[num]p.plot(last_df['日期'], last_df[new_name], label=new_name + '走势', color='orange')plt.legend(loc='best')plt.show()

得到的结果如下图:

从beta1的走势可以看出,a基金自2022年初到8月份贝塔值一直在下降,9月份后贝塔值开始上升,后续保持几乎保持稳定。从beta2的走势可以看出,a基金的择时能力一直为负,只是陆续有所提升,最终贝塔2的值维持在-3附近。从alpha的走势可以看出,a基金的选股能力一直在下降,但最终保持着正向的选股能力。从R^2的走势可以看出,当数据样本量达到一定量后,R^2趋向于稳定在一个较小的区间内,从值可以看出,模型整体的回归效果较好,具备较好的解释性。

总结下来:2022全年,a基金具备正向的选股能力,负向的择时能力

*上述对基金的分析仅为举例的个人观点,不作为任何投资建议以及基金诊断结论,读者请注意。

2.4 完整代码

import akshare as ak
import pandas as pd
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as pltdef get_data(index_code, fund_code, start_day, end_day):'''获取回归所需的变量----------index_code:str,指数代码,格式如'sh000905'fund_code:str,基金代码,格式如‘000001’start_day:str,开始日期,格式如'2022-12-01'end_day:str,结束日期,格式如'2022-12-01'Returns: DataFrame-------'''# 获取净值数据,合并表格index_df = ak.stock_zh_index_daily_em(symbol=index_code).sort_values(by=['date'], ascending=True)fund_df = ak.fund_open_fund_info_em(fund=fund_code, indicator="累计净值走势")fund_df['date'] = fund_df['净值日期'].apply(lambda x: pd.to_datetime(x).strftime("%Y-%m-%d"))new_index = index_df.loc[(index_df['date'] >= start_day) & (index_df['date'] <= end_day)]new_fund = fund_df.loc[(fund_df['date'] >= start_day) & (fund_df['date'] <= end_day)]me_df = pd.merge(new_index, new_fund, on='date', how='inner')# 计算收益率(第一行收益率为0,处理后需过滤),合成新的表格r_f = 0.01 / 365  # 无风险利率折算到每天me_df['index_re'] = me_df['close'].pct_change().fillna(0)me_df['fund_re'] = me_df['累计净值'].pct_change().fillna(0)new_me = me_df.iloc[1::]out_df = pd.DataFrame({'date': new_me['date'], 'rm': new_me['index_re'],'rp': new_me['fund_re']})# 合成线性回归所需表格out_df['(rm-rf)'] = out_df['rm'] - r_fout_df['(rp-rf)'] = out_df['rp'] - r_fout_df['(rm-rf)**2'] = out_df['(rm-rf)'].apply(lambda x: x ** 2 if x >= 0 else 0)return out_dfdef get_result(date, data_x, data_y):'''获取线性回归的结果----------终止日:str,开始日期,格式如'2022-12-01'data_x:ndarray, 自变量矩阵data_y:ndarray, 因变量矩阵Returns: DataFrame-------'''model = LinearRegression()new_model = model.fit(data_x, data_y)beta1 = new_model.coef_[0]beta2 = new_model.coef_[1]alpha = new_model.intercept_R = model.score(data_x, data_y)out_df = pd.DataFrame({'日期': [date], 'beta1': [round(beta1, 4)], 'beta2': [round(beta2, 4)], 'alpha': [round(alpha, 4)],'R^2': [round(R, 4)]})return out_dfif __name__ == '__main__':index_code = 'sh000905'fund_code = '005965'start_day = '2021-12-31'end_day = '2022-12-30'test_data = get_data(index_code, fund_code, start_day, end_day)last_df = pd.DataFrame()for num in range(66, len(test_data) + 1):new_data = test_data.iloc[:num:]one_date = new_data['date'].max()data_x = np.array(new_data.loc[:, ['(rm-rf)', '(rm-rf)**2']])data_y = np.array(new_data['(rp-rf)'])one_result_df = get_result(one_date, data_x, data_y)last_df = last_df.append(one_result_df)# 作图last_df['日期'] = pd.to_datetime(last_df['日期'])zt = plt.figure()plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']plt.rcParams['axes.unicode_minus'] = Falsename = last_df.columns.tolist()for num in range(1, len(name)):p = zt.add_subplot(2, 2, num)new_name = name[num]p.plot(last_df['日期'], last_df[new_name], label=new_name + '走势', color='orange')plt.legend(loc='best')plt.show()

3. 模型评价

3.1 模型优点

1. 模型具有较强的逻辑性,同时具备较强的理论支撑。

2. 数据容易获取,且完整度较高,处理方式也比较常见。

3. 定量化的分析,结果的可靠性较强。

3.2 模型缺点

1. 结论受统计时间区间影响,不同区间结论可能存在差异(若使用结论的时序数据或者采取同期比较可有效优化)。

2. 仅适合具有比较基准的基金,使用范围有限(相对来说较为适合指数类以及指数增强类基金)。

3. 若基金偏离基准较大,模型存在较大概率的失效风险。

4. 模型考虑的影响因素较少,对于择时能力的界定较为粗糙。

免责声明:本文由作者参考相关资料,并结合自身实践和思考独立完成,对全文内容的准确性、完整性或可靠性不作任何保证。同时,文中提及的基金仅作为举例使用,不构成推荐;文中所有观点均不构成任何投资建议。请读者仔细阅读本声明,若读者阅读此文章,默认知晓此声明。

基金评价专题4:H_M(双贝塔)模型相关推荐

  1. 基金评价专题3:交叉积比率

    目录 1. 指标介绍 1.1 定义 1.2 使用方法 2. 案例演示 2.1 获取数据 2.2 数据转换 2.3 计算CPR值 2.4 完整代码 3. 指标评价 3.1 指标优点 3.2 指标缺点 免 ...

  2. 基金评价专题1:绩效指标

    免责声明:本文由作者参考相关资料,并结合自身实践和思考独立完成,对全文内容的准确性.完整性或可靠性不作任何保证.同时,文中提及的基金仅作为举例使用,不构成推荐:文中所有观点均不构成任何投资建议.请读者 ...

  3. stata最大值最小值命令_Stata: 双栏模型简介 (Doublehurdle model)

    编译:李琼琼 (山东大学) Stata 连享会:  知乎 | 简书 | 码云 | CSDN 点击查看完整推文列表 2020寒假Stata现场班 北京, 1月8-17日,连玉君-江艇主讲 2020寒假S ...

  4. Stata: 双栏模型简介 (Double-hurdle model)

    编译:李琼琼 (山东大学) Stata 连享会: 知乎 | 简书 | 码云 | CSDN Stata连享会   计量专题 || 简书推文   文章目录 背景介绍 1. 双栏模型 (Double-hur ...

  5. 单个Transformer完成信息检索,谷歌用可微搜索索引打败双编码器模型

    选自arXiv 作者:Yi Tay等 机器之心编译 编辑:陈萍 谷歌提出基于 Transformer 的可微文本检索索引,明显优于双编码器模型等强大基线,并且还具有强大的泛化能力,在零样本设置中优于 ...

  6. 构建高可用LVS + keepalived+httpd和双主模型的keepalived方案

    ↑构建高可用LVS + keepalived+httpd和双主模型的keepalived方案↑ 标签:web服务器 拓扑图 模型 检测 软件 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始 ...

  7. linux mysql互为主从_mysql互为主从配置(双主模型)

    一.A.B双主模型的实现条件: 1. 开启二进制日志 2. 开启中继日志 3. 解决自动增长列的问题 如果A服务器上自动增长的列编号有一个35,此时还没有同步到B服务器上,在B服务器上插入一条数据,编 ...

  8. 不等距双杆模型_气体中的变质量模型

    点击蓝字 关注我们 气体中的变质量模型 物理专辑 力学专辑 电学专辑 十年高考真题专辑 物理模型 人船模型 等时圆模型 物理动态图 电表的改装 替代法测电阻 2020物理备考 人拉船模型 物理计算题的 ...

  9. keepalived + haproxy 实现web 双主模型的高可用负载均衡--转

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://xz159065974.blog.51cto.com/8618592/140581 ...

最新文章

  1. PIL库自我学习总结及应用(美白,磨皮,搞笑图片处理)
  2. Knative Service 之流量灰度和版本管理
  3. openstack nova-network 的小bug的排错经历
  4. System.out.println(i++); System.out.println(++i);的区别
  5. 1.4编程基础之逻辑表达式与条件分支 06 判断是否为两位数
  6. 通过埋点搜集日志数据的简单架构
  7. 人工智能实战2019 - 第4次作业(团队后期项目)- 就起这个名字吧
  8. c++内存池作用和优势
  9. Python案例1—人民币与美元的汇率兑换V_8.0
  10. RabbitMQ-启动各种报错,windows环境,RabbitMQPlugin configuration unchanged
  11. 微积分精简版复习提纲
  12. 用python实现成绩录入
  13. win10 apex安装
  14. SpringBoot专栏 | SpringBoot2.x系列教程之花样配置--自定义Banner
  15. 说起刘慈欣,不要只知道《三体》和《流浪地球》
  16. 东八区转为0时区_Java时区转换及时间格式
  17. SpringBoot+Vue项目实现身体健康诊疗系统
  18. 【Git】使用手册02--在本地玩转代码
  19. git 清除所有历史记录
  20. javaUDP网络传输入门

热门文章

  1. AtCoder Beginner Contest 198 A~E题解
  2. 奔驰漏洞事件最终女车主与奔驰达成和解,表面上的内容对双方最为有利
  3. 关于OPC协议解析浅谈
  4. Java基础篇之jdk、jre环境变量的配置
  5. 第二十章:异步和文件I/O.(十七)
  6. r语言对mysql数据分析_R语言:抓取股票数据并存入数据库进行分析实例 MySQL
  7. Unity动画状态机Animator使用
  8. animator 控制移动_Unity 又是一坑之移动AnimatorState
  9. 2018年互联网医疗模式创新案例分析:浙一互联网医院
  10. css设置行间距的三种方法