零收益天数流动性度量:用停滞比例给流动性打分
「一只股票有多少天价格纹丝不动?」Lesmond-Ogden-Trzcinka (1999) 把这个最朴素的观察做成了流动性度量:Zeros = 零收益天数 / 总交易天数。机制来自 LOT 交易成本模型——当信息带来的价值变动小于交易成本带 ±c 时,边际知情交易者选择不动手,价格就停在原地;成本带越宽,「装死」的天数越多。三年日线模拟实测:大盘蓝筹 Zeros 只有 3.1%,小盘微盘高达 38.3%,与真实交易成本的 Spearman 相关 0.98;危机情景里 60 日滚动 Zeros 从 15% 飙到 69%,是流动性枯竭的同期温度计。它最大的卖点是数据要求低到极致——只要收盘价,连成交量都不用,这让它成为覆盖新兴市场、公司债、上世纪历史数据的唯一可行选择。诚实边界:停牌与涨跌停会污染统计、离散报价制造伪零、对大盘股区分度趋近于零(中阶)。
问题:数据穷到只剩收盘价时,怎么度量流动性#
流动性度量是一个数据丰俭由人的谱系。最富的一端是逐笔盘口:有效价差、价格冲击、订单簿深度,什么都能算。往下是日线成交额:Amihud、Amivest 这些「收益除以成交额」的比率。但再往下呢?
很多严肃的研究场景,你手里连成交量都没有:
- 新兴市场和前沿市场的早期数据,只有价格序列;
- 公司债和市政债,成交本来就稀疏,量的记录质量堪忧;
- 回溯到上世纪五六十年代的历史研究,量数据缺失或不可信;
- 某些数据库的成交量字段跨市场口径不一致,横向比较会出鬼。
Lesmond, Ogden & Trzcinka (1999) 给出了数据要求最低的答案——只要收盘价:
数一数样本期内有多少天收益恰好为零,除以总交易天数。就这么简单。这个比例越高,流动性越差。
听起来简单得像个玩笑,但它背后有一个正经的结构模型撑腰。
机制:交易成本带如何制造零收益日#
LOT 模型的核心设定是:每只股票存在一个交易成本带 (买卖成本可以不对称)。当天的「真实信息价值变动」为 ,但观测到的收益是:
直觉是边际知情交易者的算盘:今天的信息值 0.8% 的价格变动,但一来一回的交易成本要 1.2%——那就不交易。没人交易,价格不动,收益为零。零收益日不是「没有信息」的日子,而是「信息不够付过路费」的日子。
成本带越宽(流动性越差),能被「吃掉」的信息幅度越大,零收益日就越多。Zeros 度量就是这个机制的直接读数。
用模拟把机制画出来:真实收益 ,成本带 ±1.2%——

左图是连续分布的真实信息收益,右图是被成本带「压扁」后的观测收益:45.2% 的天数被压成了精确的零,两侧的收益也整体向内收缩了一个成本带的宽度。这不是数据错误,这就是非流动性市场里价格的真实行为。
实现:可能是全网最短的流动性度量#
import numpy as np
import pandas as pd
def zeros_measure(close: pd.Series) -> float:
"""
零收益天数流动性度量 (Lesmond-Ogden-Trzcinka 1999)
close: 日收盘价序列(已剔除停牌日)
返回: 零收益天数占比,越高流动性越差
"""
ret = close.pct_change().dropna()
return float((ret == 0).mean())
def rolling_zeros(close: pd.Series, window: int = 60) -> pd.Series:
"""60日滚动 Zeros,用于监控流动性状态变化"""
ret = close.pct_change()
return (ret == 0).rolling(window).mean()python两个函数,十行代码。有一个工程细节值得单独说:ret == 0 对浮点数做精确比较通常是坏习惯,但在这里是故意的——零收益日的定义就是收盘价完全没变,pct_change 对相同价格算出的是精确的 0.0,不存在浮点误差问题。如果你的数据源经过复权处理引入了微小数值噪声,需要改成 ret.abs() < 1e-8,并在报告里披露这个阈值。
一个常用的扩展是 Zeros2(Fong-Holden-Trzcinka 2017 的输入之一):只统计「收益为零且成交量为零」的天数,把「有交易但价格没动」和「根本没人交易」区分开。前者可能只是买卖力量恰好平衡,后者才是纯粹的流动性缺失。
实验一:横截面区分度#
模拟 90 只股票(大盘蓝筹 / 中盘 / 小盘微盘各 30 只),三年日线(756 天),每只股票的成本带按组别设定并加随机扰动:

| 组别 | 平均 Zeros | 范围 |
|---|---|---|
| 大盘蓝筹 | 3.1% | 0.7%~5.2% |
| 中盘 | 13.1% | 6.7%~21.0% |
| 小盘/微盘 | 38.3% | 17.9%~57.3% |
三组之间几乎没有重叠,横截面区分度非常干净。更关键的验证是:Zeros 与模拟中植入的真实交易成本的 Spearman 相关达到 0.979——一个只数「价格没动的天数」的指标,几乎完美还原了成本排序。
这组数字与实证文献的量级一致:Lesmond (2005) 统计 23 个新兴市场,流动性最差的市场零收益天数占比超过三分之一,而美国大盘股通常在个位数。
实验二:和 Amihud 量的是同一件事吗#
同一批股票上同时计算 Amihud 非流动性比率(|收益|/成交额):

Spearman 相关 0.944——排序高度一致,但注意散点的形状:在 Zeros 低于 10% 的区域,同一水平的 Zeros 对应的 Amihud 可以差一个数量级。原因是两者的信息来源不同:
- Zeros 只看「价格动没动」,是一个离散计数,对大盘股天然饱和——流动性从「很好」提升到「极好」,零收益天数都趋近于零,指标失去分辨率;
- Amihud 用连续的成交额做分母,在高流动性区域仍有区分度。
实务结论:Zeros 是小盘股、新兴市场、债券的武器;对流动性本来就好的资产,请换 Amihud 或盘口数据。两者不是替代关系,是分工关系。
实验三:危机温度计#
把成本带做成时变的:平时 ±0.4%,危机期 80 天内逐步扩大到 ±2.0% 再缓慢恢复,模拟流动性枯竭:

60 日滚动 Zeros 从平时的 14.7% 飙升到危机峰值 68.9%——市场用「三分之二的天数价格装死」来响应成本带的扩大,同时价格阴跌。这个形态在真实危机中反复出现:流动性枯竭时,报价撤离、价差拉宽,大量交易日以「无成交或象征性成交」收场。
但要说清楚它的身份:滚动 Zeros 是同期指标,不是领先指标。它的上升与危机同步展开,等 Zeros 明显飙高时价格已经在跌了。它的价值在风险监控(组合里 Zeros 快速上升的持仓需要重估变现能力)而非择时。
什么时候该用它#
Zeros 在流动性度量家族里的定位非常明确——低数据要求场景的默认选择:
- 跨国研究:Fong-Holden-Trzcinka (2017) 对全球几十个市场做了度量赛马,结论是在只有日线数据时,基于零收益的度量家族是月度流动性的最佳代理之一;
- 公司债:债券成交稀疏,零交易日本身就是常态信息,Zeros 天然适配;
- 长历史回测:上世纪的数据没有可信的成交量,Zeros 是少数能算的指标;
- 作为复合指标的原料:LOT 模型可以更进一步,用最大似然从价格序列反解出成本带宽度 ,直接给出「隐含往返交易成本」的美元估计。
已知偏差与边界#
停牌与涨跌停是最大的污染源。 停牌日在有些数据库里被填充为「收益为零」,直接把 Zeros 吹大——必须先剔除停牌日再计算。A 股的涨跌停日则相反:价格封死在涨跌停板上,第二天继续一字板时收益为零,但这不是「流动性差导致没人交易」,而是「制度约束导致想交易的人交易不了」——语义相反的两种零。A 股场景必须把连续一字板单独处理。
离散报价制造伪零。 最小报价单位相对价格越大,价格「凑巧不动」的概率越高。一只 2 元的股票 tick 是 0.01 元(50bp),比 200 元的股票(0.5bp)更容易出现零收益日,即使两者的真实流动性相同。跨价格水平比较时这个偏差不可忽略,缓解办法是控制价格水平或用 Fong-Holden-Trzcinka 的调整版本。
对高流动性资产没有分辨率。 前面说过:大盘蓝筹的 Zeros 挤在 0~5% 的窄带里,排序噪声很大。这是指标的结构性天花板,不是参数能调出来的。
模拟的局限。 本文的成本带模型是 LOT 的教科书简化:成本对称、真实收益正态、无自相关。真实市场的零收益日还有其他来源(观测频率、四舍五入、交易所制度),Zeros 与真实成本 0.98 的相关是模拟世界的上限,实证文献里典型值在 0.6~0.8。
结果解读#
三个可以直接带走的结论:
- Zeros 是「穷人版」流动性度量,但穷得有尊严——只用收盘价就能达到与 Amihud 0.94 的排序一致性,在数据受限场景(新兴市场、债券、长历史)它不是次优选择,是唯一选择;
- 它的甜区在流动性差的那一端——小盘、微盘、债券的区分度极好,大盘蓝筹上趋于饱和,选指标前先看你的资产在谱系的哪一段;
- 滚动 Zeros 是称职的危机温度计——从 15% 到 69% 的飙升与流动性枯竭同步,适合做组合变现能力的持续监控,但别指望它提前报警。
下一步的自然延伸是 LOT 最大似然估计:不只数零的个数,而是用零收益日的信息反解出成本带的宽度,把「流动性排序」升级成「交易成本的美元估计」——那是另一篇文章的主题。