上市公司现金流分析:从docx数据提取到指标计算与财务排雷

发布时间:2026/10/10 20:23:20
上市公司现金流分析:从docx数据提取到指标计算与财务排雷
简介一份面向上市公司财务与金融实证研究的现金流指标数据集说明文档资源标签为大数据覆盖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:], columnsrows[0]) frames.append(df) df_all pd.concat(frames, ignore_indexTrue) # 数值列强制转成 float转不动的文本如--会变成 NaN for col in [数值, 金额]: if col in df_all.columns: df_all[col] pd.to_numeric(df_all[col], errorscoerce) # 单位归一如果整列数值都小于 1e7大概率是万元统一乘 1e4 换成元 if (df_all[数值] 1e7).all(): df_all[数值] df_all[数值] * 1e4逻辑说明pd.to_numeric(errorscoerce)把「暂无」「--」这类占位文本变成NaN避免整列因为混入字符串而变成object类型这一步不做后面的除法全都会报错。单位归一用的是经验判据A股公司年度营业收入几乎都大于1000万元如果整列数值都小于1000万那基本可以断定原始数据单位是万元。更稳妥的做法是看表头注释或来源说明但我一般会在清洗后抽查几行数据用「营业收入除以总资产」是否落在一个合理区间来反推单位是否统一。注意这里乘1e4会直接改变所有数值的量级执行前最好先print(df_all[数值].describe())看一眼最大值和最小值。3.3 长表转面板把科目堆叠变成「公司×年度」原始docx里的数据绝大多数是长表结构一列是公司名一列是年度一列是科目名一列是数值。分析时需要把它转成宽表每行是一家公司一个年度每列是一个科目这才是标准的分析面板。# 假设原始长表里有公司年度科目数值四列转成宽表面板 panel df_all.pivot_table( index[公司, 年度], columns科目, values数值, aggfuncfirst, # 同一单元格出现重复值时取第一个 ).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, indexFalse, encodingutf-8-sig)逻辑说明pivot_table是长表转宽表的标准手段index指定行维度columns指定列维度values指定填充数值。aggfuncfirst是为了防止同一公司同一年度同一科目在原始数据里出现多行时抛错取第一个值。关键前提是「科目」列里的文本必须和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(pctTrue) )逻辑说明第一段用中位数而不是均值是因为净现比分布里常出现净利润接近0导致比率飙到几十的极端值均值会被这类样本拉垮。中位数稳健得多。第二段是关键groupby([年度, 行业])把样本切到同年同行业的小组里rank(pctTrue)生成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_periods3) .apply(lambda s: (s 0.5).all(), rawFalse) .reset_index(level0, dropTrue) ) panel[连续三年现金流预警] bad_flag 0逻辑说明rolling(3, min_periods3)表示窗口长度三年且必须凑满三个非空值才计算避免公司上市时间短或数据缺失造成误报。apply里的lambda判断窗口内三个净现比是否全部小于0.5返回布尔值再转成0/1。参数上如果你想放宽条件比如改为「三年中至少两年低于0.5」把.all()换成.sum() 2即可。这个清单建议每周更新一次结合最新季报数据滚动跑。我自己这几年的习惯是把6.1和6.2的筛选结果做成一张固定的检查表每季度更新一次。宁可在一家「纸面富贵」的公司上错过机会也不要在现金流断裂的公司上踩雷。利润表可以被修饰现金流量表的修饰成本高得多。数据会骗人现金不会。希望帮到你。本文还有配套的精品资源点击获取