简介:一份面向上市公司财务与金融实证研究的现金流指标数据集说明文档,资源标签为大数据,覆盖1991年至2024年6月沪深北A股季度数据,基于年报及公告整理,包含净利润现金净含量、营业收入现金含量、营业利润现金净含量、折旧摊销、公司自由现金流、股权自由现金流、现金再投资比率等数十项指标,同时附股票代码、行业代码、报表类型等辅助字段,适合进行面板回归、盈利质量评估与资本结构研究。文档包仅含1个docx文件,大小51KB,内部提供百度网盘链接与提取码,可下载Excel和dta两种格式的数据文件及对应说明,方便Excel、Stata等不同工具读取分析。目前已有144人浏览学习,适用于需要批量获取标准化现金流数据的分析师、研究生或高校师生。获得文档后可直接获取字段含义说明和原始数据,字段与数据文件配套使用,无需自行识别报表口径;省去逐份年报手工提取的繁琐流程,大幅提升数据清洗与建模前准备的效率。
1. 一份 1991-202406 的上市公司现金流数据:它到底能拿来干什么
上市公司财务指标与现金流分析,跨度从1991年到2024年6月,基本覆盖了A股市场的完整历史。这份docx多半是按年度或按公司组织的报表科目汇总和派生指标,最直接的用处有三件事:给单家公司做现金流质量体检、在同行业里横向排雷、为量化模型提供现金流因子原料。适合看的人包括写财报分析的分析师、做实证研究的学生,以及所有被「利润很好但账上没钱」坑过的投资者。但网盘分享链接随时可能失效,文件格式也未必规范,真正值钱的是背后的分析方法——从拆字段、算指标到避坑,这才是下文要讲透的东西。
2. 拆开这份数据的结构:字段、口径与取数逻辑
拿到任何一张表,我第一件事不是跑代码,而是先搞清楚它是什么口径。现金流数据尤其如此,字段名差一个字,结论可能完全相反。这一章把最关键的三个结构问题说清楚:三大项目怎么切分、用合并报表还是母公司报表、1998年之前的数据为什么有断层。
2.1 现金流量表三大项目:经营、投资、筹资怎么切分
现金流量表把公司的现金变动分成三类。经营活动的核心子科目是「销售商品、提供劳务收到的现金」和「经营活动现金流量净额」,前者代表卖货真正收回来的钱,后者代表主业造血后的净剩余,是整个分析的主角。投资活动主要看「购建固定资产、无形资产和其他长期资产支付的现金」,也就是资本开支,代表公司是在扩张产能还是在收缩。筹资活动则看「取得借款收到的现金」和「偿还债务支付的现金」,反映公司对外部资金的依赖程度。三者用途整理如下:
| 现金流量表项目 | 核心子科目 | 分析用途 |
|---|---|---|
| 经营活动 | 销售商品、提供劳务收到的现金;经营活动现金流量净额 | 判断主业造血能力 |
| 投资活动 | 购建固定资产、无形资产支付的现金;收回投资收到的现金 | 判断扩张还是收缩 |
| 筹资活动 | 取得借款收到的现金;偿还债务支付的现金 | 判断外部融资依赖度 |
分析的时候三大项目必须合起来看。一个典型的健康画像:经营净额持续为正,投资净额为负说明在投产能,筹资净额有正有负是阶段性融资和还债的交替。反过来,如果经营净额连续为负、筹资净额持续为正,说明公司在靠输血活着,这种公司不管利润表多好看都要降权。实操中我还常用到一个派生值:自由现金流等于经营活动现金流量净额减去购建固定资产无形资产支付的现金,它比净利润更硬,是估值时常用的分母,后面算指标会频繁用到。
2.2 合并报表与母公司报表:分析必须用哪张
A股上市公司年报会同时披露合并现金流量表和母公司现金流量表,做现金流分析必须用合并口径。原因不复杂:母公司报表不并表子公司,母公司账上收到的可能只是子公司分红上来的现金,真正的经营流入、资本开支都在子公司层面。如果你用母公司口径去算净现比,会出现分红大年指标暴涨、平时数字很难看的情况,完全没法做连续对比。
数据里怎么辨认口径?看字段名。带「合并」前缀的是合并报表取数,带「母公司」或「公司」字样的是母公司口径;有些整理好的docx会把两张表拆成不同编号的表格,甚至分别放在不同Sheet里。我在这上面踩过一次坑:某次分析一家集团公司的净现比,连续三年为负,查了半天发现取的是母公司表,换成合并口径之后指标立刻恢复正常。现在的习惯是分析前先跑一句字段名检查,确认数据来自合并报表再往下走,这一步花十秒钟,能省后面十个小时的排查时间。
2.3 1998 年前的现金流数据:为什么会有断层
这份数据标称从1991年开始,但这里有一个绕不开的事实:A股上市公司从1998年年报起才被要求编制现金流量表,1991到1997年之间披露的是「财务状况变动表」,两者的编制基础完全不是一回事。也就是说,正式、可比、经过审计的现金流量表数据,市场层面只有1998年之后的;任何1991到1997年的现金流原始科目,要么是数据整理方用其他科目估算出来的,要么是从审计报告附注里手工扒出来的,口径五花八门。
这个断层直接影响数据怎么用。如果你拿这份文件做从1991年起的连续时间序列回测,前七年基本是噪声,算出来的均值、标准差都会失真。正确做法是把样本起点放在1998年甚至2000年之后,1991到1997年的数据只当背景参考,别进模型。验证方法也简单:随机抽一家1995年前上市的老公司,去翻它1997年的年报原文,看有没有「现金流量表」这个章节——大概率是没有的。这一点确认之后,你再回头看标题里那个1991,就知道前七年要打一个问号。
3. 从 docx 提取现金流数据:python-docx 解析脚本与清洗流程
这份文件是docx而不是csv或数据库导出,说明分享者大概率是从年报或某个数据终端手工整理、再粘贴进Word的。好消息是docx里的表格能被python-docx直接读取,不需要人工复制。这一章给出从解析到清洗到面板化的完整流程,每一步都附代码和参数说明。
3.1 用 python-docx 批量读取表格并检查结构
拿到文件先别急着算指标,第一步是摸清楚docx里到底有几张表、每张表的表头长什么样。很多整理型docx的结构是混乱的:有的表是「科目×年度」的矩阵,有的是一张表只装一年的数据,还有的是每家公司单独一张表。先打印表头,能避免后面所有列名匹配的错误。
from docx import Document doc = Document("上市公司财务指标现金流分析1991-202406.docx") # 遍历文档里的所有表格,打印表号和表头 for t_idx, table in enumerate(doc.tables): header = [cell.text.strip() for cell in table.rows[0].cells] print(f"表号 {t_idx},表头:{header},总行数:{len(table.rows)}")这段脚本只做一件事:把每张表的表头和前几个单元格打出来。逻辑上,doc.tables返回文档里全部表格对象,table.rows[0]取第一行作为表头,cell.text.strip()去掉单元格文本两端的换行和空格。参数上唯一要改的是文件路径,如果你的文件名不一样,直接替换Document()里的路径即可。看到输出后,记下哪几张表是现金流量表科目、哪几张是利润表和资产负债表科目,下一步合并才有依据。
3.2 数值清洗与单位归一:把「万元」与「元」拉齐
表头确认之后,把所有表格读成DataFrame拼在一起,然后做数值转换和单位统一。这两个问题不解决,后面算出来的指标全是错的。
import pandas as pd frames = [] for table in doc.tables: rows = [[cell.text.strip() for cell in row.cells] for row in table.rows] df = pd.DataFrame(rows[1:], columns=rows[0]) frames.append(df) df_all = pd.concat(frames, ignore_index=True) # 数值列强制转成 float,转不动的文本如"--"会变成 NaN for col in ["数值", "金额"]: if col in df_all.columns: df_all[col] = pd.to_numeric(df_all[col], errors="coerce") # 单位归一:如果整列数值都小于 1e7,大概率是万元,统一乘 1e4 换成元 if (df_all["数值"] < 1e7).all(): df_all["数值"] = df_all["数值"] * 1e4逻辑说明:pd.to_numeric(errors="coerce")把「暂无」「--」这类占位文本变成NaN,避免整列因为混入字符串而变成object类型,这一步不做,后面的除法全都会报错。单位归一用的是经验判据:A股公司年度营业收入几乎都大于1000万元,如果整列数值都小于1000万,那基本可以断定原始数据单位是万元。更稳妥的做法是看表头注释或来源说明,但我一般会在清洗后抽查几行数据,用「营业收入除以总资产」是否落在一个合理区间来反推单位是否统一。注意这里乘1e4会直接改变所有数值的量级,执行前最好先print(df_all["数值"].describe())看一眼最大值和最小值。
3.3 长表转面板:把科目堆叠变成「公司×年度」
原始docx里的数据绝大多数是长表结构:一列是公司名,一列是年度,一列是科目名,一列是数值。分析时需要把它转成宽表,每行是一家公司一个年度,每列是一个科目,这才是标准的分析面板。
# 假设原始长表里有"公司""年度""科目""数值"四列,转成宽表面板 panel = df_all.pivot_table( index=["公司", "年度"], columns="科目", values="数值", aggfunc="first", # 同一单元格出现重复值时取第一个 ).reset_index() # 只保留现金流分析最核心的几个科目 key_cols = ["公司", "年度", "销售商品提供劳务收到的现金", "经营活动现金流量净额", "营业收入", "净利润", "负债合计"] panel = panel[[c for c in key_cols if c in panel.columns]] # 存成 UTF-8-BOM 编码,Excel 打开不会乱码 panel.to_csv("cashflow_panel.csv", index=False, encoding="utf-8-sig")逻辑说明:pivot_table是长表转宽表的标准手段,index指定行维度,columns指定列维度,values指定填充数值。aggfunc="first"是为了防止同一公司同一年度同一科目在原始数据里出现多行时抛错,取第一个值。关键前提是「科目」列里的文本必须和docx里完全一致,比如「经营活动现金流量净额」和「经营活动产生的现金流量净额」就差几个字,直接导致匹配失败,所以前面3.1打印表头那步不是白做的。参数上,key_cols可以按你的分析需要增删,想做偿债分析就把「负债合计」「资产总计」加进去,想做盈利质量就把「净利润」留在列表里。utf-8-sig是给Excel用的编码,如果你只在自己代码里读,改成utf-8也行。
4. 现金流核心指标计算:比率公式、阈值参考与分组对比
数据变成面板之后,接下来就是算指标。现金流指标不比利润指标,它的口径更多、对业务的解释力更强,但也更容易算错。这一章给出四个最常用的比率,每个都附公式、参考区间和Pandas实现。
4.1 收现比与净现比:现金流质量三兄弟怎么算
收现比和净现比是最基础、也最常被引用的两个现金流质量指标。收现比看的是收入变成现金的效率,净现比看的是利润的现金含量,两者结合基本能判断一家公司的利润是不是「纸面富贵」。
# 收现比 = 销售商品提供劳务收到的现金 / 营业收入 panel["收现比"] = panel["销售商品提供劳务收到的现金"] / panel["营业收入"] # 净现比 = 经营活动现金流量净额 / 净利润 panel["净现比"] = panel["经营活动现金流量净额"] / panel["净利润"]逻辑说明:两个比率都是简单的除法,但分母的处理有讲究。净现比在净利润为负时没有解释意义,计算前最好先把净利润小于等于0的样本标记出来,单独看经营现金流的方向,而不是硬算比率。收现比的分子一定要用「销售商品、提供劳务收到的现金」,不能用「经营活动现金流入小计」,因为后者包含了税费返还、政府补助等非销售流入,会把比率撑高。参考区间方面,长期收现比低于0.7说明收入大量沉淀在应收账款里;净现比落在0.8到1.2之间大致健康,连续多年明显偏离这个区间,就需要回到报表附注找原因。
4.2 现金债务总额比与销售现金比率:偿债与盈利质量
现金流不光看盈利质量,还看偿债能力。现金债务总额比是经营现金流对总债务的覆盖程度,销售现金比率则衡量每1元收入能沉淀多少经营现金,这两个指标在信用分析里出场频率很高。
# 现金债务总额比 = 经营活动现金流量净额 / 负债合计 panel["现金债务总额比"] = panel["经营活动现金流量净额"] / panel["负债合计"] # 销售现金比率 = 经营活动现金流量净额 / 营业收入 panel["销售现金比率"] = panel["经营活动现金流量净额"] / panel["营业收入"]逻辑说明:现金债务总额比的核心用途是和融资成本对比。如果一家公司的这个比率常年低于它的平均融资成本,说明经营现金流连利息都覆盖不了,债务只会越滚越大。销售现金比率是毛利率之外看生意本质的另一个视角,它剔除了折旧摊销这些非现金项目的影响,零售、快消这类现金生意通常比率偏高,重资产行业偏低。参数上没有特殊设置,但要注意负债合计必须和经营现金流取自同一张合并报表,混用母公司负债和合并经营现金流是常见错误。
4.3 分年度、分行业的分位对比:Pandas 实现
指标算完,直接比较绝对值没有意义。正确的做法是分年度、分行业做分位对比,看一家公司的现金流指标在同年同行业里处在什么位置,这比用统一阈值打分可靠得多。
# 先按年度看净现比的中位数,避免被极端值带偏 year_med = panel.groupby("年度")["净现比"].median() print(year_med) # 再按"年度+行业"分组,给每家公司算净现比的行业内百分位 panel["行业净现比分位"] = ( panel.groupby(["年度", "行业"])["净现比"] .rank(pct=True) )逻辑说明:第一段用中位数而不是均值,是因为净现比分布里常出现净利润接近0导致比率飙到几十的极端值,均值会被这类样本拉垮。中位数稳健得多。第二段是关键,groupby(["年度", "行业"])把样本切到同年同行业的小组里,rank(pct=True)生成0到1之间的百分位排名,0.9意味着该样本处在行业前10%。参数上,「行业」列需要你事先准备好,常见做法是按交易所行业分类或常用的申万行业分类去匹配,匹配不到的统一归到「其他」。分位算完之后,判断标准从「净现比>1」这种绝对阈值,变成「连续三年行业分位低于0.3」这种相对标准,后者在实际排雷中更不容易误伤。
5. 上市公司现金流分析避坑:四个把结论带偏的口径与数据陷阱
现金流分析里翻车,绝大多数不是模型问题,而是数据口径和业务理解问题。这一章写四个我实际踩过的坑,每条按「现象→原因→解决」来讲,你可以直接对照自己的数据检查。
5.1 2007 年新旧准则切换:同一科目前后口径断裂
现象:某公司2006年经营活动现金流量净额1.2亿,2007年突然变成3.5亿,同一年营收只涨了15%,怎么看都不合理。
原因:2007年执行新会计准则,现金流量表的列报规则变了,部分原来计入经营活动的项目被重分类到筹资或投资活动,比如借款利息的处理方式发生变化。很多数据库导出的历史数据在切换年份没有做口径统一,导致同科目前后不可比。
解决:以2007年为分界,把样本分成两段做对比,不要直接用全区间做趋势线。更稳妥的做法是尽量用对口径变化不敏感的比率,比如收现比,它的分子分母都是销售类科目,受重分类影响小;而净现比这类跨类别比率,在2007年前后对比时要格外小心。
5.2 净利润为正、经营现金流为负:纸面富贵的典型特征
现象:一家公司连续两年净利润为正,且增速不错,但经营活动现金流量净额是负的,看利润表觉得是好公司,看现金流觉得要破产。
原因:利润是按权责发生制确认的,只要确认了收入就能记账,钱没收到也算利润。常见情形是放宽信用政策大量赊销、应收账款堆积,或者主动向渠道压货、存货占款。利润表是纸面富贵,现金流量表才是真金白银。
解决:不要单看一年,把连续三到五年的经营现金流净额加总,再和同期净利润加总对比,算累计净现比。如果累计值长期低于0.5,直接把这家公司放进预警清单。这里顺带说一个玄学经验:利润连年涨、现金流连年跌的公司,后面多半要出事,早晚而已。
5.3 「收到其他与经营活动有关的现金」被做大:收现比虚高
现象:某公司收现比连续多年大于1.3,看着销售回款非常好,但资产负债表上的货币资金并没有同步增长,应收账款也没降。
原因:收现比的分母是营业收入,如果分子用的是「经营活动现金流入小计」,就会把与销售无关的钱也算进去。常见操作是把政府补助、关联方资金往来、保证金退回塞进「收到其他与经营活动有关的现金」这个科目,把总流入做大。这是现金流指标里最容易踩的数据陷阱。
解决:分子一律用「销售商品、提供劳务收到的现金」,不用「经营活动现金流入小计」。同时定期拉出「收到其他与经营活动有关的现金/经营活动现金流入小计」这个占比,如果超过两成,就要去财报附注里看这一项到底是什么,很多美化现金流的案例都藏在这一行。
5.4 一刀切阈值跨行业套用:地产与零售完全不是一种生物
现象:用统一的净现比阈值给所有行业打分,结果制造业公司大量被预警,某地产公司反而显示「健康」,结论和直觉完全相反。
原因:行业商业模式决定了现金周期。地产公司从拿地到回款要两三年,期间经营现金流常年为负是常态;零售、餐饮公司当天卖货当天收钱,净现比天然偏高。拿制造业的阈值去套地产公司,等于拿体温计去量血压,工具不对。
解决:放弃绝对值阈值,改用同年同行业分位。4.3里算的「行业净现比分位」就是干这个的:看一家公司在同行里处在什么位置,而不是和某个拍脑袋的1.0比。阈值可以保留,但只作为初筛,真正下单前一定要回到行业维度做二次确认。
6. 进阶用法:用净现比背离信号做财务排雷
指标算完之后,单看某一年没有意义,要会看趋势和背离。我最常用的是两个排雷信号,操作简单,但命中率不低。
6.1 背离信号一:净利润增长但经营现金流连续下滑
利润和现金流同向变动是正常的,一旦出现净利润连续两年增长、经营现金流连续两年下滑的背离,说明利润质量在变差。常见解释是收入确认激进、回款周期拉长或存货积压。下面的代码可以自动把这类公司筛出来:
# 按公司+年度排序,计算经营现金流净额的年度同比变化 panel = panel.sort_values(["公司", "年度"]) panel["ocf_yoy"] = panel.groupby("公司")["经营活动现金流量净额"].pct_change() panel["profit_yoy"] = panel.groupby("公司")["净利润"].pct_change() # 净利润同比为正、经营现金流同比为负,标记为背离样本 divergence = panel[(panel["profit_yoy"] > 0) & (panel["ocf_yoy"] < 0)]逻辑说明:pct_change()默认计算与上一年的同比变化,groupby("公司")保证变化只发生在同一家公司内部,不会跨公司乱算。过滤条件用利润正增长加现金流负增长的交集。参数上,pct_change()会把第一年数据变成NaN,分析时记得dropna()。这个方法只适合连续年度数据,如果面板里有缺年份,最好先按公司补全年度序列再算。
6.2 背离信号二:连续三年净现比低于 0.5 的预警清单
净现比低一年可能是季节性波动,低三年就是系统性问题。连续三年净现比低于0.5,基本可以判断公司利润的现金含量长期不足,挣的是账面利润。筛选逻辑用滚动窗口实现:
# 每个公司按年度排序,看近三年净现比是否全部低于0.5 panel = panel.sort_values(["公司", "年度"]) bad_flag = ( panel.groupby("公司")["净现比"] .rolling(3, min_periods=3) .apply(lambda s: (s < 0.5).all(), raw=False) .reset_index(level=0, drop=True) ) panel["连续三年现金流预警"] = bad_flag > 0逻辑说明:rolling(3, min_periods=3)表示窗口长度三年,且必须凑满三个非空值才计算,避免公司上市时间短或数据缺失造成误报。apply里的lambda判断窗口内三个净现比是否全部小于0.5,返回布尔值再转成0/1。参数上如果你想放宽条件,比如改为「三年中至少两年低于0.5」,把.all()换成.sum() >= 2即可。这个清单建议每周更新一次,结合最新季报数据滚动跑。
我自己这几年的习惯,是把6.1和6.2的筛选结果做成一张固定的检查表,每季度更新一次。宁可在一家「纸面富贵」的公司上错过机会,也不要在现金流断裂的公司上踩雷。利润表可以被修饰,现金流量表的修饰成本高得多。数据会骗人,现金不会。希望帮到你。
本文还有配套的精品资源,点击获取