关闭
您正在使用的浏览器版本较低,无法支持聚宽的某些特性。
为了获得更好的体验,推荐使用:
Google Chrome
或者
Mozilla Firefox
或者
IE9以上
。
返回主题列表
【量化课堂】多因子策略入门
JoinQuant量化课堂
发布于2016-05-21
回复 1390
浏览 454472
2170
listen
分享到:
微信
微博
雪球
**导语:**每一位宽客都相信,影响股票涨跌的因素不胜枚举,而这些“因素”就是因子!本文作为一篇合格的入门教程,提供代码当做框架,各路宽客可以自己测试,查看收益率,亦可利用聚宽python平台自行构建代码。 $ $ ``` 规范源码已更新!请大家克隆研究。 本文由JoinQuant量化课堂推出 。难度标签为进阶上,理解深度标签:level-0 作者: 导数君 编辑: 宏观经济算命师 ``` $ $ ####**因子** 因子是什么?通俗来讲。选股择时,我们得有一个标准对不对?这些标准就叫做因子。比如,我认为营收增长率高的公司就是好公司!那我就把营收增长率大于30%的股票拉出来纳入石榴裙下好了。这个营收增长率大于30%就是因子,完毕。 因子有选股的因子(股票好不好),有择时的因子(好股票什么时候买)。由于择时往往跟技术指标关系紧密,本篇中就介绍基本面类的因子吧,偏财务向。 $ $ ####**选取因子** 最简单的方法,先物色一些自己喜欢的因子,比如增长率啦,市值啦,ROE啦,等等。然后一个个往里面加,看看效果如何,效果好了留下,效果差了删除,反复重复这个过程就能找到心仪的因子啦。 举个例子,小编先选两个因子,ROA和净利润/营业总收入(%)。ROA和利润率比较高的一般都是表现良好的公司,所以小编决定选取ROA和净利润/营业总收入前20名的股票买入,回测结果如下图所示: ![1.png][1] 表现比大盘略好一点,11年的收益有3.98倍。那换个因子试试?小编把净利润/营业总收入换成净利润环比增长率(%),回测结果如下图所示: ![2.png][2] 然后发现收益率好了一点点,过去11年的收益有7.54倍。嗯,比刚才高了一些。如果我们把这三个因子都加进去会怎样呢? ![3.png][3] 收益率为5.34倍,没有刚才那么好了,还是刚才的ROA和净利润环比增长率(%)这两个因子比较好,那就保留两个吧。小编听说小市值股票收益好,如果把市值这个因子也加进去会怎么样呢?回测了一下,发现: ![4.png][4] 收益居然有28倍!真的是太不可思议了。 所以话说回来,虽然这种试错法选因子是一种比较基础的选因子方式,但其实还挺有用。经过反复试错,小编发现小市值和ROE高的股票收益比较高,回测结果显示,收益可以达到42倍之多! ![5.png][5] 是不是很惊艳!你可以直接编程构建代码,也可以用我们的代码当做框架。总之,可以自己测试一下,看看收益会不会爆表。 作为一篇合格的教程,我们接下来看看代码是如何实现的: $ $ ####**编写代码的一些问题** 首先,财务面的数据有个问题,就是有些数据是不可获得的,这样的话对排序的影响比较大,因此涉及到一个清洗数据的步骤。一个很简单的办法就是用均值来填充,这个在Python的pandas库里面有个现成的函数,大家可以尝试使用里面的均值填充法。小编自己也写了一个填充均值的函数,大家也可以参考一下源码。 不过随着深入的研究,可能会发现用均值填充并不是一个完美的方法。这里小编再提供一个思路,大家感兴趣可以自己实现:如果某只股票这一期的某个财务数据空缺,但是上一期没有,我们可以根据该股票这个数据与上一期的平均值比例来确定。用公式说可能更清晰点: 空缺数值=本期该字段平均值*上期该字段数值/上期该字段平均值。 其次,我们对因子的单位要做一个统一。因为有的因子绝对值好几十亿(比如市值),有的可能只有十几(收益率)甚至是负的,因此因子和因子之间很难直接赋予权重进行计算。因此,我们可以考虑使用排名的方法,对这些因子进行排名。 Python自带有一个sort函数,不过为了练手起见,小编自己写了一个。用的是最简单的冒泡排序算法,高手也可以试一下堆排序或者归并排序以加快回测的速度。 最后,我们将上述功能汇总成一个函数,集中取数据-清洗数据。 有了以上的几个子函数,写主函数就很方便了,各位宽粉们赶紧尝试吧! $ $ ####**小结** 我们这篇文章主要介绍了如何通过财务数据来构建一个多因子的策略。由于是入门向,我们构建多因子的方法比较简单,选取的因子依据是主观分析 排名。 如果想定量的分析,主流的方法是做回归分析,或者对各个因子进行打分,这些将会在进阶的量化课堂中有所介绍。如果还有其他的方法,当然也欢迎尝试。 $ $ ![多因子策略入门_函数说明.png][6] ``` 本文由JoinQuant量化课堂推出,版权归JoinQuant所有,商业转载请联系我们获得授权,非商业转载请注明出处。 文章更迭记录: v3.0,2018-12-15,修正卖出,感谢 DL 指出 v2.1,2016-07-25,修正文字,感谢 liuzehong 指出 v2.0,2016-07-16,更新为规范源码,添加“函数说明书” v1.1,2016-07-04,添加“导语” v1.0,2016-05-21,文章上线 ``` [1]: https://image.joinquant.com/6b8e42bc5e87f082d531cb46a67293a2 [2]: https://image.joinquant.com/7441b1505390ffb165b68a27feff2805 [3]: https://image.joinquant.com/3754416ce49a0feeec7829b0cb240348 [4]: https://image.joinquant.com/37400e6a85f49d2e9445d6c6ecb8de14 [5]: https://image.joinquant.com/b576ccb1ced6b426c1b447dc72101744 [6]: https://image.joinquant.com/34dbdedd80333d56da44ec1a8c20f398
2170
listen
分享到:
微信
微博
雪球
评论
richard_lzy
说的太小白啦。。。希望能示例一下诸如怎么取权重之类的,谢谢!
2016-05-22
选项未来导数
@richard_lzy 这个本来就是小白版教程。。权重嘛。。比如回归法,adaboost法,人工YY法等。。这个以后高阶教程可能会有
2016-05-23
朱铭
@richard_lzy 目前是偏入门的,后续会继续推出高阶教程的~~
2016-05-23
选民
看不懂
2016-05-30
朱铭
@选民 不急,量化有一点门槛,一周左右就能入门,先看下量化课堂吧 https://www.joinquant.com/study
2016-05-30
朱铭
@选民 哪里有问题呢
2016-05-31
rogery
points=np.dot(a,g.weights) 怎么理解? dot 是个函数吗?为什么在API文档里找不到?
2016-06-20
eterne
@rogery dot是矩阵乘法,numpy中的
2016-06-21
porfavor
这个算法,我把中间结果打印出来,看了下,不明白怎么转换的,能解释下吗? 000001.XSHE, 000002.XSHE 市值,roe取值对应 [[1830.27, 4.71], [1645.6899000000001, 2.1200000000000001] 经过 fillNan(res) getRank(res) 处理后,就变成 [[19, 41], [21, 129], 回测时间设置是2015-01-01 不是太明白中间的转换,看起来只是经过了填值和排序
2016-06-21
rogery
@eterne 多谢指点
2016-06-27
宏观经济占卜师
@porfavor 问题在哪?
2016-06-27
porfavor
@宏观经济占卜师 [[1830.27, 4.71], [1645.6899000000001, 2.1200000000000001] 怎么转换为[[19, 41], [21, 129],的?
2016-07-01
宏观经济占卜师
@porfavor 是不是转换成在股票池里的排名啦?
2016-07-01
porfavor
@宏观经济占卜师 应该不是吧,这两组数据是对应的,就是股票池最前面两个数据。这样说吧,这个问题相当于,股票市值比如1830.27亿,和ROE比如4.71。不在一个数量级上,好象算法是先转化之后,再乘以矩阵[[1],[-1]],然后再排序吧。就是这个转化,没太看懂呢,想请教下
2016-07-01
宏观经济占卜师
@porfavor 我觉得它干了这么一件事:“股票市值比如1830.27亿,和ROE比如4.71” 经过转换,就告诉你,这个股票的市值在股票池里排名 第19,Roe 第41 我觉得这个以后得优化一下,变成常用代码块
2016-07-01
porfavor
@宏观经济占卜师 哦,原来,谢谢你的答复。我把想复杂了:)
2016-07-01
liuzehong
“我认为营收增长率公司就是好公司” 这句话少了一个“高”字吧
2016-07-25
宏观经济占卜师
@liuzehong 恩,谢谢指出,到时候改一下
2016-07-25
JoinQuant量化课堂
@liuzehong 已改,感谢。
2016-07-25
stack
我看不明白这一行代码 suspened_info_df = get_price(list(stock_list), start_date=context.current_dt, end_date=context.current_dt, frequency='daily', fields='paused')['paused'].T 这行代码中的fields='paused')['paused'].T是什么意思?求解答
2016-07-28
首页
上一页
1
2
3
4
5
6
7
8
9
10
下一页
尾页
您尚未登录,请
登录
或者
注册
聚宽发表回复。
取 消
提 交