halo 的技术博客

返回

问题:小盘股的 beta 为什么总是低得可疑#

拉一份 A 股全市场的 beta 表,按市值排序,你几乎必然看到这样的图景:大盘股 beta 集中在 1.0 附近,小盘股的 beta 中位数明显低于 1,最不流动的那一批甚至能低到 0.5 以下。

对这个现象最常见的解读是「小盘股防御性强」或者「小盘股不跟大盘」。两种解读都很难成立——小盘股的日波动率通常比大盘股更高,一个波动更大的资产同时对市场暴露更低,这需要极高的特质波动占比来支撑,而实际数据里小盘股在市场暴跌时跌得只多不少。

真正的解释藏在一个很土的地方:这只股票今天到底有没有成交。

如果一只股票在 t 日没有成交,它的收盘价就是 t-1 日的收盘价,你算出来的 t 日收益是 0。市场在 t 日跌了 2%,这只股票的「收益」纹丝不动。等到 t+1 日它终于成交了,价格一次性把两天的信息都反映掉。你手上的收益序列因此变成了一个被时间上打散的版本:真实的同期反应被切成碎片,分散到当天和之后若干天。

回归 r_i = α + β·r_m + ε 只看同期,那些被推迟到后面几天的反应全部进了残差。同期协方差被系统性削掉,beta 被系统性低估。

这就是非同步交易(non-synchronous trading)偏误。Dimson (1979) 给出的修正简单到有点粗暴:把滞后和领先的市场收益一起塞进回归,再把所有系数加起来。

本文用一个真实 beta 完全已知的受控模拟,测量这个偏误到底有多大、Dimson 修正能收回多少、代价是什么,以及一个更值得警惕的推论——多少「因子异象」其实是这个测量误差的产物。

模拟设计:唯一的变量是「今天有没有成交」#

之所以要做受控模拟而不是直接跑真实数据,原因很直接:真实数据里你永远不知道真实 beta 是多少。你只能比较两个估计量,无法判断谁更接近真相。模拟里真实 beta 是我设定的参数,任何偏离都可以直接归因。

设定如下:

  • 300 只股票,1500 个交易日(约 6 年)
  • 市场收益 r_m ~ N(0.03%, 1.1%) 日频
  • 每只股票的真实 beta 从 U(0.4, 1.8) 抽取,在整个样本期恒定
  • 特质波动 σ_i 从 U(1.2%, 3.0%) 抽取
  • 真实收益 r_i,t = β_i · r_m,t + σ_i · z_i,t,这是股票的内在价值变化

关键的一步是把「真实价格」变成「你能观测到的价格」:

注意这里的核心机制:信息没有丢失,只是被推迟了。 不成交的日子价格冻结在上一次成交价,一旦成交,价格直接跳到当期真实价——中间积累的所有信息一次性释放。这正是真实市场里薄交易股票的行为。

300 只股票按流动性分成 5 组,非交易日占比分别是 0%、10%、25%、40%、55%。最后一组大致对应新三板或港股仙股的活跃度。

结果一:偏误大到离谱,且严格随流动性单调#

非同步交易导致的 beta 偏误按流动性分层

非交易日占比真实 beta 均值OLS betaOLS 偏误Dimson 1 阶偏误Dimson 3 阶偏误Scholes-Williams偏误
0%1.1141.112-0.05%1.098-1.66%1.082-4.16%1.098-1.65%
10%1.0130.913-9.41%0.997-0.34%1.023+1.96%0.993-0.74%
25%1.1920.903-24.43%1.124-5.44%1.187+0.93%1.115-6.22%
40%1.0700.636-40.49%0.893-16.41%1.044-2.19%0.883-17.38%
55%1.0810.486-55.14%0.762-29.92%1.011-7.28%0.751-30.92%

先看第一行:完全流动的组,OLS 偏误 -0.05%。这是引擎正确性的证明——没有非同步交易时,普通回归是无偏的,所有后面的偏误都可以干净地归因到停摆机制。

再看最后一行:真实 beta 1.081,OLS 估出 0.486。一只真实上跟市场同步跳动、甚至放大市场波动的股票,被测量成一个防御性资产。 如果你用这个 beta 做对冲比例,你会严重对冲不足;如果你用它算风险预算,你会以为组合的市场暴露只有实际的一半。

偏误对非交易概率的关系近似线性——回归斜率 -1.010,也就是非交易概率每上升 10 个百分点,beta 被压低约 10%。这个近似的一比一关系在直觉上很好理解:如果一只股票有 55% 的日子不动,它的同期协方差大致只保留了 45% 左右。

Dimson 3 阶把最不流动组的偏误从 -55.14% 收回到 -7.28%。 这不是微调,是从「结论完全错误」到「有一点残余偏误但方向和量级都对了」的质变。

Dimson 的做法本身很简单:

def dimson_beta(y, mkt, k=1):
    """把 t-k ... t+k 的市场收益全部放进回归,系数求和"""
    T = len(y)
    cols = [mkt[k + j : T - k + j] for j in range(-k, k + 1)]
    X = np.column_stack([np.ones(T - 2 * k)] + cols)
    yy = y[k : T - k]
    coef, *_ = np.linalg.lstsq(X, yy, rcond=None)

    # 系数和的标准误:w'Σw,w 在所有 beta 项上为 1
    resid = yy - X @ coef
    s2 = resid @ resid / (len(yy) - X.shape[1])
    cov = s2 * np.linalg.inv(X.T @ X)
    w = np.zeros(X.shape[1]); w[1:] = 1.0
    return float(coef[1:].sum()), float(np.sqrt(w @ cov @ w))
python

注意标准误的算法:不能把各期系数的标准误直接相加或平方相加,因为滞后市场收益之间存在自相关,系数估计是相关的。必须用 w'Σw 的完整二次型。这是实现里最容易错的一处。

Scholes-Williams 用的是另一套逻辑(对滞后/同期/领先分别单变量回归,再用市场自相关做调整),结果和 Dimson 1 阶几乎重合(-30.92% vs -29.92%)——它本质上是一个 1 阶方法,在停摆 55% 的极端场景下阶数不够。方法之争在这里不重要,阶数够不够才重要。

结果二:信息躺在过去,不在未来#

Dimson 回归同时放了领先项(t+1、t+2、t+3)。它们有用吗?

RMSE 对比与 Dimson 滞后系数剖面

最不流动组的各期系数占真实 beta 的比例:

t-3t-2t-1tt+1t+2t+3
系数/真实 beta0.0740.1370.2460.4500.0080.0060.006

三个数字值得注意:

  1. 同期只贡献 45.0%——和「55% 的日子不成交」几乎精确对应。这不是巧合,是机制的直接读数。
  2. 滞后项贡献 45.8%(0.074+0.137+0.246),且按时间距离单调衰减。被推迟的反应主要在 1-2 天内补回来。
  3. 领先项贡献几乎为零(合计 0.020)。

第 3 点是这个模拟的一个内部一致性检验。领先项系数应该为零,因为在我的数据生成过程里,股票收益只依赖当期和过去的市场信息,不可能依赖未来。如果领先项跑出显著非零,说明代码里有 look-ahead。 实测 0.006-0.008 的量级等于噪声,引擎干净。

那实盘为什么还要放领先项?因为真实市场里领先项可能真的非零——如果是市场指数本身包含大量不流动成分股(这在小盘指数里很常见),指数收益反而会滞后于个股。领先项是为这种反向非同步准备的。在本模拟设定(指数完全流动)下,它们的唯一作用是消耗自由度。

各期系数合计 0.927,剩下的 7.3% 就是 -7.28% 的残余偏误来源:3 阶窗口截断掉了 t-4 及更远的尾巴。加大 k 可以继续收敛,但代价见下一节。

结果三:修正不是免费的,是拿方差换偏误#

这是最容易被忽略的一半。全流动对照组(所有股票 100% 每日成交)的结果:

方法偏误RMSE平均标准误(全样本)
OLS+0.14%0.0520.048
Dimson 1 阶-0.43%0.0880.083
Dimson 3 阶+0.48%0.1280.127

没有非同步交易时,Dimson 的 RMSE 是 OLS 的 2.5 倍。 偏误都接近零(这本身也是对 Dimson 的一个校验:它在不该修正的地方没有乱修),但方差爆炸——多塞 6 个几乎无信息的解释变量,每个都带来估计噪声,加总时噪声也加总。

标准误的代价在分层表里同样清楚:最不流动组 OLS 标准误 0.057,Dimson 1 阶 0.099,Dimson 3 阶 0.150。你用 2.6 倍的标准误换回了 48 个百分点的偏误修正。

在有偏误的场景里这笔交易极其划算——全样本 RMSE:OLS 0.383、Dimson 1 阶 0.198、Dimson 3 阶 0.144、S-W 0.204。与真实 beta 的横截面相关系数从 OLS 的 0.783 升到 Dimson 3 阶的 0.940

但结论必须成对来说:

对流动股用 Dimson 是纯亏方差。 只在薄交易资产上用,且阶数要按停摆程度选,不是越高越好。

一个实务上的经验规则:如果一只股票的日收益序列里零收益占比低于 5%,直接 OLS;5%-20% 用 1 阶;20% 以上考虑 3 阶。零收益占比是可以直接观测的,不需要猜。

结果四:低 beta 异象——一个被测量误差凭空造出来的「alpha」#

到这里为止都是估计量的技术讨论。下面这一段才是真正应该让人警觉的部分。

我在模拟里构造了一个没有任何异象的世界:每只股票的真实预期年化收益严格等于 β_true × 6%,CAPM 完美成立,alpha 恒等于零。然后分别按真实 beta、OLS beta、Dimson beta 排序分五组。

低 beta 异象在无异象世界中被测量误差伪造出来

分组按真实 beta 排序按 OLS beta 排序按 Dimson 3 阶排序
Q1(最低)3.24%3.71%3.47%
Q25.01%5.58%4.99%
Q36.51%6.84%6.64%
Q48.14%7.43%7.98%
Q5(最高)9.92%9.27%9.75%
Q5−Q1 跨度6.68%5.56%6.28%

按 OLS beta 排序,Q5−Q1 的收益跨度被压缩了 16.8%(5.56% vs 6.68%)。也就是说,在一个 CAPM 完美成立的世界里,用 OLS beta 排序会让你看到一条比真相更平坦的证券市场线——这正是低 beta 异象文献里最经典的实证图形。

更直接的证据在 Q1 组:

指标数值
Q1 组 OLS beta 均值0.344
Q1 组真实 beta 均值0.619
Q1 组真实预期收益3.71%
用 OLS beta 算出的「alpha」+1.65%
Q1 组中最不流动股票占比73.3%

你测出 beta 0.344,CAPM 预测收益 0.344×6% = 2.06%,实际拿到 3.71%,凭空多出 1.65 个百分点的年化 alpha。

这 1.65% 一分钱都不存在。它完全来自 beta 被低估了 0.275。而 Q1 组里 73.3% 是非交易日占比 ≥40% 的股票——「按 beta 排序」在薄交易市场里等价于「按流动性排序」,你以为在做因子分组,其实在做流动性分组。

右图把这一点画得很直白:按 OLS beta 排序,各组的平均非交易日占比从 Q1 的 39.8% 单调降到 Q5 的 10.0%;而按真实 beta 排序,五组的流动性分布基本持平(24.5%-27.6%)。流动性污染是排序变量本身带进来的,不是样本自带的。

用 Dimson beta 排序,Q5−Q1 跨度回到 6.28%(真相 6.68% 的 94%),异象基本消失。

我不认为这个模拟证明了现实中的低 beta 异象全是假的——真实市场里有杠杆约束、彩票偏好等实打实的机制。但它确立了一个必须先过的关卡:

任何在含薄交易资产的样本上发现的 beta 相关异象,都必须先用非同步修正后的 beta 复现一遍。 复现不了的,优先归因于测量误差,而不是新发现。

对照检验:这个偏误是真机制还是我编的#

一个模拟能跑出漂亮的单调关系不说明任何问题——参数是我设的,出现设定好的模式是应该的。真正需要验证的是:这个关系是不是由我以为的那个机制产生的。

置换检验:打乱流动性归属#

如果偏误真的由停摆造成,那么把流动性标签在股票之间随机打乱后,「偏误 vs 非交易概率」的关系应该消失。

时间聚合的替代方案与置换检验

200 次打乱:

统计量数值
真实斜率-1.010
置换均值0.004
置换 5 分位-0.088
置换中超过真实值的次数0 / 200

真实斜率比置换分布的最极端值还远 11 倍以上。关系是机制性的,不是数据挖出来的。

多种子稳健性#

单个种子的结果可能是运气。20 个独立种子重跑最不流动组:

指标均值标准差最小最大
OLS 偏误-55.31%0.98%-58.03%-53.42%
Dimson 3 阶偏误-9.96%1.59%

OLS 偏误在 20 个种子里的散布只有 ±1 个百分点,这是一个极其稳定的结构性偏误,不是抽样波动。 Dimson 修正后的残余偏误 -9.96% 也稳定(基准种子上的 -7.28% 落在正常散布内)。

时间聚合:一个不需要 Dimson 的替代方案#

既然问题是「一天太短,很多股票没反应过来」,那用更长的收益频率是不是就能绕过去?

聚合窗口最不流动组偏误全样本偏误平均标准误有效观测数
日频-55.14%-25.90%0.0531500
周频(5 日)-21.96%-8.78%0.111300
双周(10 日)-13.42%-5.18%0.152150
月频(21 日)-8.31%-2.95%0.22571

有效。月频把偏误从 -55% 压到 -8%,和 Dimson 3 阶(-7.28%)基本相当。

但代价更重:标准误 0.225,是日频 OLS 的 4.2 倍,也明显高于 Dimson 3 阶的 0.150。 6 年数据只剩 71 个观测,任何时变性都无法捕捉,滚动窗口更是无从谈起。

结论是:两条路都能治,但在同等偏误水平下 Dimson 的方差代价更小,且保留了日频数据用于滚动估计的可能。月频聚合更适合做交叉验证——如果 Dimson beta 和月频 beta 大致吻合,你对修正结果的信心会高很多;如果两者差很远,说明有别的问题(比如 beta 本身在时变)。

完整实现#

choose_estimator 里的零收益占比是实盘落地的关键——它直接可观测,不需要任何假设,而且和模拟里的停摆概率是同一个东西。先量出这个数,再决定用什么估计量。

需要注意一个实盘细节:A 股的零收益不完全等于「没成交」。涨跌停封死时有成交但价格不动,也会产生零收益。这两种情况对 beta 估计的影响方向一致(都削弱同期协方差),所以用零收益占比做判据在方向上是对的,但它会略微高估真实停摆程度。

已知偏差#

1. 停摆是独立随机的,真实世界是聚集的。 模拟里每天是否成交服从独立伯努利,而真实的薄交易股票经常连续多日无成交,然后在某个消息驱动下连续活跃。聚集性会让偏误结构更复杂——独立停摆下 3 阶窗口够用,聚集停摆需要更长窗口,模拟里的 -7.28% 残余偏误在真实数据上大概率更差。

2. beta 设为常数。 真实 beta 随时间变化(尤其在市场 regime 切换时)。这个设定让 Dimson 的长窗口需求显得没有代价,但实盘上「窗口越长偏误越小」和「窗口越长时变性丢得越多」是直接冲突的。本文没有测量这个权衡。

3. 市场指数假设完全流动。 因此领先项系数为零。真实的小盘指数本身包含大量薄交易成分,指数收益会滞后于流动个股,此时领先项承担真实作用,Dimson 的对称窗口设计才有意义。用大盘指数(沪深 300)做基准时这个问题不大,用小盘指数(中证 2000)时需要重新检查领先项。

4. 无买卖价差回弹。 真实的薄交易股票同时存在 bid-ask bounce,它给收益序列注入负一阶自相关,方向上会进一步压低 beta 估计。本文只隔离了非同步交易一个机制,真实偏误应该比 -55% 更大一些。

5. 「低 beta 异象全是假的」不成立。 模拟只证明了测量误差足以制造一个看起来像异象的模式,不证明现实中的异象就是这么来的。杠杆约束假说和彩票偏好假说在流动性大盘股上同样有实证支持,那些样本里非同步偏误可以忽略。

结果解读#

这个偏误的量级足以让风险模型失效,而不只是「有点不准」。 -55% 意味着一个真实 beta 1.08 的资产被登记为 0.49。如果你的组合里有 20% 权重在这类资产上,组合层面的市场暴露会被系统性低估约 12 个百分点。这不是精度问题,是方向性错误——你会在自以为中性的时候实际做多市场。

修正的收益高度集中在尾部。 分层表读下来,10% 停摆组 OLS 偏误只有 -9.41%,25% 组 -24.43%。前两组用不用 Dimson 差别不大(而且 Dimson 3 阶在流动组反而更差)。真正需要修正的是 40% 以上的那一小撮。所以正确的做法不是全市场统一换估计量,是先分层、再决定。 全市场无脑用 Dimson,你会在 80% 的股票上白白付方差成本。

滞后剖面是最好的诊断工具。 t 期系数占比 0.450 直接读出了停摆程度,滞后项的衰减速度告诉你信息补回来有多快。实盘上跑一遍 Dimson 回归,把各期系数打印出来看形状——如果 t-1、t-2 系数显著为正,非同步偏误确实存在;如果滞后项全是噪声但 beta 还是偏低,问题在别处(比如这只股票真的就是低 beta)。这比任何统计检验都直观。

方差代价必须计入决策,而不是修正完就完事。 Dimson 3 阶在最不流动组的标准误 0.150,意味着一个点估计 1.01 的 95% 置信区间大致是 [0.72, 1.31]。你确实消除了偏误,但区间宽到几乎不能用于精确对冲。诚实的说法是:Dimson 让你知道「这只股票的 beta 大概是 1 而不是 0.5」,但它给不了你一个可以直接拿去算对冲手数的数字。 对于薄交易资产,beta 本来就是一个不精确的量,修正只是把「精确的错误」换成「不精确的正确」。

对异象研究的启示比对 beta 估计本身更重要。 那个 +1.65% 的伪 alpha 是在一个我亲手构造的、alpha 严格为零的世界里跑出来的。它通过了所有常规检查——分组单调、跨度可观、样本量充足。唯一能识破它的方法是知道真实 beta,而这在实证研究里永远不可能。替代方案只有一个:换个估计量重跑,看结论是否稳定。 如果一个异象在 OLS beta 下显著、在 Dimson beta 下消失,它大概率不是异象。这个检验很便宜,代码就是上面那十几行,但我见过的实证论文里做这一步的不多。

流动性是所有横截面研究的隐形第三变量。 这个模拟里最让我意外的不是偏误多大,而是「按 beta 排序 = 按流动性排序」这个等价关系有多强——Q1 组 73.3% 是最不流动股票。任何在含小盘股样本上做的横截面排序,都值得顺手打印一下各组的流动性分布。如果分布单调,你的排序变量已经被流动性污染了,后面所有结论都要重新审视。

非同步交易与 Dimson Beta:用滞后市场收益修正被低估的系统性暴露
https://blog.halo26812.eu.org/blog/nonsynchronous-trading-dimson-beta
Author halo
Published at 2026年8月1日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨