A股股票流动性指标详解:从换手率到Amihud的Stata实现
2026/9/16 9:10:20 网站建设 项目流程

简介:数据包覆盖2000—2023年上市公司股票流动性指标,面向金融研究者、学生及量化投资者,可用于评估个股交易活跃度、换手率、市值与买卖价差等维度,解决长周期流动性数据获取与整理难题。压缩包共6个文件,包含个股流动性的Excel与Stata格式数据文件、便于追溯的数据来源HTML说明、使用说明TXT,以及两篇主题相关的PDF研究文献,整体体积仅4.08MB,结构清晰易读。已有125人学习下载。数据表可直接用于面板回归或图表分析,配套说明文档降低了使用门槛;两篇文献分别讨论股票流动性与国企绩效、创业板注册制改革下的价格发现,为理解流动性指标的经济含义提供了参考,适合毕业论文、课题研究或投资决策辅助。

1. 把 2000-2023 年 A 股流动性指标拆开看

做资产定价或公司金融实证的人,最头疼的往往不是模型设定,而是「想要的数据散落在十几个数据库里,口径还对不齐」。这个压缩包把 2000-2023 年上市公司股票流动性指标整理成了可直接使用的面板数据,同时附了 2023 年当年的 Excel 和 Stata 格式明细、数据来源说明,以及温军《股票流动性、股权治理与国有企业绩效》和李松楠《价格笼子、流动性与价格发现——基于创业板注册制改革的证据》两篇参考文献。它适合有三类需求的读者:一是做论文回归时需要流动性代理变量的研究生;二是想快速搭建个股流动性监控报表的量化分析人员;三是想搞清楚换手率、Amihud 非流动性、买卖价差这几个口径在 A 股到底怎么算才不出错的从业者。接下来按「口径原理 → 数据清洗 → Stata 实证 → 边界与坑」的顺序展开,全程附可复现代码。

2. 流动性指标口径拆解:换手率、Amihud、价差与 Roll 模型

2.1 先搞清五种常见口径的适用边界

包里的文件名为「股票流动性指标」,但流动性从来不是一个单一指标,而是一族代理变量的统称。学术文献里常用的口径至少包含以下五类,它们的计算逻辑、数据需求和适用场景差异很大。

交易量是最原始的口径,直接用日频成交股数或成交金额衡量,缺点是受公司规模影响太大,工商银行一天成交 20 亿和一家小盘股成交 20 亿含义完全不同。换手率解决了量纲问题,用成交量除以流通股本,反映的是存量股份的周转速度,但它在高送转、定增解禁等股本变动节点会失真。买卖价差(Bid-Ask Spread)最贴近流动性定义,却需要订单簿或至少是最高买价与最低卖价的分笔数据,日频汇总数据里通常没有,只能退而求其次用高频快照近似。市场深度需要盘口挂单量,同样依赖 Level-2 数据。

剩下两类是面板数据实证中最常用的:Amihud 非流动性指标和 Roll 有效价差估计。Amihud(2002)用日收益率的绝对值除以成交金额,直观含义是「每成交一元钱引起多大的价格冲击」,数值越大流动性越差。Roll(1984)则利用有效价差与价格变动负自协方差的关系,用日收益率序列的一阶自协方差反推出隐含价差,不需要任何订单簿数据,只要有日收盘价就能算。包内文件既然覆盖 2000-2023 年 20 多年的日频跨度,早期年份没有盘口数据,Amihud 和 Roll 几乎是唯一可行的标准口径;换手率则适合做稳健性替换。

2.2 Amihud 指标的计算细节与去极值处理

Amihud 的计算公式为:

[ Amihud_{i,t} = \frac{1}{D_{i,t}} \sum_{d=1}^{D_{i,t}} \frac{|R_{i,d}|}{Volume_{i,d}} ]

其中 (R_{i,d}) 是股票 i 在第 d 日的收益率,(Volume_{i,d}) 是当日成交金额(单位通常取百万元),(D_{i,t}) 是股票 i 在月份 t 的有效交易日数。计算时有两个容易被忽视的细节。第一,收益率必须用考虑现金红利再投资的日个股回报率,否则除权除息日会出现假的大幅波动。第二,成交金额的量纲直接影响回归系数的量级,如果成交额用元,系数会小到影响 Stata 输出的可读性,建议统一除以 1e6 或 1e8。

A 股数据还有一个特有的脏数据问题:涨跌停当日的成交极度萎缩,Amihud 值会出现「假性高流动性」。比如某只股票连续一字涨停,成交金额趋近于零,计算出的 Amihud 值趋近无穷大,这会严重污染后续回归。常见做法是两种,要么直接剔除涨跌停日,要么将 Amihud 值在 1% 和 99% 分位做缩尾(Winsorize)。我更推荐后者,因为涨跌停本身包含流动性信息,直接剔除会损失样本。计算月度指标时,放入超过 10 个有效交易日的月份,否则用月度缺失替代。

2.3 Roll 指标的理论直觉与 Stata 实现

Roll 模型的出发点是:有效价差存在时,观察到的价格变动会在买卖价之间来回跳跃,导致价格变动序列呈现负的一阶自协方差。假设潜在价值服从随机游走且买卖价差固定,则:

[ Roll_{i,t} = 2 \times \sqrt{-Cov(\Delta P_t, \Delta P_{t-1})} ]

当自协方差为正时,Roll 值定义为缺失或取 0,T+1 日按惯例取 0 处理即可。这个指标的优势是只需要日收盘价就能构造,缺点是对非同步交易敏感,小盘股容易出现正的序列相关导致估算失败。面板数据中,同一只股票不同月份的 Roll 值缺失率如果超过 30%,建议直接用 Amihud 做基准,Roll 仅做稳健性。

包内的 2023 个股流动性.xls 已经计算好了这些指标,但如果你拿到的是早期年份原始数据,用 Stata 复算时可以用下面这段代码:

* 假设数据已按股票代码和日期排序,变量为:stkcd year month date ret amount(元) gen amount_m = amount / 1e6 gen abs_ret = abs(ret) * 按月计算 Amihud bysort stkcd year month: egen amihud = mean(abs_ret / amount_m) * 按月计算换手率,turnover 为日换手率(小数) bysort stkcd year month: egen turnover_m = mean(turnover) * Roll 指标:先算日收益价差的一阶协方差 gen ret_lag = ret[_n-1] bysort stkcd: gen cov_ret = ret * ret_lag bysort stkcd year month: egen roll_cov = mean(cov_ret) gen roll = 2 * sqrt(max(0, -roll_cov)) replace roll = 0 if roll_cov > 0 & roll_cov != .

逻辑是:先统一成交金额量纲,用egen按月分组计算均值;Roll 协方差部分用滞后收益率交叉相乘再按月取均值,这里不能直接用 Stata 的correlate命令,因为面板数据跨期错位会导致协方差污染。最后replace roll = 0是为了和学术文献的常见处理保持一致。

2.4 换手率口径统一:流通股本还是自由流通股本

换手率看似简单,但数据源不同会给出完全不同的结果。Wind 默认用自由流通股本做分母,CSMAR 常用流通股本做分母,二者在有大股东持股锁定的公司上差异显著。包内数据来自 CSMAR 体系,使用说明.txt 里如果未特别注明,默认是流通股本口径。当你把这份数据和其他来源数据合并时,请务必先做口径核对:随机抽取 10 只股票,对比同一月份换手率的差值,若系统性偏高 20% 以上,大概率是分母口径不一致,不要直接混用。

3. 数据落地与面板构建:从 Excel 和 DTA 到可分析数据集

3.1 文件清单解读与数据字典设计

解压后你会看到六个文件,其中 2023个股流动性.xls 和 2023个股流动性.dta 是同一批数据的不同格式,前者方便非 Stata 用户查看,后者直接供回归使用。使用说明.txt 建议最先打开,里面通常包含字段含义、数据来源版本和更新日期。数据来源.html 是抓取页面的存档,用于回溯数据生成时间。两份 PDF 不是装饰品,温军那篇用流动性做解释变量研究股权治理,李松楠那篇把流动性当被解释变量研究价格笼子机制,正好覆盖了流动性的两类用法。

第一步建议把 Excel 转成长表(Long Format)结构。原始文件很可能是宽表——每行是一只股票在某一年的月度观测,但年份、月份横向展开。Stata 的reshape可以处理,不过我更习惯用 Python 先清洗再导出 dta,处理缺失值和字段类型更顺手。

import pandas as pd df = pd.read_excel("2023个股流动性.xls", sheet_name=0) # 假设原始列为 stkcd, name, 202301_amihud, 202302_amihud ... id_vars = ["stkcd", "name"] value_vars = [c for c in df.columns if c not in id_vars] df_long = df.melt(id_vars=id_vars, value_vars=value_vars, var_name="period", value_name="amihud") df_long["year"] = df_long["period"].str[:4].astype(int) df_long["month"] = df_long["period"].str[4:6].astype(int) df_long = df_long.dropna(subset=["amihud"]) # 对数化处理,Amihud 分布高度右偏 import numpy as np df_long["ln_amihud"] = np.log(df_long["amihud"] + 1e-10) df_long.to_stata("liquidity_panel.dta", write_index=False, version=118)

代码里用dropna过滤掉空值月份,同时取对数压缩量纲。需要注意:+1e-10不是随便加的,因为有些股票在停牌月份 Amihud 恰好为 0,直接取对数会丢失这些样本,加一个极小常量能保留它们在面板中的位置。

3.2 金融行业与 ST 股的筛选规则

做面板数据的第一道工序永远是样本范围切割。包内数据虽然整理了流动性指标,但没有告诉你应该用哪些股票做回归。我的习惯是:剔除金融行业(银行、保险、券商),因为它们的杠杆结构和流动性形成机制与其他行业差异太大;剔除 ST、*ST 股票,这类股票涨跌幅限制不同(5%),流动性指标不可比;剔除上市不满 60 天的次新股,上市初期流动性异常,换手率能到 100% 以上。

Stata 中执行筛选时需要股票的行业分类和 ST 状态变量,这两个字段不在流动性文件里,需要从 CSMAR 的「公司基本信息」表或 Wind 拉取后匹配。

use liquidity_panel.dta, clear merge m:1 stkcd using company_info.dta, keep(match) nogen keep if industry != "金融业" keep if st_status == "正常" keep if list_date != . & (year - year(list_date)) > 0

merge m:1用的是多对一匹配,因为公司信息表每个股票只有一条记录。注意匹配前确认两个文件的股票代码格式一致,CSMAR 的代码是字符串,Excel 读进来可能变成长整型,先tostring stkcd, format("%06.0f") replace统一成 6 位字符串再合并。

3.3 缺失值与极端值的处理策略

流动性指标缺失去向主要有三类:停牌日无交易、涨跌停日成交稀薄、以及早期年份部分字段未收录。停牌导致的缺失不能用插值填补,应该保留缺失状态,因为停牌背后的原因(重大资产重组、财务危机)本身影响流动性。涨跌停导致的异常值用缩尾处理,月度截面逐月做 1% 缩尾比全样本缩尾更合理,因为 2000 年和 2020 年的流动性分布完全不同。

Python 里逐月缩尾这样写:

def winsorize_series(s, lower=0.01, upper=0.99): lo, hi = s.quantile(lower), s.quantile(upper) return s.clip(lo, hi) df_long["amihud_wins"] = ( df_long.groupby(["year", "month"])["amihud"] .transform(lambda x: winsorize_series(x)) )

groupby.transform保证每月的分位数只基于当月截面计算,不引入未来信息。如果回归中的控制变量也需要缩尾,务必使用同一分组逻辑,不同变量用不同的分位点是可以的,但分组键必须统一为 year-month。

4. Stata 实证复现:用包内数据跑通流动性与公司绩效的基准回归

4.1 变量构造与描述性统计输出

温军那篇论文的核心逻辑是股票流动性通过改善股权治理影响企业绩效,李松楠那篇则关注注册制改革对流动性的冲击。用包内数据可以快速复现第一篇文章的基准回归。被解释变量选 ROA 或 TobinQ,解释变量选 Amihud(取负值或倒数,使数值越大表示流动性越好),控制变量包括公司规模(ln 总资产)、资产负债率、股权集中度、上市年限。

构造变量和输出描述性统计的 Stata 代码如下:

use clean_panel.dta, clear merge m:1 stkcd year using financial_data.dta, keep(match) nogen gen roa = net_profit / total_asset gen size = ln(total_asset) gen lev = total_debt / total_asset gen age = year - year(list_date) gen ln_amihud_neg = -ln_amihud label var ln_amihud_neg "流动性(取负Amihud, 越大流动性越好)" label var roa "总资产收益率" label var size "公司规模" label var lev "资产负债率" * 输出描述性统计表 estpost summarize roa ln_amihud_neg size lev age, detail esttab using desc.rtf, replace /// cells("mean sd min p50 max") label

代码中把 Amihud 取负是纯粹为了解释方向更直观:回归系数为正表示流动性提升 ROA。描述性统计输出用esttab转成 rtf 或 Excel,如果 Stata 没有安装 estout,先ssc install estout

这里有个容易犯的错:merge之前财务数据里的总资产单位如果是千元或万元,而 ROA 的分子是元,计算出的 ROA 会小 4 个数量级,回归系数的小数位数会非常尴尬。合并后先sum roa看一眼均值和量级,正常 ROA 应该在 0.01~0.1 之间。

4.2 面板固定效应模型与聚类标准误

基准回归用双向固定效应(公司 + 年份),标准误在公司层面聚类。温军原文用的是系统 GMM 处理内生性,但作为基准回归,双向固定效应足够说明数据质量。

xtset stkcd year * 基准回归 xtreg roa ln_amihud_neg size lev age i.year, fe vce(cluster stkcd) estimates store fe_base * 换用换手率作为流动性代理做稳健性 xtreg roa turnover_m size lev age i.year, fe vce(cluster stkcd) estimates store fe_turnover esttab fe_base fe_turnover using regression.rtf, replace /// b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) /// label scalars("N 样本量" "r2 组内R方") keep(ln_amihud_neg turnover_m size lev age)

vce(cluster stkcd)必须保留,因为同一家公司的流动性在不同年份间高度序列相关,不聚类会严重低估标准误。keep选项控制输出表格只保留核心变量,避免年份虚拟变量把表格拉得太宽。

回归结果中如果ln_amihud_neg的系数显著为正,说明流动性改善确实提升了公司绩效;如果系数不显著,先检查样本区间是否包含了 2015 年股灾和 2018 年去杠杆年份,这两个时期流动性极度收缩,可能存在非线性关系,可以考虑去掉异常年份或增加交乘项。

4.3 价格笼子政策的双重差分思路

李松楠那篇论文研究的是创业板注册制改革引入的价格笼子机制对流动性的影响,天然适合用 DID 框架。创业板在 2020 年 8 月 24 日首批注册制公司上市,同时新上市规则对存量创业板公司也施加了价格笼子约束。构建虚拟变量treat(创业板为 1)和post(2020 年 8 月后为 1),用包内数据验证改革前后的流动性变化。

gen treat = (board == "创业板") gen post = (ym(year, month) >= ym(2020, 8)) gen did = treat * post xtreg amihud_wins did treat##post size lev turnover_m i.year, fe vce(cluster stkcd)

注意treat在固定效应模型里会被公司固定效应吸收,所以只报告did的系数即可。如果did系数显著为负(Amihud 下降),说明价格笼子机制确实提升了流动性。这个设计只能作为初步探索,严格做法还要做平行趋势检验,用事件研究法画出改革前后各期的系数。以上步骤全部拆完,你已经能用包内数据独立完成从描述性统计到因果推断的完整流程。

5. 进阶处理:停牌、涨跌停与 2024 年数据的无缝衔接

拿到 2000-2023 年的数据后,下一步大概率是往 2024 年延伸,或者把流动性指标用在更复杂的模型里。这里给三个可以直接用的处理方案。

第一个是处理停牌期间的空窗。CSMAR 在停牌日不生成收益率记录,直接把月度 Amihud 的零除问题变成了缺失值。统计每月有效交易天数时,如果某月有效天数少于 10 天,该月指标直接设为缺失。用 Stata 实现是bysort stkcd year month: egen valid_days = count(date) if ret != .,然后replace amihud = . if valid_days < 10。不要用插值去补连续停牌的月份,重组复牌后第一天的收益率通常极端,单独保留会比插值更真实。

第二个是涨跌停日的识别与剔除。用日收益率超过涨跌幅限制的 95% 来近似识别涨跌停日,因为 10% 限制下真实的涨停收益率为 9.95% 到 10.05% 之间,受四舍五入影响。识别后用bysort stkcd date: gen limit_flag = (abs(ret) >= 0.095)打标,计算月度 Amihud 时剔除这些记录即可。如果想做得更细,可以结合收盘价是否封死在涨停价来判断,但这需要 Level-1 的买卖五档数据,包里没有提供。

第三个是 2024 年新数据的追加。包内数据的结构是「股票-年份-月份」长表,新的日频数据下载后,先按第 2 节的方法计算月度指标,再append到原表即可。注意新数据的股票代码格式要补齐 6 位,以及新股上市当月的换手率会异常高,建议在合并前先去检查新股样本。追加后跑一次xtset stkcd year验证面板是否平衡,xtdescribe会列出每个股票的观测次数,出现观测次数波动的板块通常就是新加数据时没对齐的样本,人工核对一遍总没错。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询