本文设计了一个能长期跑赢沪深300指数的screen。并通过回测观察了该screen在不同市场环境下的表现。对基于价值的股票投资有一定的指导意义。
量化的第一步通常是确定投资标的池,面对几千只股票,通过初步的筛选,哪些是符合标准并进入池子中。这步工作不太可能人工完成,因为数量实在太大。那么,接下来一个问题的我该如何设计一个screening?这就涉及到你的投资风格问题了,通常来说,有如下这些风格:
- 价值股投资;格雷厄姆,巴菲特都是祖师爷。
- 成长股投资;贵有贵的道理。。。
- 趋势投资;顺势而为。
- 逆向投资;人弃我取。
- 跟投;别人投啥我投啥,比如跟踪外资策略。
- 。。。
我比较认同价值投资,因此就基于价值投资的理念,设计一个screening。顺便扯一下题外话,买P/E是100倍的股票未必就不是价值投资。价值投资的本质上还是看买入的价格是否低于内在价值,言归正传。既然目标是做一个价值投资的screen,那就来明确一下该目标背后的含义。我希望通过该screen,找到被错误定价的公司,即被低估的公司,价格便宜,但没有明显的负面因素造成这种低估,例如高风险,低增长,或低质量的增长(需要很高的资本投入等)。换句话说,我希望找到一组股票,在低价格乘数(multiples)区间交易(e.g.低P/E),公司风险低,有高的增长,并且增长的质量好。这么写出来是不是觉得在做梦啊?!Too good to be true!这就对了,凭啥赚钱那么容易?!你都觉得不可能了说明市场其实在大部分时间还是有效的!但是,虽然觉得概率低,试着找找看这样的股票也没啥坏处,指不定就真在地上找到了皮夹子。
Screen 维度
接下来我就从下面几个维度开始设计screening:
- 价格
- 风险
- 成长性
- 成长质量
Screen for price
衡量价格一般用价格乘数,相关指标有很多,最常用的P/E,P/B。需要指出一个大原则,如下图所示:
即分子与分母从财务角度必须一致,如果分子是equity value,那分母也必须是equity value。同样,如果分子是enterprise value,那分母也必须是enterprise value。举例来说,P/E 是满足一致性要求的,P(price)是equity value,E(earning, net income)也是equity value。
由于不同行业有其自身的特征,比如有些行业杠杆率高,为了实现跨行业的可比性,我使用enterprise value 乘数: EV / EBIT。其中:
- EV = enterprise value = market value of equity + interest-bearing debt - cash
- EBIT,息税前利润。
有了价格乘数,那么接下来一个问题是:如何算是便宜?可以有两种方式:
- 绝对,设定一个具体的EV / EBIT 标准,超过了就算贵。
- 相对,对所有股票EV / EBIT 进行排序,设定一个百分比,比如top 33% 算贵。
我倾向使用相对方式进行screening。因为,格雷厄姆时代的标准放到今天可能就找不到股票了。
Screen for risk
Risk 可以分为:
- Operating risk,主要是从公司经营角度出发,影响营收或公司正常用作的风险
- Financial risk, 从财务角度出发,例如债务
- Liquidity risk,主要从股票持有人变现角度出发,如买卖spread,公司停牌之类
对于设计Screen来说,一般比较容易做的是:
- 基于价格:如股票的beta,或是standard deviation for returns。
- 基于会计:根据财务报表上的数据进行分析,例如公司偿债能力。
从债务杠杆出发,选用book debt-to-equity ratio作为风险度量。当然,并非说债务高就一定不好。但是,“这个世界上没有无缘无故的狠”,便宜的股票通常在财务上面临压力,因此,在此前提下,债务越低越安全。之所以没有使用market value来计算debt-to-equity ratio是因为market value of equity其实是price的一种度量,而EV / EBIT已经度量了价格。
除了考虑债务杠杆的绝对值,在加入债务杠杆的变化:
Change in book D/E = Current year’s D/E - prior year’s D/E
收入容易被操控,因此是一个需要小心的地方。如果net income大于cash flow from operatinos,那么就有可能是一个不好的信号。使用以下指标:
ACCRUAL = (NI-CFO)/TA
其中:
- NI = net income before extraordinary items
- CFO = cash flow from operations
- TA = total assets
Screen for growth
对于增长我没有太多好的想法,使用一致性预期应该是一个不错的选择,但是,并非每只股票都有一致性预期,尤其是不受待见的问题股票。因此,我就简单用Revenue growth了:
Revenue growth = Current year’s Revenue / Prior years’s Revenue - 1
这里,我还想加入一个技术指标用来表示增长:Momentum,使用3个月的股票价格的return:
M3M = 3-Month price change
Screen for quality of growth
我希望入围的公司不光有增长,而且增长的质量比较高。比如,不用靠很高的资本支出。对于这个Screen,我使用return on invested capital (ROIC)。
ROIC = EBIT(1-t) / (Book value of equity + book value of debt - cash)
进一步,不光考虑ROIC的绝对水平,还进一步考虑ROIC的变化:
Change in ROIC = Current year’s ROIC - prior year’s ROIC
总结一下,我用了一下这些条件对股票进行过滤:
- Price
- EV / EBIT
- Risk
- book debt-to-equity ratio
- Change in book D/E
- ACCRUAL = (NI-CFO)/TA
- Growth
- Revenue growth
- M3M = 3-Month price change
- Quality
- ROIC
- Change in ROIC
一共8个过滤条件。
两种不同的过滤方式
如何使用这8个条件进行筛选并获得目标股票池?一种方式是顺序过滤。根据重要性将条件排序。比如,我觉得股票是否便宜是最重要的,那么就将EV / EBIT排在第一位,用这个条件将所有股票进行排序,然后选择top 50%,然后接下来再用次重要的条件对入围的股票再进行排序,依次完成所有的条件。但是,这么做有几个问题:
- 如果某两个或多个条件具有相同的重要性,你必须给定一个顺序,这样造成的结果就是会过滤掉你希望保留的股票。
- 最后可能没有满足条件的股票,或结果集的数量太少了。
为了解决以上问题,可以使用多条件并行过滤(simultaneous screening)的方法:
- 首先将每个条件的值进行标准化处理 — Z-Score
- 将各个条件的z-score值按照一定的权重加总
- 根据加总后值进行排序,获得过滤结果
这里需要注意的地方是:
- 对条件值进行标准化处理可以有多种方法,我选用z-score。这步是必须的,否则不同的条件值之间的数量级会有很大的差别。汇总后,那些值很大的条件就会对结果产生更大的影响
- 不同条件z-score的方向应该有相同的影响。比如,z-score大,代表有正面影响,反之则有负面影响
模型实现
到了这步就要拿出我码农的本色!开始撸数据,写代码。目标就是计算出每只股票在对应条件上的z-score。其实,最大的挑战还是数据,包括获取数据,清理数据以及处理outlier。具体细节没必要放在这里(此处省略240行代码。。。)。我主要做以下工作:
- 工具方面,基本就是python了,利用numpy,pandas来存储加工数据
- 数据利用的是ricequant平台,不得不说,他们在数据的二次加工上做的挺完善,基本上你想要的股票基本面数据他们都提供了。这就极大简化了数据处理的工作,至于数据是否准确,还需要观察一段时间
- 扫描全部A股。确保股票至少上市3年才进入我的筛选范围
- 对于EBIT < 0的股票不考虑,虽说EBIT < 0不代表这支股票不好,但是,由于我这里的策略还是基于value,而EBIT < 0 的股票有可能是成长型公司,或是公司经营出了问题。另外,如果EBIT < 0,那么EV / EBIT就变得没有意义
- 对于outlier,我的定义是z-score > 3 或 z-score < -3,发现outlier,我并不是简单做删除处理,而是将outlier设置成3或-3
- 剔除了所有的金融股票,包括银行和非银,原因很简单,你很难定义什么是他们的debt,就更不用说interesting bearing debt了,那该怎么计算他们的debt to equity ratio呢?
下图所示是数据处理完的结果:
上半部分cleaned_df是所有股票的条件值的计算结果,下半部分则是将其转化成了z-score。至此z-score都已计算完成。
z-score权重
有了各个条件上z-core,那么接下来我需要加总求和。如何求和?也就是每个条件上z-score对应的权重是多少?这个权重该如何确定?
最简单的方法:等权重求和了!虽说是简单粗暴,但是,等权重也是有一个明显的好处,那就避免了overfitting!因此是一个不错的benchmark,以后对z-score权重的优化都可以同这个等权重benchmark做比较。再强调一下,每个条件上的z-score在求和的时候必须保证同方向,因此求和操作应如下:
SUM of Z-Score =
- minus EV / EBIT
- minus book debt-to-equity ratio
- minus Change in book D/E
- minus (NI-CFO)/TA
- plus Revenue growth
- plus M3M
- plus ROIC
- plus Change in ROIC
下表显示了排名前50的股票:
label | z_score_sum | symbol | industry_code | industry_name |
---|---|---|---|---|
300677.XSHE | 10.716210 | 英科医疗 | C29 | 橡胶和塑料制品业 |
002869.XSHE | 7.475962 | 金溢科技 | C39 | 计算机、通信和其他电子设备制造业 |
600421.XSHG | 7.123312 | ST仰帆 | C34 | 通用设备制造业 |
002164.XSHE | 7.034439 | 宁波东力 | C35 | 专用设备制造业 |
601020.XSHG | 6.866158 | 华钰矿业 | B09 | 有色金属矿采选业 |
002838.XSHE | 6.495545 | 道恩股份 | C29 | 橡胶和塑料制品业 |
300552.XSHE | 6.002087 | 万集科技 | I65 | 软件和信息技术服务业 |
002124.XSHE | 5.956577 | 天邦股份 | C13 | 农副食品加工业 |
603606.XSHG | 5.861706 | 东方电缆 | C38 | 电气机械和器材制造业 |
002289.XSHE | 5.485774 | ST宇顺 | C39 | 计算机、通信和其他电子设备制造业 |
000048.XSHE | 5.417372 | 京基智农 | C13 | 农副食品加工业 |
002286.XSHE | 5.285237 | 保龄宝 | C13 | 农副食品加工业 |
300464.XSHE | 4.960576 | 星徽精密 | F52 | 零售业 |
603129.XSHG | 4.847436 | 春风动力 | C37 | 铁路、船舶、航空航天和其他运输设备制造业 |
300056.XSHE | 4.837722 | 中创环保 | C35 | 专用设备制造业 |
600652.XSHG | 4.782898 | ST游久 | I64 | 互联网和相关服务 |
002216.XSHE | 4.725449 | 三全食品 | C14 | 食品制造业 |
300246.XSHE | 4.653786 | 宝莱特 | C35 | 专用设备制造业 |
002714.XSHE | 4.440177 | 牧原股份 | A03 | 畜牧业 |
600132.XSHG | 4.402648 | 重庆啤酒 | C15 | 酒、饮料和精制茶制造业 |
002030.XSHE | 4.378498 | 达安基因 | C27 | 医药制造业 |
300274.XSHE | 4.367707 | 阳光电源 | C38 | 电气机械和器材制造业 |
002555.XSHE | 4.361072 | 三七互娱 | I64 | 互联网和相关服务 |
002677.XSHE | 4.335123 | 浙江美大 | C38 | 电气机械和器材制造业 |
300103.XSHE | 4.327513 | 达刚控股 | N77 | 生态保护和环境治理业 |
002312.XSHE | 4.320156 | 三泰控股 | C26 | 化学原料及化学制品制造业 |
601633.XSHG | 4.311244 | 长城汽车 | C36 | 汽车制造业 |
300225.XSHE | 4.307500 | 金力泰 | C26 | 化学原料及化学制品制造业 |
300676.XSHE | 4.304628 | 华大基因 | M74 | 专业技术服务业 |
603416.XSHG | 4.267281 | 信捷电气 | C40 | 仪器仪表制造业 |
603338.XSHG | 4.231131 | 浙江鼎力 | C35 | 专用设备制造业 |
300435.XSHE | 4.172462 | 中泰股份 | D45 | 燃气生产和供应业 |
603906.XSHG | 4.095128 | 龙蟠科技 | C26 | 化学原料及化学制品制造业 |
002285.XSHE | 4.074116 | 世联行 | K70 | 房地产业 |
300411.XSHE | 4.064889 | 金盾股份 | C34 | 通用设备制造业 |
000913.XSHE | 4.055015 | 钱江摩托 | C37 | 铁路、船舶、航空航天和其他运输设备制造业 |
002735.XSHE | 4.049436 | 王子新材 | C29 | 橡胶和塑料制品业 |
603877.XSHG | 3.998039 | 太平鸟 | C18 | 纺织服装、服饰业 |
601216.XSHG | 3.992290 | 君正集团 | C26 | 化学原料及化学制品制造业 |
002706.XSHE | 3.991975 | 良信电器 | C38 | 电气机械和器材制造业 |
603787.XSHG | 3.990077 | 新日股份 | C37 | 铁路、船舶、航空航天和其他运输设备制造业 |
000897.XSHE | 3.988275 | 津滨发展 | K70 | 房地产业 |
601012.XSHG | 3.951803 | 隆基股份 | C30 | 非金属矿物制品业 |
603960.XSHG | 3.926110 | 克来机电 | C35 | 专用设备制造业 |
002730.XSHE | 3.869764 | 电光科技 | C35 | 专用设备制造业 |
002569.XSHE | 3.842822 | ST步森 | C18 | 纺织服装、服饰业 |
601069.XSHG | 3.841323 | 西部黄金 | B09 | 有色金属矿采选业 |
002568.XSHE | 3.825067 | 百润股份 | C15 | 酒、饮料和精制茶制造业 |
300405.XSHE | 3.803350 | 科隆股份 | C26 | 化学原料及化学制品制造业 |
002833.XSHE | 3.783292 | 弘亚数控 | C35 | 专用设备制造业 |
新鲜出炉啊~~~这是根据2020年Q3财报产生的结果。
回测
回测其实更为繁琐,借助RQAlpha框架,真的是极大的降低了工作量(此处又省略了296行代码。。。)。在本篇中,我只用最简单粗暴的方式进行回测,不做任何的优化。说一下我在回测过程中做了哪些处理:
- 在构建portfolio时,直接用aggregate z-score为top 50的股票;也就是说没有太多考虑分散投资,在下一篇,我会根据行业构建一个相对分散投资的portfolio。
- 使用等权重资金投资到每个股票,也就是说,有50只股票,将资金等分成50份,每份投资一只股票。如果以后做优化的话,可以考虑risk parity方法,或根据每只股票的预期收益,做MVO。我觉得sharpe ratio应该是可以提高不少。
- 在回测的过程中考虑forward looking bias。由于国内财报的披露时间为:
- 1季报:每年4月1日——4月30日。
- 2季报(中报):每年7月1日——8月31日。
- 3季报: 每年10月1日——10月31日
因此我在回测的过程中,定义获取财报的时间分别为: - 1季报:4月30日以后的第一个交易日。
- 2季报(中报):8月31日以后的第一个交易日。
- 3季报: 10月31日以后的第一个交易日。
- 每年做3次rebalance,分别对应以上三个财报季。rebalance方式也是简单粗暴,第一步全部卖出,第二步再以等权重方式买入新入围的50只股票。因此将来,这步也是有很多的优化可以做。
- 考虑了survival bias,比如,我从2015年6月12日开始回测,那我会以当时股票市场的全部股票作为我的pool,并以此进行screening(而非今天市场上的全部股票)。而当时的股票到今天可能已经退市了!因此用这种方式进行回测能避免survival bias。
下面上结果,我先用2年时长进行回测(2018-9-25到2020-9-25):
- 基准是沪深300指数
- 深红色是screen的净值曲线,蓝色是基准,黄色是超额收益
- 2年的周期最后是跑赢了基准!但是,有超过1年多的时间是落后基准,这里想表达的意思是,使用这个screen(包括其他策略)需要有一个相对长期的预期,不能期望时时刻刻都能跑赢基准
- 整体来说和沪深300的相关性很高,beta=0.9。screen的收益是46.66%,基准的收益是33.734%。作为未经任何优化的screen能取得这样的结果还是有点出乎我的意料
然后,我想看看2015年股灾后的表现,用了一个很极端的场景:从2015-6-12开始回测,也就是从股灾的顶点开始,一直到2020-9-25。我想看看,这个策略在股灾巨幅下跌时的表现,以及需要多久能重新回到原点。如下图所示:
- 首先这段回测超过5年。从刚开始那段暴跌看,似乎screen也没有表现出抗跌的特点,但有意思的是,在其后的反弹过程中大幅跑赢了基准
- 最终的结果看screen不仅收复了所有的下跌,还获得了7.288%的收益,而沪深300还亏损了13.88%!其实不能觉得5年多才7.288%,要知道这是很极端的情况,也就是你在泡沫的顶点开始投资!因此对screen的表现也觉得挺不错!
- 还有一点比较有意思,就是沪深300代表的大盘股从2016年2月开始稳步上涨一直到2018年1月,而screen在这段时间一直没有表现,甚至在行情结束时被反超。因此,要坚持策略也需要有个强大的内心!
- 这里beta只有0.8,我觉得是一个好现象,长期来看同沪深300的相关性变低了
聊一聊下一步打算,我会对这个screen做进一步的优化:
- 在计算aggregate z-score时,不是简单粗暴的使用等权重
- 在构建portfolio时,不是简单的选择aggregate z-score为top n的那些股票,而是考虑如何做好分散。因为排在前面的股票可能会集中在某几个行业,这样,你的portfolio就太集中了
- 对screen做一些风格方面的调整,比如,我就想追求绝对便宜,那么可以试一下先根据 EV / EBIT 剔除掉最贵的50%的股票,然后在余下的50%里面做aggregate z-score
- rebalance时是否需要将股票全部换掉?可以考虑每次换出aggregate z-score最低的几只股票,并补充新的高分股票等等。。。
这些测试我将放在下一篇。感觉本篇内容足够干货了! 等以上优化完成以后,我打算在雪球上以此建一个portfolio,作为benchmark长期跟踪,并能分享给有兴趣的朋友。
总结
最后,想谈谈使用各种类型的screen是否能击败市场获取超额收益。从经验上看是存在这个可能的,比如本文的screen,还有如Joel Greenblatt的神奇公式(更简单)长期也能跑赢SP500。但是,光是这样的跑赢是否足够,我们是否可以要求的更多?我比较认同Damodaran的观点,他认为作为一个投资者,你必须得有一些独特的东西(核心竞争力)才能在这个市场上获得超额收益。换句话说,就好像我们看公司会看它是不是有护城河,那么作为个人投资者,你需要考虑你的竞争优势在哪里。当格雷厄姆在1951年使用screen时,screen可以看作是一种竞争优势,因为:
- 首先,要做一个screen在当时并不容易。那个时代,要获取大量公司的财报,并且还得有自动化的工具来分析数据,对于普通投资者来说是一件相当难的事情,只有极少数实力强悍的投资者才具备这样的能力。
- 其次,是纪律性,投资者必须让自己远离各种诱惑和潮流,并始终如一的关注screen产生的股票。
- 第三,是耐心,投资者必须长期持有screen产生的股票才能获得理想的收益(这同本文的回测结果是相符的)
今天,人们有各种途径获得股票数据,还有无数的分析工具。因此第一种优势几乎不存在了,(这里我想多说一句,在这一点上我不太认同,个人感觉,第一种优势在当今可能还是发挥着比较关键的作用,因为高质量的数据通常不会免费,所以仅此一点,就挡住了绝大部分的散户。其次是技术的使用,有多少投资人懂得python,甚至能熟练使用excel?)那么就剩下纪律和耐心作为你潜在的竞争优势。可以说,自动化的screening以及投资流程可以做到不需要人工介入,因此,这样一套系统从受到情绪化影响的角度来看,即使同最有纪律性且耐心的人来比,也明显胜出一大截!更直白的说,作为一个主动投资者,如果说所有你能拿得出手的东西仅仅是screen,那你基本不太可能打败机器。除了用screen武装自己外,你是否能赚到钱还取决于你在screen之后所做工作的质量。如果你在分析股票内在价值或定性研究方面有所专长,你也许能获取更高超额收益。
参考文献:
- Joseph D. Piotroski. Value Investing: The use of historical financial statement information to separate winners from losers. Journal of accounting Research Vol. 38 Supplement 2000
- Ludwig B. Chincarini, Daehwan Kim. Quantitative Equity Portfolio Management . P89-179
- Aswath Damodaran. Passive Value investing Screening for bargains. https://aswathdamodaran.blogspot.com/2012/06/passive-value-investing-screening-for.html