4. 红利因子选股框架:单因子选股流程、因子值计算、股票池构建、回测框架搭建
好,咱们直接进入正题。这一章我打算把红利因子选股的整个框架给你拆开揉碎了讲清楚。说白了,就是告诉你一套完整的、能直接上手的操作流程。我自己刚开始做量化那会儿,最头疼的就是「知道因子是什么,但不知道怎么把它跑起来」。所以这一章,咱们就解决这个痛点。
4.1 单因子选股流程:从想法到策略
单因子选股的流程,其实没那么玄乎。我习惯把它分成四个步骤:
- 因子定义与计算:把「红利」这个抽象概念,变成一个具体的数字。
- 股票池构建:划定我们选股的范围,不能什么股票都往里塞。
- 因子排序与分组:按因子值大小给股票排队,看看高分红的股票是不是真的表现更好。
- 回测验证:用历史数据检验这个策略能不能赚钱。
嗯,这里要注意一点。很多人一上来就急着写代码回测,结果发现结果乱七八糟。为什么?因为前两步没做好。你想想看,因子值算错了,股票池里一堆ST股,那回测结果能信吗?
4.2 因子值计算:把红利量化
红利因子最常见的代理变量就是「股息率」。公式很简单:
股息率 = 每股现金分红 / 当前股价
但这里有个坑。我曾经在项目里直接用「上一年年报的分红」除以「今天的股价」,结果回测效果一塌糊涂。后来才发现,分红数据有滞后性。你想想看,年报通常在次年4月底才出完,你用4月前的股价去算,数据对不上。
所以我个人的习惯是:
- 用「最近12个月(TTM)的每股分红」作为分子。
- 用「分红除权除息日之后的股价」作为分母。
- 如果遇到还没分红但已预告的,用预告值代替。
下面是一个简单的Python计算示例,我用的是伪代码风格,方便你理解逻辑:
# 伪代码示例:计算TTM股息率
def calc_dividend_yield(stock_code, current_date):
# 获取最近4个季度的每股分红总和
ttm_dividend = get_ttm_dividend(stock_code, current_date)
# 获取当前股价
current_price = get_price(stock_code, current_date)
# 计算股息率
if current_price > 0:
yield = ttm_dividend / current_price
else:
yield = 0
return yield
4.3 股票池构建:划定你的狩猎范围
股票池不是越大越好。我见过有人把全市场5000只股票都拿来算因子,结果回测曲线跟心电图似的。为什么?因为很多股票根本不具备分红能力,或者流动性太差。
我个人构建股票池时,会设置几个硬性门槛:
- 剔除ST、*ST股票:这些公司基本面有问题,分红不稳定。
- 剔除上市不满1年的新股:次新股数据太少,分红历史不可靠。
- 剔除最近3年未分红的股票:连年不分红,说明公司没把股东回报当回事。
- 剔除日均成交额低于1000万的股票:流动性太差,你买进去卖不出来。
这里我画了一张流程图,帮你理清整个框架的逻辑:
4.4 回测框架搭建:让历史告诉你答案
回测框架,说白了就是一台「时光机」。你设定好规则,它帮你模拟过去几年如果按这个策略操作,能赚多少钱。
搭建回测框架时,我建议你关注这几个关键点:
- 调仓频率:红利策略通常按月或按季度调仓。我个人偏好月度调仓,因为分红数据变化不快,太频繁反而增加交易成本。
- 交易成本:包括佣金、印花税、滑点。很多人回测时忽略滑点,结果实盘一跑就亏。我一般设千分之一到千分之二的滑点。
- 基准对比:拿你的策略跟沪深300或者中证红利指数比一比。如果连指数都跑不赢,那这策略就没意义。
下面是一个简化的回测框架代码结构:
# 伪代码:回测框架核心逻辑
def backtest(stock_pool, factor_data, start_date, end_date):
portfolio = []
for month in get_trading_months(start_date, end_date):
# 1. 获取当前股票池
current_stocks = get_stocks_in_pool(stock_pool, month)
# 2. 获取因子值并排序
factor_values = get_factor_values(factor_data, current_stocks, month)
sorted_stocks = sort_by_factor(factor_values)
# 3. 选前20%的股票
selected = sorted_stocks[:int(len(sorted_stocks)*0.2)]
# 4. 调仓
portfolio = rebalance(portfolio, selected, month)
# 5. 记录收益
record_return(portfolio, month)
# 6. 计算最终绩效
return calculate_performance(portfolio)
4.5 一个完整的示例:用股息率选股
咱们把上面这些串起来,看一个完整的例子。假设我们要在2023年做月度调仓:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 构建股票池 | 剔除ST、次新、无分红、低流动性股票,剩余约2000只 |
| 2 | 计算因子值 | 每月初计算每只股票的TTM股息率 |
| 3 | 排序分组 | 按股息率从高到低排序,取前20%(约400只) |
| 4 | 等权买入 | 每只股票分配相同资金,每月调仓一次 |
| 5 | 回测统计 | 计算年化收益、最大回撤、夏普比率等指标 |
这个框架看起来简单,但实际跑起来你会发现很多细节。比如分红除权后股价会跳空,你的因子值会突然变化。再比如有些股票分红后股价填权很快,有些则一直趴着。这些都会影响最终收益。
嗯,说到这,我想起一个案例。之前有个学员用这个框架跑中证红利指数的成分股,回测年化收益12%,最大回撤只有8%。但换成全市场选股后,收益反而下降了。为什么?因为中证红利指数本身已经帮你做了一层筛选,股票质量更稳定。所以你看,股票池的选择,真的能决定成败。
好了,这一章的内容就到这里。框架搭好了,下一章咱们就可以往里面填具体的策略逻辑了。