先说句实在话:我在几个常用财经数据库里翻了大半天,也没有找到一个自带“耐心资本”字段的报表。但这不代表这个概念没法落到实证里,反而说明它需要我们自己动手,从财报里一笔一笔拆出来。
所谓耐心资本投资,通俗讲就是企业把钱投到回报周期长、短期利润表上不太好看、但决定未来三五年甚至十年竞争力的地方,典型包括研发投入、长期产能建设、核心技术引进、战略股权投资等。这篇文章就以2000—2025年上市公司为样本,手把手做一套能在Stata里跑通的耐心资本投资测算流程。文章不会只丢一个高深公式,而是从口径设计、数据清洗、指标计算到常见坑位完整走一遍,适合需要建长面板做实证研究的朋友,也想给从财务角度筛选“长期主义”公司的读者一个可复现的参考脚本。
1. 耐心资本投资的测算思路:没有现成科目,就从报表里拆
在正式开始写代码之前,我得先把测算口径讲清楚。因为“耐心资本”不是会计准则里的官方概念,不同人做出来的指标很可能完全不一样,甚至得出相反结论。我的做法是把公司财报里和“长期价值创造”强相关的支出拆成三个维度,再根据研究需要选择主指标或合成指标。
第一个维度是内部创新投入,核心看研发支出。研发的钱花出去,当期利润会受影响,但新产品、新工艺、专利积累都是靠这种“看不见的资产”滚出来的。第二个维度是长期产能投入,用现金流量表里的“购建固定资产、无形资产和其他长期资产支付的现金”来度量。这个科目非常直观,企业在扩产线、建厂房、买设备,说明它在为未来做实物资本布局。第三个维度是外部战略布局,用长期股权投资的变动额来衡量。一家公司愿意长期持有一家上下游或同行的股权,通常不是为了短期炒价,而是为了产业协同和技术卡位。
| 维度 | 原始报表科目(示例) | 标准化分母 | 说明 |
|---|---|---|---|
| 研发创新投入 | 研发支出 / 研发费用 | 期初总资产 / 营业收入 | 可反映创新驱动强度 |
| 长期产能投入 | 购建固定资产、无形资产和其他长期资产支付的现金 | 期初总资产 | 最稳定的长期投资代理变量 |
| 外部战略布局 | 长期股权投资期末余额减期初余额 | 期初总资产 | 关注产业协同而非金融投资 |
主指标我一般用下面这个公式:
耐心资本投资率 =(研发支出 + 购建固定资产、无形资产和其他长期资产支付的现金) / 期初总资产
这里有个容易忽略的细节:分母我用的是期初总资产,而不是当期期末总资产。原因很简单,企业如果当年做了大额股权融资,期末总资产会快速膨胀,单纯以期末值做分母会把耐心资本投资率人为压低,造成“资金越充裕、指标越难看”的错觉。期初总资产代表的是公司年初的可支配资源基数,用它作分母更能反映企业利用存量资源进行长期布局的力度。
当然,这个主指标不是唯一答案。如果你研究的行业研发投入很少,比如传统消费或公用事业,那可以侧重长期产能投入;如果你关注的是企业对外产业整合能力,那长期股权投资变量就需要单独拿出来看。文章的代码部分会把这几个变量都生成出来,方便按需取用。
2. 原始数据清单与字段口径:先用对表,再用对代码
跑任何长面板研究,第一个拦路虎往往是原始数据表没对齐。耐心资本投资测算需要用到的数据,主要来自四类表。
第一类是资产负债表,核心字段有资产总计、长期股权投资、固定资产等。第二类是现金流量表,核心字段就是购建固定资产、无形资产和其他长期资产支付的现金,这个科目在现金流量表的投资活动部分。第三类是研发投入明细表,核心字段是研发支出金额,通常按年度披露。第四类是公司基本信息表,主要用来获取股票代码、上市日期、所属行业代码以及上市公司是否被ST/PT标记。
合并这几张表之前,有两点必须确认清楚,否则后面全白做。
第一点是报表类型,强烈建议统一采用合并报表口径。合并报表反映的是上市公司整体及其子公司的经营全貌,母公司报表只代表上市公司本部,对于集团型企业来说两者差异很大。你从数据库导出数据时,要留意“合并报表”和“母公司报表”的标记字段,数据导入后第一件事就是把报表类型筛选为合并。
第二点是年度口径,2000—2025年跨越了26年,中间会计准则发生过多次重大调整。早期企业披露“研发支出”的覆盖率和标准化程度,和后期完全不同;现金流量表科目名称也有过变化。所以建议统一按照报告期结束日期来提取年度数据,绝大多数公司是12月31日,个别非12月31日年结的公司需要单独决定取舍。
我平时整理出来的一套标准字段命名如下,后面Stata代码会直接基于这套命名来写:
| 统一变量名 | 含义 | 来源表 |
|---|---|---|
| stkcd | 证券代码(六位字符) | 基本信息表 |
| year | 会计年度 | 各报表 |
| total_asset | 资产总计 | 资产负债表 |
| lt_invest | 长期股权投资 | 资产负债表 |
| capex | 购建固定资产等支付的现金 | 现金流量表 |
| rd_exp | 研发支出 | 研发明细表 |
| opt_revenue | 营业收入 | 利润表 |
| ind_code | 行业代码 | 基本信息表 |
| list_date | 上市日期 | 基本信息表 |
| st_flag | ST/PT标记 | 基本信息表 |
如果你从CSMAR或Wind导出来的字段名是中文,不用着急,导入Stata后先rename成英文名再往下走就行。中文变量名Stata也能用,但写长命令时切换输入法很痛苦,一次性改好能省很多事。
3. Stata数据清洗:从重复值和错误口径中抢救出可用面板
这一节我按实际操作的顺序来写代码,每一步都解释为什么这么做。原始表导入后,第一步永远不是直接算指标,而是先检查数据状态。
3.1 导入与统一字段命名
* 以资产负债表为例,假设从CSMAR导出的Excel中“报表类型”字段为“报表类型” import excel "D:\patience_capital\资产负债表.xlsx", sheet("合并报表") firstrow clear rename 证券代码 stkcd rename 统计截止日期 date rename 资产总计 total_asset rename 长期股权投资 lt_invest rename 报表类型 report_type * 转换成Stata日期并提取年份 gen date2 = date(date, "YMD") format date2 %td gen year = year(date2) * 保留年报数据:绝大多数公司年报截止12月31日 keep if month(date2) == 12 keep if report_type == "合并" * 转字符串为六位证券代码,防止前面的0被吃掉 tostring stkcd, replace format("%06.0f") duplicates tag stkcd year, gen(dup_tag) list stkcd year if dup_tag > 0这里我要重点提醒一下证券代码的问题。Excel打开证券代码列时,像“000001”这类代码很容易被自动变成数字1,如果不在读取前设置文本格式,导入Stata后就会丢开头两位。最稳妥的办法是在导入前检查一次,导入后立刻用tostring补位。
重复值检查也非常关键。有时候数据库会同时在某个表里出现两条同一公司同年度的记录,可能是因为报表更新过、或者同一会计年度下出现多份报告。对于重复观测,建议先在列表中人工确认,确认只是重复后,再去重。
duplicates drop stkcd year, force3.2 多表合并成完整数据文件
拿到清洗好的资产负债表后,用同样的方式依次导入现金流量表、研发支出表、利润表和基本信息表,然后通过证券代码和年度字段进行一对一的合并。
* 假设现金流量表文件已经清洗完毕,保存为cash_flow.dta use "D:\patience_capital\balance.dta", clear merge 1:1 stkcd year using "D:\patience_capital\cash_flow.dta" keep if _merge == 3 drop _merge merge 1:1 stkcd year using "D:\patience_capital\rd_expense.dta" keep if _merge == 3 drop _merge merge 1:1 stkcd year using "D:\patience_capital\info.dta" keep if _merge == 3 drop _merge save "D:\patience_capital\full_sample.dta", replace这里用keep if _merge == 3的逻辑是:只保留在各张表里都存在的公司年度观测。如果你担心某张表缺失严重导致样本量下降,也可以把主表换成资产负债表,然后对其他表用merge m:1或keep if _merge != 2,再结合缺失情况做取舍。但研究的口径必须从头到尾一致,不能在摘要里说一套、代码里跑另一套。
3.3 样本筛选:为什么剔除金融类公司和上市初期观测
完整面板构建之后,还需要做一轮样本筛选。我的常规标准有三条,你可以根据研究目的调整。
第一条,剔除金融行业公司。银行、券商、保险公司的报表结构和一般企业差别太大,它们的“长期股权投资”口径和存货、固定资产等科目都不具备可比性。行业代码字段中,金融业通常以“J”开头,可以直接按行业代码过滤。
第二条,剔除ST/PT状态的公司观测。ST公司往往处于经营异常状态,其投资行为更多是财务救急而不是长期布局,混在样本里会污染耐心资本指标。如果数据库里没有现成的ST标记,也可以根据股票简称中包含的“ST”或“*ST”来过滤。
第三条,保留上市满三年以上的公司。耐心资本强调持续性,如果公司刚上市两三年,募投项目还在建设期,指标波动会非常大。用xtset建立面板后,可以统计每家公司的观测次数,保留至少出现过三次以上的个体。
* 剔除金融业和ST标记 drop if substr(ind_code, 1, 1) == "J" drop if st_flag == 1 * 建立面板 xtset stkcd year * 保留至少三年观测的公司 bysort stkcd: gen obs_count = _N keep if obs_count >= 3特别说明一下为什么“上市满三年”这条标准很关键。次新股上市后,账面上趴着大量募集资金,资本开支和研发支出往往远高于正常经营状态,如果把这些公司纳入计算又不做处理,行业年度均值很容易被次新股拉偏。
4. 核心测算:耐心资本主指标、备选指标和行业年度调整
数据面板整理好之后,接下来就是生成核心指标。代码本身不复杂,但每一条对应的计算逻辑和潜在陷阱,我会拆开讲清楚。
4.1 生成基础变量
use "D:\patience_capital\full_sample.dta", clear xtset stkcd year * 期初总资产 gen double total_asset_lag = l.total_asset label variable total_asset_lag "期初总资产" * 长期资产投资率 gen double long_asset_inv = capex / total_asset_lag label variable long_asset_inv "长期资产投资率" * 研发支出处理:缺失值先补0,并生成缺失标记 gen byte rd_missing = missing(rd_exp) replace rd_exp = 0 if rd_missing gen double rd_int = rd_exp / total_asset_lag label variable rd_int "研发投资率" * 长期股权投资变动率 gen double long_eq_inv = (lt_invest - l.lt_invest) / total_asset_lag label variable long_eq_inv "长期股权投资变动率" * 耐心资本主指标 gen double pat_cap = (rd_exp + capex) / total_asset_lag label variable pat_cap "耐心资本投资率=(研发支出+长期资本支出)/期初总资产"为什么要把研发支出缺失值置为0?这其实是一个容易被误解的做法。早期年份许多公司没有单独披露研发数据,严格的“什么都不做”会让这些公司直接变成缺失值,样本量大幅减少,而且容易残留的是那些恰好有研发披露的大公司,造成严重的选择偏差。相比之下,补0后至少保留了观测,同时加一个rd_missing虚拟变量,在后续稳健性检验里可以把研发缺失的公司单独拿出来对比,或者干脆对缺失率过高的年份做敏感性分析。
4.2 缩尾和标准化
长面板数据一定躲不开野值问题。有些公司可能是当年发生重大并购,资本开支一下子翻了几十倍;也有可能是数据录入错误,出现明显异常值。处理方式通常有两种:缩尾和截尾。实证中我更推荐缩尾,因为截尾会丢失样本信息,缩尾则把它们压回到合理区间。
* 安装缩尾命令 cap which winsor2 if _rc ssc install winsor2, replace * 对核心连续变量进行1%和99%分位缩尾 winsor2 long_asset_inv rd_int long_eq_inv pat_cap, suffix(_w) cuts(1 99)这里顺带提一句行业年度调整。单纯看绝对数值,不同行业的耐心资本投资率天然就不同。比如制造业的资本开支强度通常远超互联网行业,用绝对值做横向比较并不公平。因此,我会生成每个公司当年所处行业年度的相对位置指标,这样既保留了时间维度上的变化,又消除了行业固有差异。
* 行业年度中位数 bysort ind_code year: egen pat_cap_med = median(pat_cap_w) * 是否高于行业年度中位数 gen byte pat_cap_high = (pat_cap_w > pat_cap_med) if pat_cap_w != .如果你的样本量不够大,分行业年度算中位数可能会产生某些行业只有三五家公司的情况,这时可以退一步用大类行业,或者只控制行业固定效应而不做中位数分组。
4.3 合成综合耐心资本指数
主指标pat_cap已经把研发和长期资本支出一并纳入了,这能满足大多数研究需要。但如果你希望把外部战略布局的长期股权投资也融进来,可以构造一个综合指数。做法很简单:先把三个子指标分别做标准化,再加总。
* 标准化三个子指标 foreach v of varlist long_asset_inv_w rd_int_w long_eq_w { egen z_`v' = std(`v') } * 综合耐心资本指数 gen patience_index = z_long_asset_inv_w + z_rd_int_w + z_long_eq_w label variable patience_index "耐心资本综合指数"这里要注意,标准化之后的综合指数已经不是有量纲的投资率了,它的经济学含义是“该企业在长期投资维度上相对全样本的位置”。用它做分组变量回归没问题,但做描述性统计时,一定要标注清楚这是标准化得分,不能直接读成占比百分数。我自己一般会在实证里同时报告pat_cap和patience_index,前者做基准回归,后者做稳健性检验,双轨并行。
4.4 保存与导出
指标生成完毕,把需要的变量保留下来,导出成excel或者直接存成dta文件,方便后续合并其他数据。
keep stkcd year ind_code pat_cap* long_asset_inv_w rd_int_w long_eq_w patience_index order stkcd year ind_code pat_cap* save "D:\patience_capital\patience_capital_2000_2025.dta", replace * 导出excel export excel using "D:\patience_capital\patience_capital_2000_2025.xlsx", firstrow(variables) replace注意,如果你做学术研究,导出的Excel主要用于人工快速查看,最终跑回归时还是建议直接使用dta文件,避免Excel重复打开和转换造成精度损失。
5. 测算结果怎么用:描述性统计、趋势图与后续实证接口
指标算出来以后,一定要先做充分的结果检查,再进入正式分析。这一步很多人都图省事跳过,直接拿指标跑回归,结果回归出来不显著还找不出原因,问题往往就出在前面没做基础校验。
5.1 描述性统计先跑一遍
use "D:\patience_capital\patience_capital_2000_2025.dta", clear xtset stkcd year xtsum pat_cap_w long_asset_inv_w rd_int_w long_eq_w观察xtsum输出的三个部分:overall、between和within。如果between方差太小,说明各公司长期投资强度的差异不大,这个指标可能区分度不够;如果within方差太大,说明公司个体在时间维度上波动剧烈,可能受到宏观周期或并购事件影响。理性状态下,耐心资本指标的个体之间差异和时序变动都要存在,才适合做后续面板回归。
5.2 按年份画趋势
看时间趋势是长面板数据清理的最好体检方式。如果某一年突然出现断崖式下跌,大概率不是经济现象,而是数据处理出了问题。
collapse (mean) pat_cap_mean = pat_cap_w (median) pat_cap_median = pat_cap_w, by(year) twoway (connected pat_cap_mean year, lpattern(solid)) /// (connected pat_cap_median year, lpattern(dash)), /// title("上市公司耐心资本投资率年度趋势") /// xtitle("年份") ytitle("耐心资本投资率") graph export "D:\patience_capital\pat_cap_trend.png", replace width(1200)如果趋势图在会计准则变更的年份出现显著跳跃,要单独核实是真实商业周期还是统计口径变化。处理办法也很直接:把那两年分别画出来,再对比调整前后的数值,判断是否需要剔除或做分年段稳健性检验。
5.3 作为回归变量的接口
测算出来的耐心资本指标,既可以当解释变量,也可以当被解释变量。用pat_cap_high这种分组变量做实证很常见。比如检验耐心资本是否提升了企业长期价值,可以用未来一期或未来三年的托宾Q值、ROA或全要素生产率做因变量。
* 如果已安装reghdfe cap which reghdfe if _rc ssc install reghdfe, replace * 示例:高耐心资本组对未来托宾Q的影响 gen tobinq = (流通市值 + 非流通股*每股净资产 + 总负债) / total_asset reghdfe tobinq i.pat_cap_high size lev age, absorb(stkcd year) vce(cluster stkcd)这里我只用来说明测算结果的用法,实际研究中控制变量和固定效应应该根据你的研究假设来定。有一点要提醒:耐心资本指标和当期绩效变量往往存在内生性,简单回归只能得到相关性,不能直接解释成因果。如果文章层面需要更严格的因果识别,可以寻找政策冲击或行业层面的外生变量做DID设计,但这已经超出了本文代码部分的范畴。
6. 我在2000—2025年长周期测算里踩过的几个坑
前面这些都是按“理想流程”在讲,实际做的时候一定不会一帆风顺。以下是我自己在跑2000—2025年这个超长面板时反复踩过的坑,也是每一步代码背后为什么要那样写的真实原因。
6.1 研发支出大规模缺口的处理
2000年代初期的研发支出披露极不完整,大量公司没有单独的研发费用科目。如果直接把缺失研发支出当成0,会明显压低早期年份的耐心资本投资率,造成一种“近年来企业突然变长期主义”的假象。
我的处理办法是双轨制:核心回归用2007年以后的数据做,研发缺失严重的早期数据只用来算长期资产投资率,不纳入包含研发的主指标。同时生成rd_missing变量,在稳健性检验中把研发缺失公司单独控制住。这样至少可以识别出,指标变动到底来自研发投入增长,还是只是覆盖率提高。
6.2 会计制度变更带来的序列断裂
2007年前后上市公司执行的新企业会计准则在资产计量、研发费用处理、长期股权投资核算等方面都有较大变化。最典型的是研发费用中符合资本化条件的部分需要确认为无形资产,而不是全部费用化,这使得“研发支出”和“长期股权投资”两个科目的内涵在新旧准则下并不可比。
如果你硬着头皮用同一套口径跑26年,结果很容易在制度切换年份出现跳点。稳妥的办法是分阶段测算,比如2000—2006年用长期资产投资率为主指标,2007—2025年再启用包含研发支出和长期股权投资变动的完整指标。需要合并成年面板时,再根据全样本模型和分阶段模型的系数方向是否一致来判断是否可以统一处理。
6.3 合并报表与母公司报表不要混用
这个坑很低级,但发生的频率极高。有些数据库默认导出合并报表,有些默认导出母公司报表,如果中间换了一个人导出数据,或者换了数据供应商,很容易把两种口径的数据接在一起。
合并报表和母公司报表的资产总计、长期股权投资差异很大,尤其是集团型公司,母公司报表中大量子公司的经营资产并不会体现在本体的长期股权投资科目上。同一家公司,两种口径算出来的耐心资本投资率可能相差数倍。我的做法是在每次合并新表前,都检查一遍report_type字段的取值分布,并且用tab stkcd report_type抽查几家公司,确保全样本统一。
6.4 退市样本缺失导致幸存者偏差
如果你直接按当前仍在上市的公司名单抓取历史数据,那2000—2025年之间那些已经退市、被吸收合并的公司就不会出现在样本里,测算结果天然偏向“活下来”的公司。这会让耐心资本投资率的均值被高估,因为真正长期主义且生存下来的公司比例偏高。
处理思路有两条:一是尽量补全历史退市公司的财务数据,很多数据库是保留历史上市代码的,只是需要单独抓取;二是在论文或分析报告的局限性部分专门披露幸存者偏差存在的可能性。对于商业数据分析场景,如果只关注当前存量公司,也可以接受,但心里要知道这个边界在哪里。
6.5 证券代码和单位问题
证券代码被Excel变成数字,是我在答疑时遇到最多的共性问题。此外还有金额单位不一致的坑,有些表单位是元,有些表单位是万元,合并前没注意单位,跑出来的耐心资本投资率会莫名大出或小出几个数量级。
对单位问题,我惯用一个笨办法:每次合并完新表,先按同一家公司在同一年的数据交叉验证一遍。比如资产总计应该在总资产附近,资本开支不会超过总资产很多。跑两个list语句就能发现大部分低级错误,但就是这关键的几分钟,能帮你免掉后面返工几小时。
6.6 长面板缩尾要分年度做吗
文章前面用的是全样本缩尾,因为代码简单、直观。但在2000—2025年这么长的窗口期里,全样本缩尾有一个隐藏缺陷:早期年份正常值在26年全样本中可能处于较低分位,到了后期,那些早期正常值反而被缩尾处理成异常值,跨期可比性受影响。
如果你想更严谨一点,可以做分年度缩尾。思路是逐年对pat_cap进行1%和99%分位的缩尾,再合并成全样本。这样能保证每个年度的数据分布都是自洽的,尤其适合观察长期趋势的研究。缺点是为了保持跨期加总的一致性,你得再跑一遍稳健性检验,确认分年度缩尾和全样本缩尾对基准回归结论没有本质影响。我一般会把两套结果都附在附注里,这种做法在评审中也更受认可。
最后再分享一个我个人的习惯:每次跑完这套测算,我会把当年的缩尾变量分布和中间关键变量的对数图存成一份PDF,按年份存档。因为代码过三个月再看,哪怕有注释也容易忘了当时为什么做了某些特殊处理,但看到图、看到分布,上下文马上就能捡回来。做长面板数据,真正厉害的不是跑出某个回归系数,而是让任何一段数据都经得起别人从头到尾复现和推敲。