3、因子挖掘方法论:基本面因子、技术面因子、另类数据因子、因子挖掘的流程与注意事项
因子挖掘,说白了就是找到那些能预测股票涨跌的「信号」。我做了这么多年量化,见过太多人一上来就堆数据、跑回归,结果挖出来的因子全是噪音。今天咱们就聊聊,到底该怎么系统地挖因子。
3.1 基本面因子:从财报里找「硬逻辑」
基本面因子,就是基于公司财务数据、经营数据构建的因子。这类因子逻辑清晰,不容易过拟合。我个人习惯把基本面因子分成三类:
- 估值类:PE、PB、PS、PCF 等。说白了就是「便宜没好货」的反面——便宜有时候真是好货。
- 成长类:营收增速、利润增速、ROE 变化等。我在项目中遇到过,单纯用利润增速效果一般,但「超预期增速」往往很灵。
- 质量类:毛利率、净利率、资产负债率、现金流比率等。这类因子在熊市里特别管用。
核心经验:基本面因子最怕「数据滞后」。财报出来的时候,股价可能已经反应完了。我建议用「预期数据」或「一致预期调整值」来构建因子,效果会好很多。
3.2 技术面因子:从价格和成交量里找「规律」
技术面因子,就是基于历史价格、成交量、换手率等数据构建的因子。很多人觉得技术面是玄学,其实不然。关键在于你用什么逻辑去构造。
我常用的技术面因子包括:
- 动量因子:过去 N 日的收益率。注意,A 股短期动量(1-3 个月)往往反转,长期动量(6-12 个月)才有效。
- 反转因子:过去 N 日的跌幅。嗯,这里要注意,反转因子在震荡市里表现很好,但在单边牛市中会亏钱。
- 波动率因子:过去 N 日的标准差。低波动率股票长期跑赢高波动率,这个现象叫「低波动异象」。
- 成交量因子:换手率、成交量变化率等。量价配合才是真突破。
一个小技巧:技术面因子最好做「中性化」处理。比如动量因子,要剔除市值和行业的影响。我曾经吃过亏,没做中性化,结果挖出来的因子其实就是「小市值因子」的变种。
3.3 另类数据因子:从非传统数据里找「信息差」
另类数据,就是那些不是传统财报、也不是行情数据的信息。这类因子是当前量化竞争的「主战场」。为什么?因为传统因子已经太拥挤了。
我接触过的另类数据包括:
- 舆情数据:新闻情感、社交媒体热度、研报评级变化等。注意,舆情数据噪音很大,需要做「情感分析」和「异常检测」。
- 供应链数据:上下游企业的订单、库存、物流信息等。比如,苹果的供应商股价往往跟着苹果走。
- 卫星数据:停车场车流量、农田面积、港口集装箱数量等。这类数据成本高,但信息价值也高。
- 支付数据:信用卡消费、支付宝交易等。能直接反映企业的真实经营状况。
避坑指南:我曾经花大价钱买了一套卫星数据,结果发现信号太弱,根本覆盖不了多少股票。另类数据一定要先做「覆盖率测试」和「信噪比测试」,别被数据商忽悠了。
3.4 因子挖掘的流程:从想法到上线
因子挖掘不是拍脑袋,而是一套系统工程。我总结了一个五步流程:
- 因子定义:明确因子的逻辑、计算方式、数据来源。比如「过去 20 日收益率」,要定义清楚是简单收益率还是对数收益率。
- 数据准备:清洗数据、处理缺失值、对齐时间戳。这一步最耗时,也最容易出错。
- 因子计算:用代码实现因子计算。注意,要避免「未来函数」——也就是用到了未来的数据。
- 因子检验:做 IC 分析、分组回测、多因子共线性检验等。只有通过检验的因子才能进入候选池。
- 因子上线:实盘测试、监控衰减、定期更新。因子是有「半衰期」的,过一段时间可能就失效了。
下面这张图展示了因子挖掘的完整流程:
3.5 因子挖掘的注意事项:别踩这些坑
挖因子看起来简单,但坑特别多。我把自己踩过的坑总结一下:
- 避免过拟合:你想想看,如果你用 1000 个因子去拟合 100 只股票,总能找到几个「显著」的。但那是假的。我建议用「样本外检验」和「交叉验证」来防止过拟合。
- 注意数据质量:数据有缺失、有错误、有幸存者偏差,都会导致因子失效。我曾经用了一套有「未来函数」的数据,回测曲线漂亮得不得了,实盘直接亏成狗。
- 关注因子衰减:因子不是永恒的。一个因子被发现后,大家都会用,它的超额收益就会消失。我一般每季度重新检验一次因子库,把失效的剔除掉。
- 不要忽视交易成本:有些因子换手率很高,看起来收益不错,但扣掉手续费和滑点,可能就亏了。一定要在回测中模拟真实交易成本。
核心原则:因子挖掘不是找「最赚钱」的因子,而是找「最稳定」的因子。一个年化收益 10%、夏普比率 2.0 的因子,比一个年化 30%、夏普 0.5 的因子有价值得多。
3.6 一个简单的因子计算示例
说了这么多,咱们来点实际的。下面是一个简单的「过去 20 日动量因子」的计算代码:
import pandas as pd
import numpy as np
def calc_momentum_factor(price_df, window=20):
"""
计算过去 N 日的动量因子
price_df: DataFrame, 索引为日期, 列为股票代码, 值为收盘价
"""
# 计算收益率
ret_df = price_df.pct_change(window)
# 做市值中性化处理(简化版)
# 实际中需要回归剔除市值影响
factor_df = ret_df - ret_df.mean(axis=1).values.reshape(-1, 1)
# 处理缺失值
factor_df = factor_df.fillna(0)
# 做横截面标准化
factor_df = (factor_df - factor_df.mean(axis=1).values.reshape(-1, 1)) / factor_df.std(axis=1).values.reshape(-1, 1)
return factor_df
# 使用示例
# price_data = pd.read_csv('price_data.csv', index_col=0, parse_dates=True)
# momentum = calc_momentum_factor(price_data, window=20)
一个小提醒:上面的代码只是演示逻辑。实际生产中,你还需要处理停牌、退市、新股等特殊情况。我建议用专业的量化平台(比如聚宽、米筐)来跑因子,它们已经帮你处理了很多底层问题。
因子挖掘是一门手艺活,需要不断积累经验。别指望一上来就能挖到「圣杯」。多试、多错、多总结,慢慢你就会找到感觉。