这份2000-2022年上市公司对外开放程度数据包,我前前后后用了差不多一个多星期才彻底吃透。最初拿到它是因为研究需要引入上市公司国际化程度的控制变量,结果发现手头现有的数据库要么是截面数据,要么区间对不上,要么指标口径完全不是我想要的。后来找到这份资源,它同时包含原始数据、计算代码和最终结果,正好覆盖我需要的时间跨度,解决了我最头疼的"从哪拿数据""怎么算出口占比"这两大问题。
简单介绍一下这份数据的价值:它基于沪深A股上市公司公开披露的年报信息,整理了2000年至2022年共23个年度的对外开放相关字段,并通过统一的代码逻辑计算出了一个适合面板数据回归的"对外开放程度"指标。也就是说,不管你是做公司金融、国际贸易与企业国际化研究,还是写论文需要一个现成的企业层面开放度变量,这份数据都可以直接接入。我后续会详细拆解它的构成、指标背后的度量逻辑、计算流程以及实际使用时容易踩的坑,希望能帮你省下那些重复造轮子的时间。
1. 这份数据包的真实构成:先弄清楚里面有哪些东西
拿到数据包,第一步不是急着跑回归,而是先把目录结构和字段搞清楚。很多朋友上来就merge,结果变量对不上、年份不连续,回头又找我排查,其实都是忽略了文件设计逻辑。
1.1 数据文件的组织方式与使用逻辑
整个数据包解压后,大致是这么几个部分:
| 目录/文件 | 内容说明 | 使用阶段 |
|---|---|---|
原始数据/ | 上市公司基础财务数据、分地区收入数据原始导出文件 | 数据清洗与核验 |
计算代码/ | 包含Stata和Python两个版本的计算脚本 | 自行复现时直接运行 |
结果数据/ | 清洗合并后生成的面板数据文件(dta/csv) | 实证回归时直接读取 |
它把文件按"输入-处理-输出"三层展开,这一点对我这种喜欢验证每一步逻辑的人来说非常友好。我能先看原始数据长什么样,再跑一遍代码,最后对照结果数据是否一致,整个流程是可审计的。
这里要提醒一句:不要只看最终结果文件就直接写回归代码,至少花半小时把原始数据里的缺失模式和年份覆盖情况摸清楚。因为结果数据中的缺失值大量来自早期年份上市公司信息披露不完整,这个背景信息会直接影响你后续做描述性统计时对样本量的判断。我刚开始没注意,结果跑最小二乘回归时一次性丢掉了近两成样本,折腾了半天才意识到问题不在模型,而在数据筛选。
1.2 对外开放程度的具体指标口径与字段解释
数据中的核心变量是foc_d_i(对外开放程度综合指标)和几个辅助变量。其中最重要的基础指标是"境外收入占营业总收入的比例",再结合"是否具有境外业务"虚拟变量以及"外资持股比例"做交叉补全。
具体关键字段如下:
stkcd:股票代码,用于与CSMAR、Wind等其他数据集匹配year:会计年度,覆盖2000-2022foc_revenue_ratio:境外收入占比,取值为0-1foc_dummy:是否有境外业务,1为有,0为无foc_foreign_share:外资持股比例,来自前十大股东中境外法人或自然人持股合计foc_d_i:对外开放程度综合得分,范围0-100,用于回归分析
我在实际做论文回归时,直接使用foc_d_i作为被解释变量或解释变量都没有问题。不过要注意,不同指标的分布差异很大。比如早期2000到2005年,foc_revenue_ratio的缺失率可能超过40%,因为当时有不少公司只披露境内收入,没单独拆分海外部分。如果你直接删掉缺失值,样本就会明显向大型出口企业倾斜,产生样本选择偏误。这一点在后文我会专门讲处理策略。
2. 对外开放程度的度量逻辑:为什么是这套指标而不是别的方法
很多人会用"出口额占营业收入比重"来代表企业对外开放程度,这个思路没有错,但它只覆盖了出口这一个维度。数据包中的综合指标其实重新定义了度量框架,需要理解背后的逻辑。
2.1 主流测量方法的三种思路对比
学术界对企业对外开放程度的量化,大体可以归为三种路径:
- 出口强度法:用境外收入/出口额占营业总收入的比重来衡量。优点是数据容易获取,上市公司年报基本都会披露分地区收入;缺点是忽略了很多仅有非出口形式国际化经营的企业,比如境外子公司、技术授权、跨国并购等。
- 国际化深度法:参考国际化深度指标,即海外子公司数量、海外资产占比、海外雇员占比等。理论上最能反映企业融入全球市场的真实深度,但问题是数据极难获取,尤其是2000-2010年的披露很不规范,手工搜集成本极高。
- 综合评分法:将多种原始信息统一标准化后合成综合指标。样本覆盖面更广,兼顾了企业出口行为和外资参与度,同时缓解了单一指标口径过窄的问题。
这份数据包采用的是第三条路径的简化和优化版,核心逻辑是:"境外收入占比"作为连续变量保留,如果该值缺失但公司在年报中明确提到有境外业务(比如境外子公司收入或以分地区披露但未列金额),则用foc_dummy和外资持股等辅助信息插补,最终形成**主指标foc_revenue_ratio+辅助指标foc_dummy+综合指标foc_d_i**三层结构,既照顾了数据连续性,又不牺牲指标解释力。
2.2 选取综合指标的依据与边界条件
综合指标foc_d_i的计算方式,实际上是先对foc_revenue_ratio进行95%分位缩尾处理,再进行极差标准化,将其转换为0-100的数值;同时引入两个微调项:一是如果企业当年聘用了境外高管或存在境外直接投资,加5分;二是如果企业完全没有境外业务,则直接记为0分。
这个设计有个很明显的优势:它区分了"没披露"和"确实没有境外业务"这两种不同状态。如果是纯粹用境外收入占比,没披露和等于0在数据里长一个样,但经济含义完全不同。综合指标则可以通过foc_dummy把"披露了但没有境外业务"的企业正确归零,防止下拉缺失值造成假零值。
边界条件是,这套指标只在上市公司层面有效,不适用于非上市公司或金融行业(银行保险类公司的对外开放逻辑与非金融企业差异太大)。如果你用的时候恰好把金融类公司放进样本,建议直接剔掉,或者单独做稳健性检验。我个人的习惯是全样本跑一次,剔除金融业再跑一次,对比系数方向与显著性是否一致,一致才敢往下写。
3. 从枯燥的年报数据到最终指标:核心计算流程全拆解
这一节是数据包的核心价值所在,也是我花时间最多的部分。很多人手里有原始数据但不会算,卡在第二步处理。数据包自带的代码实现了整套清洗、合并和计算逻辑,我在此把关键步骤逐一拆开讲一遍。
3.1 原始数据导入与清洗的关键操作
首先一定要把股票代码统一格式。CSMAR导出的股票代码有时是纯数字,有时带后缀(比如"600519.SH"),Wind的格式又不一样。代码里用了格式统一函数,这在合并多个数据源时非常必要。
输入数据需要做五个关键处理,按顺序分别为:
- 将财务数据和分地区收入数据分别导入,统一日期格式
- 对股票代码做标准化处理:删除字母后缀,仅保留6位数字代码
- 剔除2000年之前上市的公司(非必须,看研究设计)
- 剔除ST及退市公司样本(回归时通常剔除)
- 按照
stkcd和year唯一标识去重,保留首次出现值
有些公司的年报会对应两个不同的数据库记录,比如注册资本变更后乱入一条重复记录,不去重会导致多对多合并,你的样本量会莫名其妙翻倍。不少朋友遇到合并后样本量远超实际公司数量的情况,原因就在这里。
3.2 对外开放程度指标的代码实现
我用Stata和Python分别跑过这套逻辑,核心代码逻辑是相通的。以下是Stata版本中计算境外收入占比的核心部分:
* 以stock code和year为唯一匹配键,合并财务数据与收入明细 merge 1:1 stkcd year using foreign_revenue_data.dta * 剔除没有匹配上的非上市公司数据 keep if _merge == 3 * 生成对外开放程度基础指标:境外收入/营业总收入 gen foc_revenue_ratio = foreign_revenue / total_revenue if ...... replace foc_revenue_ratio = 0 if foc_revenue_ratio == . & foreign_revenue == 0 * 生成是否存在境外业务虚拟变量 gen foc_dummy = (foc_revenue_ratio > 0) if foc_revenue_ratio != . replace foc_dummy = 1 if ......Python版本逻辑也是如此,我用pandas的merge加上groupby操作实现同样结果:
import pandas as pd import numpy as np # 数据读取与合并 fina = pd.read_csv('fina_data.csv', dtype={'stkcd': str}) foreign = pd.read_csv('foreign_revenue.csv', dtype={'stkcd': str}) # 关键匹配键为股票代码+年份 df = pd.merge(fina, foreign, on=['stkcd', 'year'], how='inner') # 计算对外开放程度基础指标 df['foc_revenue_ratio'] = df['foreign_revenue'] / df['total_revenue'] df['foc_revenue_ratio'] = df['foc_revenue_ratio'].replace([np.inf, -np.inf], np.nan) # 缺失值处理:境外收入为0时,比值直接赋0 df.loc[df['foreign_revenue'].fillna(0) == 0, 'foc_revenue_ratio'] = 0注意一点:merge之前最好用df['stkcd'].str.zfill(6)把股票代码统一补到6位数字,否则"000001"和"1"会被当成两个不同的公司,这是我早期吃过亏的地方。
3.3 数据质量核验:怎么确认算出来的结果是对的
代码跑完不等于数据可靠,关键要核验。数据包附带了一段质量核验脚本,它的逻辑就是对照原始年报公开数据随机抽样验证。
具体核验方法我建议分三步:
- 第一步,核对总样本量。2000-2022年A股上市公司累计大概在5000家左右,如果你算出来只有2000条,说明合并逻辑丢了大量样本;如果超过8000条,则可能存在重复匹配或合并键设错。
- 第二步,抽查特定公司年度值。比如你知道某公司在某年境外收入占比大概是多少,就直接筛选它的记录看代码值是否一致,误差超过0.01就要回头检查计算逻辑。
- 第三步,看变量分布。
foc_revenue_ratio的分布应呈右偏态,即在0附近集中,尾部逐步减少。如果大量企业等于1或者整体均匀分布,大概率是数据处理出了问题。
数据包很贴心地把校验结果也附在了文件里,你可以直接对比自己跑出来的结果与原始结果文件是否完全一致。如果一致,说明复现成功。
4. 用这套数据做实证研究:适用场景与最容易踩的坑
数据本身是死工具,怎么用出价值才是关键。这一节我结合自己做实证的经验,总结这套数据在主流量化研究里的典型应用方式,以及实际跑数据时最容易遇到的那些问题。
4.1 适合延伸的研究方向与常见模型
对外开放程度在企业金融和公司治理研究中的使用频率很高,常见的有以下几类:
- 对外开放与企业绩效:以
foc_d_i为核心解释变量,研究它对企业全要素生产率、利润率或股价表现的影响。样本区间正好覆盖中国加入世贸组织前后的关键时间段,有较强的政策含义,但这个话题要注意避免涉及时政讨论。 - 数字化与企业国际化:用数字化转型指数与对外开放程度做交互项,检验数字化能力对海外市场拓展的放大效应。我最近就在做这个方向。
- ESG表现与国际化经营:对外开放程度作为调节变量或分组变量,观察企业环境、社会与治理表现在不同国际化水平下的定价差异。
在模型设定上,因为对外开放程度是典型的公司层面特征变量,基本都用面板固定效应模型,控制公司与年份固定效应,标准误聚类到公司层面。可以参考以下Stata结构:
xtset stkcd year xtreg y foc_d_i x1 x2 i.year, fe vce(cluster stkcd)在Python中用linearmodels包也能实现类似操作,核心原则是企业和年份双向固定效应不能省,否则估计系数会被遗漏变量严重干扰。
4.2 缺失值、极端值与样本选择:处理经验分享
这套数据最大的坑集中在缺失值处理上。前面提过,2000-2005年境外收入披露不全,早期缺失率明显偏高。很多人直接丢掉缺失值,结果样本严重偏向了那些规模大、国际化程度高的企业。
我的经验做法是:
- 缺失但明确提到境外业务:先用
foc_dummy标为1,再用行业同年度平均值插补foc_revenue_ratio,这样可以保留样本量,又不至于把缺失值当成0。 - 完全不披露分地区收入:如果公司年报中连分地区信息都没有,大概率境外业务占比极低。可以稳健性检验中用0填充。
- 极端值处理:
foc_revenue_ratio小于0或大于1的异常值直接删除,大于0.9的做缩尾处理到95%分位数。如果不对极端值做处理,回归系数会被少数超高国际化企业严重影响。
因为早期数据含有大量0值,我建议在回归中额外控制一个"是否披露境外收入"的虚拟变量,这样能把真正的0和缺失填补的0区分开,减少估计偏误。这个细节很多文献里不提,但在审稿人眼中是加分项。
4.3 稳健性检验的替代指标建议
如果能拿到不同口径的数据,强烈建议换指标做一套稳健性检验。除了数据包里的foc_revenue_ratio,还可以尝试:
- 用"境外所得税占比"反推收入结构,部分企业会在报表附注中披露境外分支机构的所得税贡献,这是很好的替代数据。
- 用"海外子公司数量",可以通过企查查或年报关联交易列表手工构建。虽然工作量较大,但样本如果有500家以上,足以支撑子样本检验。
- 用"外币收入折算比例":部分上市公司会用不同币种披露收入结构,这项数据可以用来构造连续型的国际化深度指标。
我自己的经验是,主回归用foc_d_i,稳健性检验换foc_revenue_ratio和foc_dummy,三个指标结果方向一致,审稿人那边基本不会在这个环节刁难你。
5. 最后聊聊我在实际操作中的几点体会
这套数据真正帮我省下的不只是整理时间,更是对"对外开放程度"这个看似简单概念的重新理解。没有哪个指标是完美的,境外收入占比简洁但遗漏了国际化深度,综合评分全面但解释稍弱。数据包把两种思路都做出来了,让研究者可以根据自己的场景灵活选择。
有两个小技巧,算是我自己趟出来的经验,分享一下。
第一个是关于代码的可复现性。拿到数据后,别急着跑结果,先修改路径设置,保证原始数据、代码和结果三个文件夹的相对路径不出错。我建议直接把整个文件夹放到一个固定的项目目录里,并在代码开头用cd或设置干净的工作目录。否则改一次路径就要改几十个地方,很容易出错。
第二个是关于数据的分年使用。2000到2005年数据质量相对弱,近年来质量明显提升。如果你的研究不涉及早期阶段,建议直接使用2010年之后的子样本,数据完整度会高很多。如果需要全样本,建议在回归中加入年份固定效应和分行业趋势项,用来吸收早期信息披露质量差异带来的系统性影响。
另外提醒一句:数据包中的foc_d_i是标准化后的综合得分,它的大小只在相对意义上可比,不能直接解读为"对外开放程度的绝对水平"。在论文写作时,最好说明指标是经过标准化处理的,这样读者才不至于误解数值的含义。
最后说一句,如果做论文用这份数据,引用或致谢时最好注明数据来源和计算逻辑,既是对数据整理者的尊重,也方便其他研究者复核结果。数据整理不易,且用且珍惜。