
简介一份面向金融数据研究者的资源文档内含百度网盘分享链接及提取码可获取1991—2024年6月沪深北上市公司财务指标现金流分析数据。数据按季度整理覆盖沪深北证A股主板、中小企业板、创业板、科创板字段涵盖净利润现金净含量、营业收入现金含量、营业利润现金净含量、折旧摊销、自由现金流、营运指数、现金再投资比率等多项现金流指标并区分TTM滚动口径适合用于公司财务研究、量化建模与投资分析。压缩包共1个docx文件体积仅51KB借助其中的网盘链接即可下载Excel、DTA格式数据文件及说明文档方便不同软件工具直接使用。目前已有144人学习/浏览该类资源可作为财务分析、论文写作与数据清洗的便捷数据入口。1. 一份数据看懂 A 股三十年现金流1991 到 202406 的季度指标库做财务实证的人应该都有过这种经历为了算一个「净利润现金净含量」得先把三大报表手工对齐再处理经营现金流与净利润在不同口径下的正负号问题一套流程走完大半天没了。而这份资源直接整理了 A 股市场所有上市公司从 1991 年到 2024 年 6 月的季度现金流专项指标包含净利润现金含量、营业收入现金含量、营运指数、自由现金流等几十个字段且同一指标同时给出本期值和 TTM 滚动值配套 Stata 的 dta 与 Excel 两种格式。对写论文的、做财务排雷的、搭基本面量化模型的从业者来说这是把基础数据准备工作大幅缩短的现成底稿。我第一次拿到时就在想如果早几年有这份表很多个熬夜对数的晚上都能省下来。2. 先看清字段再动手指标命名规则、三类口径和数据范围2.1 数据集组成与统计范围两个文件、四组字段这份资源是 2 个文件的压缩包一份 Stata 的 dta 格式一份 Excel 格式。dta 是为了直接喂给 Stata 做面板回归不用再经历 csv 导入的编码折腾Excel 格式则是给 Python、R 或者干脆用 Excel 透视表做筛选的人准备的。数据内容完全一致只是载体不同。很多数据库只提供 csv 或 xlsx拿到手还得转格式这份省了那一步。字段可以分成两组一组是样本标识与分类字段包括 Stkcd股票代码、ShortName股票简称、Accper统计截止日期、Typrep报表类型编码、Indcd 与 Indnme行业代码与行业名称、Source公告来源另一组是现金流专项指标以 F06 开头的字段占了绝大部分。基础字段决定你怎么做面板主键、怎么做固定效应分组指标字段决定你能算哪些比率、哪些必须自己再加工。数据范围方面统计的是 A 股市场上市公司覆盖主板、中小企业板、创业板、科创板等板块。时间跨度从 1991 年到 2024 年 6 月季度粒度。1991 年前后证券市场刚起步早期样本自然稀疏这不是数据缺失而是市场发展阶段如此。做描述性统计时如果画全样本时间趋势1990 年代那几年的样本量会低得吓人很容易被误判成数据质量问题。字段名中文名典型取值与使用场景Stkcd股票代码6 位数字面板主键第一维度ShortName股票简称做展示和去重辅助Accper统计截止日期季度末日期如 2024-06-30面板主键第二维度Typrep报表类型编码区分合并报表与母公司报表处理前先查看取值分布Indcd / Indnme行业代码 / 行业名称做行业固定效应注意分类标准跨年调整2.2 字段命名规则F06 前缀、B/C 结尾和两套口径看字段列表能发现一个规律所有指标字段都以 F06 开头后面跟 6 位数字再以 B 或 C 结尾。以 F060101B 和 F060101C 为例字段名一模一样只有结尾字母不同。熟悉金融数据库命名习惯的人会立刻明白B 多半是当前报告期的取值C 多半是 TTMTrailing Twelve Months滚动值。为什么要有这样一对字段因为现金流指标有两类用法做横截面比较时用本期值就够了做时序分析时则需要 TTM把季节周期性消掉。例如一季度的经营活动现金流天然偏低直接用单季值对比不同公司的净利润现金含量会得到系统性偏差改用 TTM 口径相当于把过去四个季度滚动加总季节因素被抹平。数据集里大部分指标同时提供 B 和 C 两个版本省去了自行滚动的麻烦。还要注意有些指标出现了「1」「2」两个编号例如 F061301B 公司现金流 1 与 F061302B 公司现金流 2。这意味着该指标存在两套计算口径。常见的情况是口径 1 采用早期的自由现金流定义口径 2 采用更严格的定义比如扣除利息费用、考虑营运资本变动后的版本。具体到某个数据库哪个是旧哪个是新最好的办法是拿一家有完整年报披露的公司自己动手算一遍做比对而不是背公式。字段清单里同时出现 F061501B 公司自由现金流原有和 F062401B 企业自由现金流说明数据库保留了两代算法版本做跨年份纵向研究时尤其要留意这一点。2.3 三类现金流指标口径含量类、自由现金流类和综合质量类把几十个 F06 字段按业务含义归类可以分为三类。第一类是现金含量类核心是「经营现金流除以某个利润或收入口径」。代表字段包括 F060101B 净利润现金净含量、F060201B 营业收入现金含量、F060301B 营业收入现金净含量、F060401B 营业利润现金净含量。这类指标回答的问题是账面上的利润到底收回了多少现金。净利润现金净含量大于 1说明利润基本有现金支撑小于 1 甚至为负则需要警惕应收堆积或利润质量的问题。第二类是自由现金流类包括 F061301B 与 F061302B 公司现金流 1/2、F061401B 与 F061402B 股权现金流 1/2、F061501B 公司自由现金流原有、F061601B 股权自由现金流原有、F062301B 股权自由现金流、F062401B 企业自由现金流。自由现金流类指标在估值模型里是核心输入但各家数据库算法差异非常大使用前必须确认它是否扣除了维持性资本支出、是否包含利息税盾。第三类是综合质量类包括 F061701B 全部现金回收率、F061801B 营运指数、F061901B 资本支出与折旧摊销比、F062001B 现金适合比率、F062101B 现金再投资比率、F062201B 现金满足投资比率。这些指标大多是现金流与资产、资本开支、再投资需求之间的比值常用于判断一家公司维持现有经营需要消耗多少现金、新增投资对现金流的依赖程度。做财务排雷时现金再投资比率长期偏低往往意味着扩张靠外部融资而非内生造血。字段名中文名一般算法与使用说明F060101B/C净利润现金净含量经营现金流除以净利润衡量利润含金量净利润为负时失真F060201B/C营业收入现金含量销售商品收到的现金除以营业收入衡量收入收现程度F060301B/C营业收入现金净含量经营现金流净额除以营业收入综合收现与付现能力F061701B全部现金回收率经营现金流除以总资产体现资产整体的现金回收速度F061801B营运指数经营现金流除以经营所得现金反映营运资本变动的影响F062101B现金再投资比率经营现金流扣除股利后除以再投资资产衡量内源扩张能力表格里写的是通用解释不代表该数据集的精确算法。我在拿到任何现金流数据库时都会先做一次字段核对再开始建模否则后面所有结论都可能建立在错误口径上。3. Stata 把面板数据洗干净use、xtset 和 TTM 校验三步3.1 打开 dta 文件use、describe、list 三连如果装的是 Stata打开这份 dta 文件非常直接。把压缩包里的 dta 解压到工作目录然后执行* 打开 Stata 数据文件 use 上市公司财务指标现金流分析_1991_202406.dta, clear * 查看变量数量、观测数量和存储类型 describe * 预览前 5 条记录 list Stkcd ShortName Accper Typrep F060101B F060101C in 1/5use 命令的 clear 选项用于把内存里的旧数据清掉避免残留数据集影响判断。describe 输出里重点看两处观测数是不是符合「公司数 × 报告期数」的数量级变量中有没有存储类型为 str 的字段——比如 Stkcd 若是字符串后面 xtset 之前要先 destring。list in 1/5 只渲染前 5 条大文件千万不要直接 list几万行的列表刷出来会把 Stata 界面卡住这是新手最容易翻车的地方。如果 Stkcd 在描述里显示为字符串类型需要转成数值* 股票代码转数值去掉可能存在的空格并转换 destring Stkcd, replace * 再次确认转换结果 tab Stkcddestring 的 replace 选项是就地覆盖原变量。有些供应商会把 Stkcd 导出成带前导零的字符串destring 后前导零消失但 6 位代码本身不受影响。做完这一步再看一眼 tab Stkcd确认没有出现缺失值。3.2 构造面板主键Accper 解析与重复值处理面板回归最怕主键混乱。Stkcd 和 Accper 合起来应该是「公司 × 报告期」的二维主键但在实际数据里经常出现重复。先做重复检测* 统计按股票代码、报告期、报表类型分组的重复记录 duplicates report Stkcd Accper Typrep * 查看前 20 组重复样本 duplicates list Stkcd Accper Typrep in 1/20duplicates report 会直接输出按 Stkcd、Accper、Typrep 三列分组后的重复次数。如果报告里有大量 duplicate别急着 drop先看多出来的记录是不是 Typrep 不同——一个公司同一天可能同时披露合并报表和母公司报表这正是上一章说过的报表类型编码造成的。这时应该按研究目的保留一种口径而不是机械去重。Accper 是日期字段但在 dta 中有可能是字符串。先 inspect 确认格式* 确认 Accper 的取值格式 inspect Accper如果是带横杠的标准日期格式用下面的方式转换成 Stata 日度日期再声明面板* 字符串日期转 Stata 日度日期 gen report_date date(Accper, YMD) format report_date %td * 声明面板主体是股票代码时间维度是报告日期 xtset Stkcd report_datedate() 的 YMD 参数告诉 Stata 按年-月-日解析。如果是纯数字 20240630把参数改成 YMD##。转换后做一次 assert report_date .确保所有日期都成功解析。xtset 声明时如果报「repeated time values within panel」说明主键仍然不唯一回到 duplicates 环节把 Typrep 纳入主键或者明确保留合并报表记录后重新去重。这里有个细节财务数据库的 Accper 通常就是季度末那天同一公司一年最多 4 条记录用日度日期做主键不会产生频率问题。做高频因子时如果另接日行情数据这份表需要先折叠到公司-日期粒度再与行情 merge别反过来用行情的每条交易日去 join 季度数据那样会造出大规模笛卡尔积。3.3 验证 B 与 C 的口径年报样本对照拿到字段后不要急着跑回归先验证自己的假设。「B 是本期值、C 是 TTM 滚动值」这个判断在年报观测上有一个天然的验证点年报的累计期间正好是一年理论上 B 与 C 应该相等或非常接近。用下面的代码做一致性检查* 生成年报标识日期字符串的第 6、7 位是 12 gen is_annual substr(Accper, 6, 2) 12 * 只保留年报样本做相关性检验 corr F060101B F060101C if is_annual * 看差异分布 gen diff F060101C - F060101B if is_annual sum diff, detailcorr 给出两个字段的相关系数若接近 1说明 B/C 命名逻辑符合预期。sum diff, detail 输出差异的百分位数如果中位数在 0 附近但有少量极端离群值多半是当年发生了报表追溯调整或数据修正。遇到这种观测处理办法是保留原始字段不要手工改数在回归中加一个「是否年报且被追溯调整」的哑变量作为稳健性检验。如果检查发现 B 与 C 差异系统性存在那就需要反过来思考也许 B 指的是单季值而不是累计值。判断方法也很简单把同一公司一年内四个季度的 B 相加与年报的 B 对比单季口径下四季之和约等于年报累计口径下四季度末值直接等于年报。这一步等于给数据库的字段口径做了一次逆向工程做完之后才能放心使用。提示字段口径校验是拿到外部数据库后最值得花时间的一步。我一般会随机抽三家公司分别覆盖制造业、金融业和亏损企业手工复算后再批量处理。4. Python 读 dta 后怎么直接用日期解析、同比计算与样本筛选4.1 用 pandas 直接读取 dta环境准备与类型检查没有 Stata 使用许可的团队用 Python 操作这份数据同样顺手。pandas 的 read_stata 函数原生支持 dta 文件不需要额外装驱动。读取代码很短import pandas as pd # 读取 Stata 格式数据 df pd.read_stata(上市公司财务指标现金流分析_1991_202406.dta) # 查看数据规模和字段类型 print(df.shape) print(df.dtypes)read_stata 会把 dta 里的变量标签转成 DataFrame 的列名值标签则转换成 category 类型的列。print(df.dtypes) 的目的是看 Accper 是不是被读成了 object 字符串、Stkcd 是不是被读成了整数。这两个字段是面板主键类型判断直接影响后面的日期解析和质量控制。如果发现某些指标列被读成了 float64 但大量缺失是正常的——早期年份很多公司没有披露现金流附表字段留空是当时披露规则导致的结果不是文件损坏。只有当你发现 2020 年后仍然大面积缺失时才需要警惕。读取时还有一个可选参数# 关闭自动值标签转换保留原始编码数值 df pd.read_stata(上市公司财务指标现金流分析_1991_202406.dta, convert_categoricalsFalse)convert_categoricalsFalse 会把原本带值标签的分类列读成整数。对于 Typrep 这种报表类型字段如果你需要比较编码 1 和编码 2 的差异关闭自动转换反而更安全避免 pandas 把不同年份的标签统一映射造成错位。4.2 日期解析与季度样本筛选两种字符串格式的兼容主键字段 Accper 在 dta 里可能是字符串Python 侧同样要转成日期类型。这一步看起来简单却是整个分析里出错率最高的地方——因为日期格式可能是 2024-06-30 或者 20240630 两种pd.to_datetime 的默认行为对前者友好对后者经常需要显式传 format。# 尝试自动解析失败则手动指定格式 try: df[report_date] pd.to_datetime(df[Accper]) except ValueError: df[report_date] pd.to_datetime(df[Accper], format%Y%m%d) # 派生年度、季度、月份字段 df[year] df[report_date].dt.year df[quarter] df[report_date].dt.quarter df[month] df[report_date].dt.monthtry/except 是应对供应商格式不统一时最简单的兜底策略。注意 to_datetime 默认会把 2024-06-30 解析成功但遇到 20240630 会直接抛异常或输出错误日期所以先自动解析一次再手动补格式是稳妥做法。生成 year、quarter、month 三个派生字段是为了后面筛选年报季、中报季时不用反复截取字符串。筛选 2018 年之后所有中报样本# 提取 2018 年及以后的中报统计截止日期为 6 月观测 mid df[(df[year] 2018) (df[month] 6)] # 按年度和行业看中报样本量 print(mid.groupby([year, Indnme]).size())month6 是按统计截止日期筛选而不是按披露日期。很多公司年报实际披露在次年的 4 月但 Accper 是上一年的 12 月 31 日两者不要混用。如果你的研究关心「公告及时性」需要另找公告日期字段这份数据里的 Source 只是公告来源不包含披露日期。4.3 计算同比增速用 merge 自连接代替 shift计算现金流指标的同比增长新手最容易写成 df.groupby(Stkcd)[F060101B].pct_change(4)这在数据完全平衡的面板上勉强可用但一旦某个公司中间缺了季度shift(4) 就会拿错期数。更稳的做法是用自连接把同一份数据自己往过去平移一年然后按公司加报告期对齐。# 保留需要的列 base df[[Stkcd, report_date, F060101B, F060101C]].copy() # 构造上年同期副本 lag base.copy() lag[report_date] lag[report_date] - pd.DateOffset(years1) lag lag.rename(columns{F060101B: F060101B_lag}) # 按股票代码和报告期合并 merged base.merge(lag[[Stkcd, report_date, F060101B_lag]], on[Stkcd, report_date], howleft) # 计算同比增速 merged[yoy] merged[F060101B] / merged[F060101B_lag] - 1这段代码的关键是 DateOffset(years1)它把副本里的报告日期强行拨回一年前然后 merge 自然找到上年同期的指标值。相比 shift自连接不受中间缺失季度影响能做严格的上年同日对齐。计算出来的 yoy 会有两类极端值一类是上年同期为 0 或缺失导致的 NaN另一类是分母很小造成的巨大倍数使用前需要单独处理。对于分母小于等于 0 的观测常见做法是先标记再看分布。我一般会把带 _lag 后缀的列直接 join 进来再用分位数截断处理极端值避免把样本均值拉偏。如果要做 TTM 同比那就直接用 F060101C 替换 F060101B 重跑一遍两个字段口径不同正好可以互为稳健性检验。5. 避坑现金流数据实证分析的六条血泪经验5.1 Typrep 编码为什么 Stkcd 加 Accper 去重后还有重复现象按 Stkcd 和 Accper 去重发现多出不少重复记录直接扔进 xtset 报错。原因Typrep 区分报表类型同一个公司在同一报告期同时存在合并报表和母公司报表两条记录。如果只按 Stkcd 加 Accper 做主键就会被当成重复值。解决先查看 Typrep 的取值分布确认编码含义。常见模式是 1 表示合并报表、4 表示母公司报表但也可能直接用 A、B 字母。做大多数研究时保留合并报表口径即可做资本结构与集团内部往来研究时才需要母公司报表。确定后按 Stkcd 加 Accper 加 Typrep 重新定义主键或者直接过滤保留需要的 Typrep 再 xtset。5.2 B 结尾字段是累计值别当单季值直接用现象用 F060101B 算季度环比得到的中报环比数值异常大一季报又异常小。原因国内财报采用累计披露规则——一季报是 1 到 3 月累计中报是 1 到 6 月累计三季报是 1 到 9 月累计。B 结尾字段大概率对应这类累计口径直接相邻季相减得不出单季值。解决单季值等于本期末累计值减上期末累计值。如果想把四年报拆成单季必须手工做差值如果直接用 TTM 字段 C则不存在这个问题因为滚动 12 个月天然消掉了累计效应。建议在论文里明确写清楚用的是累计口径还是 TTM 口径避免审稿人追问。5.3 202406 不是整年数据别把最新样本当成完整年度现象2024 年的观测数量比前一年少一大截描述统计里各年样本量断崖。原因数据更新截止到 2024 年 6 月 30 日最新一批观测是中报而非年报。同一自然年里年报样本覆盖全部公司中报样本虽然也接近全部公司但后续年份没有年报面板必然是非平衡的。解决做面板回归前先画一个 report_date 的频数图确认各期观测数。用非平衡面板估计时固定效应模型能容忍这类缺失但做描述统计均值比较时要标注数据截止日。稳健性检验可以选择统一用 2023 年 12 月 31 日之前的样本避免把期末数据形态变化混入研究结论。5.4 行业代码跨年修订直接做行业固定效应会出错现象同一家公司不同年份的 Indcd 前后不一致行业固定效应的分组样本发生跳变。原因行业分类标准在 2012 年前后、2019 年前后都有过修订公司自身也可能因为主营业务变化被重新分类。解决做行业固定效应前先按 Stkcd 分组取每家公司最新一期的 Indcd 作为面板统一行业归属如果研究期跨越分类标准修订年份建议在稳健性检验里用 Indnme 行业名称重新映射到某个统一版本。别直接用原始 Indcd 跑全样本否则同一家公司在两个分类标准下会被当成两家不同行业的公司。5.5 净利润现金净含量为负可能是亏损公司现象描述统计里 F060101B 出现大量负值有人把它当成数据错误直接剔除。原因净利润现金净含量等于经营现金流除以净利润。净利润为负时这个比值会失真——亏损公司的净利润现金净含量往往是个负数绝对值大小没有经济含义不能和盈利公司放在一起排序。解决先按净利润正负分组看分布再做选择。研究盈利质量时只保留净利润为正的样本或者对亏损样本单独设哑变量。对连续变量统一做 1% 与 99% 分位的截断处理能减少极端值影响但解决不了符号语义问题。5.6 Excel 打开 dta 乱码用数据导入而不是直接双击现象直接双击 dta 文件Stata 能打开但中文标签变成问号有人转成 xlsx 后中文也乱码。原因dta 文件内部使用 Stata 的编码体系Excel 默认按系统 ANSI 读取转 csv 时如果不指定编码中文字段名会变成乱码。解决不要直接双击优先在 Stata 里打开原文件再另存为 xlsx用 Python 转换时指定 encodinggb18030 写 csv或者让 pandas 直接读写 dta 避免中间格式转换。Excel 端用「数据」菜单里的「自文件」导入并手动选择编码 UTF-8 或 GB18030也能解决大部分乱码。6. 进阶把现金流指标变成可落地的量化信号数据准备工作做完这份资源真正值钱的地方在于可以快速往策略或研究里落地。这里给出两个我自己常用的验证与构造方法。6.1 用企业自由现金流收益率做横截面打分F062401B 企业自由现金流是估值模型里最核心的分子。用企业自由现金流除以总市值就得到自由现金流收益率# 假设已经从行情数据合并出了 total_mv 列 df[fcff_yield] df[F062401B] / df[total_mv] # 每个报告期、每个行业内做百分位排名 df[score] df.groupby([report_date, Indnme])[fcff_yield].rank(pctTrue)fcff_yield 相当于把利润表的操纵空间换成现金流口径再做一次相对估值rank(pctTrue) 把原始比率映射到 0 到 1便于跨行业比较。使用前要过滤掉 F062401B 缺失、净利润为负或市值小于等于 0 的反常观测。筛选后score 接近 1 的组合可以当作现金流质量最高的分组配合 F060101B 净利润现金含量做二次过滤能规避只看盈利增速带来的暴雷风险。6.2 手算 TTM 与自带 C 字段互验自带 TTM 字段是数据库供应商的口径用之前值得自己动手算一遍。国内季度报表采用累计口径正确的 TTM 公式是当期累计值加上上年年报累计值再减去年上年同期累计值。注意不是简单的四期滚动因为每年一季报会把累计数重置# 按公司和日期排序保证 shift 指向正确的上一期 df df.sort_values([Stkcd, report_date]) # 上年同期累计值 df[B_lag4] df.groupby(Stkcd)[F060101B].shift(4) # 上年年报累计值按公司、年份单独取出并合并 annual_df df[df[month] 12][[Stkcd, year, F060101B]].rename( columns{year: prev_year, F060101B: B_annual_prev} ) df[prev_year] df[year] - 1 df df.merge(annual_df, on[Stkcd, prev_year], howleft) # 自算 TTM 并与字段 C 对比 df[ttm_manual] df[F060101B] df[B_annual_prev] - df[B_lag4] df[ttm_diff] df[ttm_manual] - df[F060101C] print(df[ttm_diff].describe())shift(4) 取的是四个报告期之前的上年同期值关键是上年年报必须单独取不能直接依赖固定 shift。如果 ttm_diff 的均值与标准差都接近于 0说明自带 C 字段口径与常规累计法一致如果差异系统性存在就要回去看数据说明而不是盲目信任字段标签。从那以后我每次拿到新的金融数据库第一件事永远是画报告期分布、查看 Typrep 取值再挑几个有完整年报披露的公司手算一次关键指标确认口径无误后才敢往下跑。把字段背后的口径搞清楚这份资源才算真正属于自己。希望帮到你。资源获取链接: https://pan.baidu.com/s/11COISQsQCw2XOjZGBMolQA 提取码: dhhb本文还有配套的精品资源点击获取