4. 流动性因子的构建方法:排序分组法、差值法、回归残差法

流动性因子,说白了就是衡量「资产好不好卖」的指标。你想想看,一个股票如果交易量稀薄、买卖价差巨大,那它本质上就带着流动性风险。在资产定价里,这种风险是需要被定价的。

我个人习惯把流动性因子的构建方法分成三大类:排序分组法、差值法、回归残差法。每种方法都有它的适用场景和坑。今天我就把这三种方法掰开揉碎了讲清楚。

4.1 排序分组法:最直观的做法

排序分组法,是业界最常用的方法。它的逻辑很简单:按流动性指标排序,然后分组,做多流动性好的,做空流动性差的。

具体步骤是这样的:

  1. 选指标:比如用 Amihud 非流动性指标、换手率、买卖价差等。
  2. 排序:每个月末,把所有股票按流动性指标排序。
  3. 分组:分成 10 组(或 5 组),流动性最差的放第 1 组,最好的放第 10 组。
  4. 构建多空组合:做多第 10 组,做空第 1 组。

嗯,这里要注意:分组数不是越大越好。我见过有人分 20 组,结果每组股票太少,组合波动大得吓人。我个人建议,A 股市场用 10 组就够用了。

核心公式

流动性因子收益率 = R(流动性最好组) - R(流动性最差组)

这个差值,就是流动性溢价。

4.2 差值法:更精细的度量

差值法,其实是对排序分组法的一个改进。它不满足于简单的多空组合,而是把流动性差异量化成连续变量。

我在项目中遇到过一个问题:用排序分组法构建的因子,在极端行情下会失效。为什么?因为分组法只考虑了排名,没考虑组内差异。比如第 1 组里,最差的股票和次差的股票,流动性可能差了一个数量级,但分组法把它们同等对待了。

差值法的做法是:

  1. 计算每个股票的流动性指标 z-score。
  2. 用市值加权或等权,计算流动性最好 30% 和最差 30% 的加权平均流动性。
  3. 取两者的差值作为因子值。

我的经验:差值法对极端值非常敏感。我曾经用 Amihud 指标直接做差值,结果因为几个小盘股的流动性极差,把整个因子都带偏了。后来我加了 winsorize(缩尾处理),效果好了很多。

4.3 回归残差法:剥离其他因素的影响

回归残差法,是学术圈比较推崇的方法。它的核心思想是:流动性因子应该只包含流动性风险,不能混杂市值、波动率等其他因素。

具体做法:

  1. 把流动性指标(如换手率)作为因变量。
  2. 把市值、波动率、价格等作为自变量。
  3. 做横截面回归,取残差作为「纯净」的流动性因子。
# Python 伪代码示例
import statsmodels.api as sm

# 每个月做一次横截面回归
def compute_liquidity_residual(liquidity, market_cap, volatility):
    X = sm.add_constant(pd.DataFrame({'mkt_cap': market_cap, 'vol': volatility}))
    y = liquidity
    model = sm.OLS(y, X).fit()
    residual = model.resid
    return residual

避坑指南:我曾经犯过一个错误——用全样本做回归,结果引入了未来信息。回归残差法必须用滚动窗口,每个月只使用当月数据做横截面回归。否则就是 look-ahead bias,后果很严重。

4.4 因子构建中的细节处理

构建因子时,细节决定成败。我总结了三个关键点:频率、权重、去极值。

4.4.1 频率:日频 vs 月频

流动性因子的重平衡频率,直接影响因子表现。

频率 优点 缺点
日频 捕捉短期流动性变化 交易成本高,容易过拟合
月频 稳健,交易成本低 可能错过短期机会
季频 更稳健,适合长期策略 流动性变化可能被平滑掉

我个人习惯用月频。为什么?因为流动性因子的换手率本来就高,如果用日频,交易成本会吃掉大部分收益。你想想看,一个月调一次仓,已经能捕捉到流动性变化的主要部分了。

4.4.2 权重:等权 vs 市值加权

权重选择,其实是在「代表性」和「可投资性」之间做权衡。

  • 等权:每个股票权重相同,更能反映流动性因子的「纯」效果。但等权组合在实际交易中很难执行,小盘股占比过高。
  • 市值加权:更贴近实际投资组合,但大市值股票的流动性好,会稀释因子的效果。

我记得有一次做回测,用等权构建的流动性因子年化收益 12%,换成市值加权后只剩 6%。差别就是这么大。所以,如果你做学术研究,用等权;如果你做实战策略,用市值加权或两者都试试。

4.4.3 去极值:MAD 法 vs 百分位法

流动性指标,尤其是 Amihud 和买卖价差,经常出现极端值。不去极值的话,一个异常值就能把整个因子带偏。

常用的去极值方法有两种:

  1. MAD 法(中位数绝对偏差):用中位数 ± 3 倍 MAD 作为截断点。这个方法对异常值更稳健。
  2. 百分位法:直接截断 1% 和 99% 分位数。简单粗暴,但效果不错。
# MAD 法去极值示例
def mad_winsorize(series, n=3):
    median = series.median()
    mad = (series - median).abs().median()
    upper = median + n * mad
    lower = median - n * mad
    return series.clip(lower, upper)

我的建议:先用 MAD 法去极值,再用百分位法做二次检查。如果两种方法结果差异很大,说明数据质量可能有问题,需要回头检查原始数据。

4.5 本章知识体系

下面这张图,是我自己梳理的流动性因子构建流程。你可以把它当作一个检查清单。

流动性因子构建流程 第一步:数据准备 日频交易数据、报价数据 第二步:指标计算 Amihud、换手率、价差 第三步:细节处理 去极值、标准化 排序分组法 排序 → 分组 → 多空组合 简单直观,适合初筛 差值法 z-score → 加权平均 → 差值 连续度量,更精细 回归残差法 OLS回归 → 取残差 剥离其他因素 流动性因子 用于资产定价模型

这张图把整个流程串起来了。从数据准备到指标计算,再到三种构建方法的选择,最后生成可用的流动性因子。你写代码的时候,可以按这个流程一步步来。