4. 红利因子选股框架:单因子选股流程、因子值计算、股票池构建、回测框架搭建

好,咱们直接进入正题。这一章我打算把红利因子选股的整个框架给你拆开揉碎了讲清楚。说白了,就是告诉你一套完整的、能直接上手的操作流程。我自己刚开始做量化那会儿,最头疼的就是「知道因子是什么,但不知道怎么把它跑起来」。所以这一章,咱们就解决这个痛点。

4.1 单因子选股流程:从想法到策略

单因子选股的流程,其实没那么玄乎。我习惯把它分成四个步骤:

  1. 因子定义与计算:把「红利」这个抽象概念,变成一个具体的数字。
  2. 股票池构建:划定我们选股的范围,不能什么股票都往里塞。
  3. 因子排序与分组:按因子值大小给股票排队,看看高分红的股票是不是真的表现更好。
  4. 回测验证:用历史数据检验这个策略能不能赚钱。

嗯,这里要注意一点。很多人一上来就急着写代码回测,结果发现结果乱七八糟。为什么?因为前两步没做好。你想想看,因子值算错了,股票池里一堆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
小技巧: 我建议你计算时,把股息率乘以100,变成百分比形式。这样在排序时,数值差异更明显,方便观察。

4.3 股票池构建:划定你的狩猎范围

股票池不是越大越好。我见过有人把全市场5000只股票都拿来算因子,结果回测曲线跟心电图似的。为什么?因为很多股票根本不具备分红能力,或者流动性太差。

我个人构建股票池时,会设置几个硬性门槛:

  • 剔除ST、*ST股票:这些公司基本面有问题,分红不稳定。
  • 剔除上市不满1年的新股:次新股数据太少,分红历史不可靠。
  • 剔除最近3年未分红的股票:连年不分红,说明公司没把股东回报当回事。
  • 剔除日均成交额低于1000万的股票:流动性太差,你买进去卖不出来。

这里我画了一张流程图,帮你理清整个框架的逻辑:

红利因子选股框架流程图 全市场股票 股票池构建 剔除ST、次新、无分红、低流动性 因子值计算 TTM股息率 = 近12月分红 / 当前股价 因子排序与分组 按股息率从高到低分5组 回测验证
核心要点: 股票池的质量,直接决定了你策略的天花板。池子里的股票越「干净」,回测结果越可信。

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%。但换成全市场选股后,收益反而下降了。为什么?因为中证红利指数本身已经帮你做了一层筛选,股票质量更稳定。所以你看,股票池的选择,真的能决定成败。

我的建议: 刚开始做回测时,先用一个较小的股票池(比如沪深300成分股)练手。等流程跑通了,再慢慢扩大范围。这样出了问题也好排查。

好了,这一章的内容就到这里。框架搭好了,下一章咱们就可以往里面填具体的策略逻辑了。


专注资料整理