量化选股——基于动量因子的行业风格轮动策略(第2部分—策略回测)
文章目录
- 1. 交易策略
- 2. Backtrader回测程序
- 3. 回测效果
- 3.1 2020年1月1日 - 2021年1月1日
- 3.2 2021年1月1日 — 2022年1月1日
- 3.3 2022年1月1日 — 2023年1月1日
动量因子的概述与测算,阿隆指标测算请参考:https://blog.csdn.net/weixin_35757704/article/details/128767040
1. 交易策略
阿隆动量因子策略构建:
- 相同权重,满仓持有5个指数;每卖出1个或多个指数后,都会等权重用现金买入指数,始终保持5个指数的持仓
- 买入:AroonDown+AroonUp>50,且当AroonUp > AroonDown时买入
- 卖出:AroonDown+AroonUp>50,且当AroonDown > AroonUp时卖出
- 买入时:
- 计算【aroon差额】= AroonUp-AroonDown;得到上涨与下跌动量的差额
- 每个指数按照 aroon差额 从大到小的顺序排序;为了买入上涨动量最强,且下跌动量最弱的指数
- 如果多个指数的aroon差额值相同,则按照15年到20年测算的胜率高低,按照历史测算时综合胜率的先后关系排序
- 然后从上到下依次买入指数,最终保持始终持仓5个指数
以 1/1000 作为摩擦成本,不计算管理费
2. Backtrader回测程序
这里我们使用backtrader回测框架,回测的内容除了在 量化策略——准备3 数据、Backtrader回测框架与quantstats评价指标 中提供的一些方法外,核心的策略代码如下:
class AroonStrategy(TemplateStrategy):params = (("start_date", None), ('end_date', None),)def __init__(self):super().__init__()# 基本配置self.max_hold = 5self.this_month = self.params.start_date.monthtotal_bond_code = []for this_data in self.datas:if type(this_data).__name__ == "StockData":total_bond_code.append(this_data._name)self.total_bond_code = total_bond_codeself.vic_dict = {'801210.SI': 0, '801110.SI': 1, '801750.SI': 2, '801120.SI': 3, '801890.SI': 4, '801080.SI': 5,'801200.SI': 6, '801140.SI': 7, '801160.SI': 8, '801730.SI': 9, '801010.SI': 10,'801130.SI': 11, '801760.SI': 12, '801770.SI': 13, '801050.SI': 14, '801040.SI': 15,'801180.SI': 16, '801720.SI': 17, '801710.SI': 18, '801030.SI': 19, '801880.SI': 20,'801170.SI': 21, '801790.SI': 22, '801150.SI': 23, '801230.SI': 24, '801740.SI': 25,'801950.SI': 26, '801780.SI': 27}def next(self):"""最核心的触发策略"""hold_bond_name = [_p._name for _p in self.broker.positions if self.broker.getposition(_p).size > 0] # 查看持仓# 计算指标_candidate_dict = {}for _candidate_code in self.total_bond_code:_candidate_dict[_candidate_code] = {"aroondown": self.getdatabyname(_candidate_code).aroondown[0],"aroonup": self.getdatabyname(_candidate_code).aroonup[0],}candidate_df = pd.DataFrame(_candidate_dict).Tcandidate_df['aroo_energy'] = candidate_df['aroondown'] + candidate_df['aroonup']candidate_df['aroo_mines'] = candidate_df['aroonup'] - candidate_df['aroondown']candidate_df = pd.merge(candidate_df, pd.DataFrame(self.vic_dict, index=['rank']).T,left_index=True, right_index=True)candidate_df = candidate_df.sort_values(['aroo_mines', "rank"], ascending=[False, True])if candidate_df['aroo_energy'].sum() == 0:returnif len(hold_bond_name) < self.max_hold:self.get_buy_bond(candidate_df, self.max_hold - len(hold_bond_name))# 卖出的逻辑for _index, _series in candidate_df.iterrows():if _index in hold_bond_name:if _series['aroonup'] < _series['aroondown']:self.sell(data=_index, size=self.getpositionbyname(_index).size,valid=self.getdatabyname(_index).datetime.date(1))def get_buy_bond(self, candidate_df, buy_num):hold_bond_name = [_p._name for _p in self.broker.positions if self.broker.getposition(_p).size > 0]for index, series in candidate_df.iterrows():if series["aroo_energy"] <= 50: # 当 AroonDown + AroonUp > 50时才执行判操作continueif index in hold_bond_name:continuebuy_data = self.getdatabyname(index)if len(buy_data) >= buy_data.buflen():continueif series['aroonup'] > series['aroondown']:buy_cost_value = self.broker.getcash() / (self.max_hold - len(hold_bond_name)) * (1 - self.broker.comminfo[None].p.commission)buy_size = buy_cost_value / self.getdatabyname(index).close[0]self.buy(data=buy_data, size=buy_size, exectype=bt.Order.Limit,price=buy_data.close[0],valid=buy_data.datetime.date(1))logger.debug("买入 {} size:{} 预计费用:{}".format(index, buy_size, buy_cost_value))buy_num -= 1if buy_num == 0:breakdef stop(self):# 绘制净值曲线wealth_curve_data = {}for _k, _v in self.value_record.items():wealth_curve_data[_k] = _v / self.broker.startingcashself.plot_wealth_curve(wealth_curve_data, "arron_{}_{}".format(self.params.start_date.strftime("%Y-%m-%d"), self.params.end_date.strftime("%Y-%m-%d")))# 最终结果daily_return = cal_daily_return(pd.Series(self.value_record))_, record_dict = cal_rolling_feature(daily_return)print(record_dict)print('a')
在策略中,当【aroon差额】相同时,按照测算的胜率从大到小依次买入,下面的字典便是每个行业指数胜率从大到小的排名,用于辅助排序:
{'801210.SI': 0, '801110.SI': 1, '801750.SI': 2, '801120.SI': 3, '801890.SI': 4, '801080.SI': 5,'801200.SI': 6, '801140.SI': 7, '801160.SI': 8, '801730.SI': 9, '801010.SI': 10,'801130.SI': 11, '801760.SI': 12, '801770.SI': 13, '801050.SI': 14, '801040.SI': 15,'801180.SI': 16, '801720.SI': 17, '801710.SI': 18, '801030.SI': 19, '801880.SI': 20,'801170.SI': 21, '801790.SI': 22, '801150.SI': 23, '801230.SI': 24, '801740.SI': 25,'801950.SI': 26, '801780.SI': 27}
3. 回测效果
3.1 2020年1月1日 - 2021年1月1日
- 最终净值:1.21
- 复合年增长: 0.226
- 夏普比率: 0.885
- 索蒂诺: 1.167
- omega: 1.175
- 最大回撤: -0.173
- 年波动率: 0.253
3.2 2021年1月1日 — 2022年1月1日
- 最终净值:0.909
- 复合年增长: -0.092
- 夏普比率: -0.481
- 索蒂诺: -0.663
- omega: 0.924
- 最大回撤: -0.191
- 年波动率: 0.205
3.3 2022年1月1日 — 2023年1月1日
- 最终净值:0.74
- 复合年增长: -0.255
- 夏普比率: -1.681
- 索蒂诺: -2.073
- omega: 0.741
- 最大回撤: -0.258
- 年波动率: 0.186
量化选股——基于动量因子的行业风格轮动策略(第2部分—策略回测)相关推荐
- 量化选股——基于动量因子的行业风格轮动策略(第1部分—因子测算)
文章目录 动量因子与行业轮动概述 动量因子的理解 投资视角下的行业轮动现象 投资者视角与奈特不确定性 动量因子在行业风格上的效果测算 动量因子效果测算流程概述 1. 行业选择:申万一级行业 2. 动量 ...
- 西蒙斯都在用的量化选股策略——风格轮动模型
阅读原文:京东量化平台-为投资者提供数据支持.策略开发到策略输出的量化生态服务 京东金融官方资讯QQ:3414182370 有什么想问的想说的都可以来参与!还有机会获取奖品! 市场上的投资者是有偏好的 ...
- xstream 数字映射不上去_基于股票因子映射的行业轮动方法
首发于 优矿金工 2020-06-22 A. 研究目的:本文基于优矿提供的因子数据构建个股因子并探索将个股因子映射到行业构建行业轮动模型的方法,文中部分方法参考光大证券<基于股票因子映射的行业轮 ...
- 股债轮动、股票指数间轮动和行业间轮动的一种新思路:GEYR策略
前言 GEYR一般定义为长期国债收益率与证券市场股利收益率的比值,可用于股债配置.当该值增大时,债券配置价值较高:反之则股票配置价值较高.GEYR策略的本质思想在于将标的资产视为零息债券,并对票息进行 ...
- 量化选股——基于多因子模型的量化策略(第1部分—因子测算策略构建)
文章目录 1.多因子模型概述 2.因子挖掘 3.多因子策略 4.多因子策略构建 基于多因子的策略通用流程 Fama-French三因子 因子效果测算方法 因子测算结论&量化策略构建 东西有点多 ...
- 量化选股模型—动量反转模型
A股市场存在显著的动量及反转效应,按照形成期为6个月持有期为9个月的动量策略以及形成期为2个月持有期为1个月的反转策略构建的投资组合表现最佳.从不同的市场阶段看,动量策略在熊市阶段表现优异,而反转策略 ...
- Python量化交易05——基于多因子选择和选股策略(随机森林,LGBM)
参考书目:深入浅出Python量化交易实战 在机器学习里面的X叫做特征变量,在统计学里面叫做协变量也叫自变量,在量化投资里面则叫做因子,所谓多因子就是有很多的特征变量. 本次带来的就是多因子模型,并且 ...
- python量化选股策略_【机器学习】第六课:基于SVM的量化选股策略
导语 接触过机器学习或数据挖掘算法的人都应该知道支持向量机(SVM),支持向量机一经提出就得到了广泛应用.本文主要探讨该算法在金融领域量化投资多因子策略上的应用.在这篇文章中,先是介绍了SVM的基本原 ...
- 量化选股策略模型大全
原文链接:原文 量化选股就是利用数量化的方法选择股票组合,期望该股票组合能够获得超越基准收益率的投资行为.量化选股策略总的来说可以分为两类:第一类是基本面选股,第二类是市场行为选股. 基本面选股主要有 ...
最新文章
- return error怎么定义_自定义一个注解校验接口参数
- golang中的strings.Contains
- CentOS 7系统启动后怎么从命令行模式切换到图形界面模式
- 遍历文件夹_使用JavaScript遍历本地文件夹的文件
- MySQL主从复制(Centos6.3MySQL5.6)
- Struts2学习笔记《二》
- Android 系统(75)---Android常用的网路框架
- python 一些练习 (初学)
- 左连接与右连接的区别
- 【优化算法】符号LMS算法【含Matlab源码 697期】
- 飞客蠕虫(Conficker)
- ubuntu内部错误
- 最小二乘估计与卡尔曼滤波公式推导
- frp内网穿透(Mac远程连接公司windows)
- 【报告分享】数观食机|2020快手食品行业数据价值报告-磁力引擎-202103.pdf(附下载地址)
- [Java]打印数组的三种方式
- SSM实训:11、页面插件集成
- git pull 技巧
- solidworks渲染材质库_solidworks渲染材质参数
- 嵌入式系统——复杂指令集系统与精简指令集系统(CISCRISC)