☰
CnOpenData港股利润表数据全解析:科目差异、指标计算与避坑指南
2026/10/12 5:43:38 网站建设 项目流程

做港股上市公司盈利分析的第一步,从来都不是跑模型,而是先解决数据问题。我过去几年一直在和各类公司财务数据打交道,经常遇到一种情况:从数据库里导出“利润表”,满心欢喜开始跑回归,结果发现科目口径对不上、财年错位、币种混用,整套结果推倒重来。直到我认真用了一遍CnOpenData 港股上市公司利润表数据集,才真正把这条流水线理顺。

这篇文章以我自己的实际使用经历为线索,把港股利润表的科目逻辑和A股差在哪、CnOpenData 这个数据集到底做了什么标准化、拿到手之后怎么读取和计算常用指标、以及几类非常容易踩的坑,一次性说清楚。不管你是做学术研究的硕博生、搞基本面量化的分析师,还是刚开始接触港股财务数据的学生,下面的内容基本都能直接照着用。

1. 港股利润表和A股根本不是同一套玩法:科目体系的底层差异

1.1 港股利润表的完整链路:从营业额到每股盈利

先说最基础的问题:港股上市公司披露的利润表,长什么样?

港股财报遵循香港财务报告准则(HKFRS),和内地企业会计准则(CAS)在“要不要单列某些科目”“某些科目怎么归并”上差别很大。一份典型的港股合并利润表,从上到下大概是这么一条链路:

  • 营业额(Turnover),部分公司叫“收益”“收入”或“总收入”
  • 销售成本(Cost of Sales)
  • 毛利(Gross Profit)
  • 其他收入及收益(Other Income and Gains)
  • 销售及分销成本(Selling and Distribution Expenses)
  • 行政开支(Administrative Expenses)
  • 财务成本(Finance Costs)
  • 应占联营公司及合营企业损益(Share of Results of Associates and Joint Ventures)
  • 除税前溢利(Profit before Taxation)
  • 税项(Taxation)
  • 期内溢利(Profit for the Period)
  • 本公司拥有人应占溢利(Profit Attributable to Owners of the Company)
  • 非控股权益应占溢利(Profit Attributable to Non-controlling Interests)
  • 每股盈利(Earnings per Share)

注意“溢利”就是内地说的“利润”,“除税前溢利”类似A股的利润总额。港股最底部一定给两行归属:股东应占和少数股东应占,而且每股盈利是只按“股东应占溢利”来算的。

1.2 和A股对比,差在哪几个关键位置

内地A股上市公司按《一般企业财务报表格式》披露利润表,大致是:

  • 营业收入(含主营业务收入、其他业务收入)
  • 营业成本
  • 税金及附加
  • 销售费用、管理费用、研发费用、财务费用
  • 其他收益、投资收益、公允价值变动损益
  • 营业利润
  • 营业外收入、营业外支出
  • 利润总额
  • 所得税费用
  • 净利润(归属于母公司股东/少数股东)

逐项对过去,差异非常明显。

研发费用:A股从2018年起把研发费用从管理费用里单列出来,港股绝大多数公司没有这一行,研发开支要么塞在行政开支里,要么只在附注里单独披露。所以如果直接用港股利润表做“研发强度”分析,这个字段大概率是空的,得去附注找。

税金及附加:A股利润表里“税金及附加”是营业收入的减项,港股利润表上没有这个单列项,消费税、城建税等通常归入销售成本或行政开支。这导致同样一家公司在两地报表里,毛利口径会有差异。

其他收入的范围:港股利润表里的“其他收入及收益”是个大筐,政府补助、利息收入、租金收入、汇兑收益、出售资产收益都可能装在里面,并不等于A股“其他收益”科目。做盈利质量分析时,不拆出来很容易高估经常性盈利能力。

应占联营公司损益:A股把按权益法核算的联营企业投资收益放在“投资收益”里,港股直接单列一行“应占联营公司及合营企业损益”,位置在财务成本之后、除税前溢利之前,性质上属于投资收益,但不并入营业利润。

营业利润这个“中间量”:A股利润表有“营业利润”这个环节,港股没有统一要求。很多港股公司会在毛利和除税前溢利之间标一个“经营溢利”(Operating Profit),但这不是所有公司都列,口径也不完全一样。跨公司比较时,最好自己重新定义“经营溢利 = 毛利 + 其他收入 - 销售分销成本 - 行政开支”,而不是直接用披露值。

1.3 为什么不能直接拿原始年报来做研究

有人会说:“这些差异我都能处理,直接去港交所披露易下载年报手工录不行吗?”理论上可以,实操上非常痛苦。

不同公司的科目命名不统一。同样是收入,有的公司写“营业额”,有的写“收益”,有的用英文Revenue,有的用Turnover。老牌港资公司偏向用“营业额”,新经济公司更爱用“收入”,如果不做同义词映射,Excel里光是VLOOKUP都要断好几层。

不同公司会自行调整披露层级。港交所对利润表披露格式没有像内地那样严格的统一模板,公司可以在准则允许范围内增删科目。比如有些地产公司会单列“投资物业公允价值变动收益”,有些把它挤在“其他收入”里,这直接影响到利润结构分析的准确性。

很少人意识到,港股并不要求所有上市公司都用HKFRS。部分公司按IFRS编报,和HKFRS实质趋同但科目名称可能不同;还有少数在港上市的内地公司直接按CAS编报,利润表长得和A股一模一样,这对“统一处理”造成很大干扰。

所以核心矛盾是:港股利润表的原始披露“长得太自由”,而研究工作需要的是“整齐划一的字段”。把原始披露变成整齐划一的字段,本身是个费时费力又不产生研究价值的环节,而标准化数据集存在的意义,就是替你把这个环节做掉。

2. CnOpenData 港股利润表数据集:它把标准化做到了哪一步

2.1 先搞清楚这张表的覆盖范围

我拿到的 CnOpenData 港股上市公司利润表数据,覆盖了港交所主板和创业板(GEM)的全部上市公司,时间跨度从各公司上市披露首份年报开始,一直滚动更新到最近一个完整财报期。需要说明的是,不同版本的数据在起始年份上可能不一样,早年间港交所电子化披露不完善,部分早期数据只覆盖到2000年前后;用的时候第一步先画出“公司数×年份”的覆盖图,确认样本范围再往下走。

数据来源以公司在港交所披露的定期报告为主,包括年报、中报以及创业板公司需要披露的季度报告,同时经过整理和交叉校验。CnOpenData 的做法比较接近“学术数据库”的定位:他们不做原始文本堆砌,而是把报表里的信息结构化,输出成能直接读入统计软件的表。

2.2 标准化字段的设计逻辑

这个数据集最值钱的地方不是“把数字从PDF里扒出来”,而是它把几百家公司的披露习惯统一成一套字段体系。我实际使用下来,标准化逻辑主要体现在以下五条:

第一,科目归并。原始报表里“营业额”“收益”“收入”“Revenue”,统一归到同一个收入字段;不同公司对销售成本的叫法差异也被抹平。

第二,利润链路一步不跳。从营业收入开始、销售成本、毛利、各类费用、财务成本、应占联营损益、除税前溢利、税项、净利润、归母净利润,每个环节都有一个对应字段。这样做的好处是,计算任何中间指标都不用回头翻原始报表。

第三,币种字段保留。港股公司里有很多收入以人民币计价、报表以港元列示,数据表里会保留原始币种标记,方便用户按需换算。

第四,基础信息配套。每行记录不只是一个数字,而是带着股票代码、公司简称、行业分类、财报期截止日、报告类型(年报/中报/季报)、公告日期、审计意见等配套信息。这些看起来不起眼,却是后面做面板数据合并的关键键值。

第五,归属口径明确。净利润会区分“归母净利润”和“少数股东损益”,每股收益提供基本和稀释两列,避免用户自己从净利润推算时出错。

提示:实际字段名在不同版本的数据文档里可能有差异,拿到数据后先找对应的字段说明表,把“中文字段名—英文变量名—原始报表科目”三者对应关系核对一遍,再用。

2.3 和“自己爬数据”“商业终端导出”的对比

我身边不少朋友喜欢自己从披露易爬年报,或者找商业金融终端导出。这条路到底值不值得走,我给一个直观对比:

方案时间成本资金成本标准化程度可复现性数据溯源
自己爬披露易+手工录入极高低低差清楚
商业终端导出低非常高中等一般不好回溯
科研数据平台低中等高好有版本可追溯

商业终端导出的最大问题是,它更像“查询快照”,今天导和三个月后导可能拿到不同版本,而且终端字段是面向投资分析的,不一定按学术研究的口径定义字段;自己爬数据虽然灵活,但一个年报季几千份财报的清洗工作量非常夸张,而且年报PDF格式五花八门,解析错误率很难控制。

科研数据平台的优势在于“批量标准化”:它已经把跨公司、跨年度的口径统一好了,还保留底层版本信息,这对实证研究的可复现性特别重要。当然也有代价——如果想拿某个细分科目(比如从“其他收入”里拆出政府补助),标准化表通常帮不了你,还得回原始报表。

3. 拿到表格先核对一遍:核心字段逐个拆解

3.1 从营业收入到净利润:每个环节对应什么

拿到数据之后,先别急着算指标,把核心字段都过一遍。以我常用的字段清单为例,大体可以分成四组:

收入与毛利层:营业收入、销售成本、毛利。毛利率 =(营业收入 - 销售成本)/ 营业收入,这里的营业收入是“合并利润表口径的营业总收入”。有些港股公司会把利息收入做到“其他收入”,如果你的研究对象是银行或金融公司,这个字段的语义完全不同,要格外小心。

费用与经营利润层:销售及分销费用、行政开支、财务成本、其他收入。港股普遍没有“研发费用”字段,如果研究需要,一般通过附注补。这里的“财务成本”对应A股的“财务费用”但内容更窄,通常只包括利息支出和融资成本,汇兑损益经常被归入其他收入或行政开支。

税前利润与净利润层:除税前溢利、所得税费用、净利润、归母净利润、少数股东损益。“除税前溢利”和A股“利润总额”基本对应,但税项的包含范围在两个准则下有细微差异,主要影响在递延所得税的披露习惯上。

每股指标层:基本每股收益、稀释每股收益。港股利润表会把“每股盈利”单独列示,部分公司还会披露“每股股息”。注意每股收益的分子只能是“归母净利润”,用净利润总额算出来的结果会和披露值对不上。

3.2 港股特色科目,别拿A股习惯去套

数据里有两个港股特色科目,值得单独强调。

第一个是“应占联营公司与合营企业损益”。它代表公司按权益法核算的联合营企业投资收益,在利润表上排在财务成本之后、除税前溢利之前。这个科目的波动性通常很高,如果某一年联营公司爆雷,它会直接把利润表拉下来一大截。做盈利预测时,我习惯把“经常性经营利润”和“应占联营损益”分开看,不要把联营公司的利润波动当成主营业务波动。

第二个是“其他收入及收益”里的公允价值变动、投资物业重估、出售资产收益等项目。港股对投资物业的公允价值变动非常普遍,房地产公司经常用这个科目调节利润。标准化数据集通常不会帮你把这些细分项拆出来,想区分“经营利润”和“非经营利润”,要么在数据里寻找更细的字段,要么回去查附注。

3.3 容易被忽略的基础信息字段

很多人在数据清洗阶段只保留代码和数字,把“财年截止日”“报告类型”“公告日期”这些字段直接扔掉,这是非常可惜的。

“财年截止日”决定你以后所有同比、面板匹配的基准。港股上市公司财年截止日非常分散:大量内地企业是12月31日,但不少香港本地企业、部分消费品和零售公司选择3月31日、6月30日或9月30日。如果不引入财年截止日这个字段,后面做跨公司同比时一定会错配。

“报告类型”区分年报、中报和季报,也决定了你能用多高频率的数据做分析。港股主板绝大多数公司只有年度和中期报告,季度报告不是强制性义务;创业板公司才有季度披露要求。如果想做高频盈利预测,基于港股利润表的频率上限大概就是“半年”。

“公告日期”则和“财报期截止日”是两个概念。年报可能在财年结束后三个月才披露,和公司实际经营表现之间存在时滞,事件研究时用公告日期,面板匹配时用财报期截止日,两者混用会出现严重的时间错位。

4. 实操:用Python把利润表变成可分析的指标

4.1 读取数据后的第一轮体检

拿到数据后,我的第一个操作永远是“描述性体检”。下面是一段最基础的 Pandas 代码:

import pandas as pd df = pd.read_csv("hk_income_statement.csv", dtype={"stock_code": "str"}) print("总行数:", df.shape[0]) print("上市公司数:", df["stock_code"].nunique()) print("报告类型分布:\n", df["report_type"].value_counts()) # 财年截止月分布 df["fiscal_end_month"] = df["fiscal_period_end"].str[-2:].astype(int) print("财年截止月分布:\n", df["fiscal_end_month"].value_counts().head(10)) # 空值率检查 missing_ratio = df.isnull().mean().sort_values(ascending=False) print("主要字段空值率:\n", missing_ratio[missing_ratio > 0.1])

这段代码做的事很朴素:看有多少公司、有多少年报和季报、财年截止日集中不集中在12月、哪些字段空值率过高。我几乎每次拿到一个新的财务数据集都要跑一遍这个流程,能在半小时内发现数据文件里潜在的大问题。

如果发现某些年份公司数量出现断崖式下跌,那不是退市潮,而是数据覆盖还没补齐;如果发现“归母净利润”空值率高到20%,那就要确认是不是只在部分报告类型里披露。这些问题越早暴露越好,等回归结果跑出来再发现就晚了。

4.2 毛利率、净利率和同比增速怎么算

体检没问题之后,就可以构造常用盈利指标了。这里给一套可以直接抄的代码,但字段名以你自己下载的数据版本为准。

# 构造毛利率(注意先处理0值和缺失收入) df["gross_margin"] = (df["revenue"] - df["cost_of_sales"]) / df["revenue"] # 归母净利润率 df["net_margin_parent"] = df["net_profit_parent"] / df["revenue"] # 按公司分组,按财年截止日排序,算同比增速 df = df.sort_values(["stock_code", "fiscal_period_end"]) df["revenue_yoy"] = df.groupby("stock_code")["revenue"].pct_change() # 当年和上一年财年截止日相差超过365天的,同比口径需要特别标记 df["period_diff_days"] = df.groupby("stock_code")["fiscal_period_end"].diff().dt.days df.loc[df["period_diff_days"] > 380, "revenue_yoy"] = None

最后一步很多人会漏:港股公司财年截止日不统一,如果直接把上一行当作“上一年”,那么一家3月31日截止的公司和一个12月31日截止的公司,效果都正确;但如果有公司变更财年截止日(有公司从12月改为6月,导致中间出现一个短财年或长财年),pct_change 就会算出一个没有实际意义的“同比增速”。所以我用财年截止日间隔做了过滤,超过380天的视为财年变更,不放进同比计算。

毛利、净利率是最基础的盈利指标,再进阶一点,EBITDA 需要加回折旧摊销,但港股利润表正文通常不直接披露折旧摊销,一般放在现金流量表或附注里。如果 CnOpenData 这份表里没有单独的折旧摊销字段,就需要用另一张“现金流量表”数据表去补,不要凭空在利润表数据里找。

4.3 和其他表拼接时最容易出问题的地方

学术研究很少只用利润表,通常还要关联资产负债表和现金流量表。拼接时最常出问题的,是“键值”的格式。

港股公司的股票代码在不同数据源里格式完全不同:披露易里常见的是腾讯控股(00700.HK),某些终端里可能是“700.HK”,另有数据源不带后缀直接给“00700”。如果直接用字符串去匹配,极容易把所有代码都匹配不上。我的解决方法是写一个统一的标准化函数:

def normalize_hk_code(raw_code: str) -> str: # 去掉空格、点和.HK后缀,补齐5位数字 code = raw_code.strip().replace(".HK", "").replace("HK", "").split(".")[0] return code.zfill(5) df["stock_code"] = df["stock_code"].apply(normalize_hk_code)

另外,同一家公司在同一财报期出现两条记录时,不要默认是重复数据。先检查是不是“重述版本”或“不同披露口径”——公司年报发布后发生会计差错更正、追溯调整,数据会更新一版,保留哪一版取决于你的研究目的:做当期基本面分析用最新重述版,做信息披露与市场反应研究用首次公告版。

5. 复盘五个真实踩坑:港股利润表数据常见误用

5.1 财年截止日不统一,同比增速算错一整个样本

我最早用港股数据时犯过一个典型的错误:直接从一张表里按“年份”字段筛出2021和2022,然后相减算同比。结果一个样本里混进了两种公司:财年截止于2021年12月31日的,和财年截止于2022年3月31日的。前者代表“截至2021年底的经营”,后者已经包含2022年第一季度,完全不是同一时期,却被当成同一年的数据去比较。

后来我形成习惯:所有跨公司比较都基于财年标识而不是自然年标识。用数据里自带的财年字段生成一个“fiscal_year”变量,例如把截止日在2021年4月至2022年3月的公司统一标记为FY2022,再在这个基础上做面板匹配。不同公司的经营季节性差异是存在的,但只要统一按“各自财年内的完整经营周期”来对齐,时间错配的问题就基本消掉了。

5.2 港元人民币混着算,汇率波动变成经营波动

港股上市公司里,很多内地公司以人民币为记账本位币,但报表以港元列示;另有一些公司直接用人民币列示。这意味着同一张标准化的利润表里,不同公司的“营业收入”背后是不同币种,直接横向比较会把汇率波动全部混进经营差异里。

稳妥的做法分两步:先看数据表里每一行有没有币种标记,例如“report_currency”字段,把标记为HKD和CNY的记录分开;再选定统一比较基准,如果研究视角是“人民币口径的盈利能力”,就把港元数字按财报期平均汇率转换成人民币,反之亦然。这里要注意,不能用某个时刻的即期汇率去转全年利润表,至少得用年度平均汇率,否则误差会被季节性盈利放大。

如果数据表里已经提供“原始币种金额”和“换算后金额”两套字段,那么优先使用后者做跨公司比较;如果只有单一币种字段,建议随机抽几家公司和原始年报数字核对一遍,确认平台做换算时采用的汇率规则。

5.3 把银行和保险公司混进一般行业指标

“毛利率”这个指标对银行、保险公司来说本质上不成立。银行的利润表核心结构是利息净收入、手续费及佣金净收入、经营费用、减值损失;保险公司的核心是已赚保费、赔付支出、提取保险责任准备金。把银行放进“毛利率排名”里,得到的结果不但没有意义,还会污染整个样本的描述统计。

我的习惯是:在做全样本分析之前,先把金融行业单独筛出来。判别依据不是公司简称,而是行业分类字段。恒生行业分类系统(HSIC)里的“金融业”大类,包括银行、保险、其他金融;又或者用GICS分类里的Financials,效果类似。不同数据平台给港股配的行业体系可能不同,但处理原则一致:金融行业单独建模、单独展示、单独解释。

另外注意,很多港股公司名字里带有“金融”或“银行”但实际是控股公司,利润表结构偏投资控股而非银行业务。观察“营业收入”里的利息收入占比和“应占联营损益”占比,能更好判断实际业务属性。

5.4 追溯重述把新旧版本混在一起

上市公司发布年报时,如果同期对以前年度报表做了追溯调整,一段时间后你会看到同一个公司、同一个财年出现两套不同的净利润数据。比如某公司因会计政策变更,把之前五年的折旧方法调整,导致前一年净利润发生变化。数据平台在抓取时会更新记录,如果原用户已经下载过旧版本,就容易出现新旧版本混用。

我经历过一次很尴尬的事:同一个样本里,同一家公司的FY2019净利润,一部分行是原始披露值,另一部分行是重述后的值,面板里出现时间序列跳动。后来我学到的做法是,看数据里有没有“公告日期”或“更新版本”字段,按“同一股票代码+同一财年标识”分组,保留公告日期最新的记录;如果做事件研究,则反过来保留首次公告日期那条记录。

5.5 中报数据被过度使用或完全忽略

港股主板公司没有强制季报义务,所以基于利润表数据,一年最多只有两个观测点(年报和中报)。有些研究者为了拉长面板,把中报数据也放进同一套年度指标里,却忘了中报是没有经过完整年度审计的、而且部分公司的中报披露质量远低于年报。

另一些人则彻底忽略中报,只用年报。这在某些场景下会损失重要信息:比如一家港股公司在前一年年报亏损、当年中报已经大幅扭亏,市场会沿着中报重新定价,如果忽略中报,你对这家公司“盈利拐点”的判断会晚半年。我的折中方案是:在做年度面板时只用年报;做盈利动量分析或事件研究时引入中报,但单独设置“report_type”变量,在模型里控制报告频率差异带来的噪音。

6. 对这份数据集的使用体会与落地建议

6.1 用好这个数据集的三个习惯

第一,永远在数据清洗前做覆盖体检。我用 CnOpenData 这类数据集的第一天,都会画出“公司数量×年份”的柱状图,再多看一眼财年截止日的分布。这种看似低级的检查,能帮你躲开数据版本不完整带来的大坑。

第二,挑几家自己熟悉的大公司做锚点。我会把腾讯、汇丰这类头部公司的历年利润表从数据集里抽出来,和原始年报上的数字逐行核对一遍。如果锚点公司对得上,说明数据质量大概率是稳的;如果锚点都对不上,那这个数据集就不适合你的研究场景。

第三,保留“字段映射底稿”。处理港股利润表时,我始终会在旁边放一份“原始报表科目—标准化字段”的对应关系表。这份底稿在写论文的数据章节时非常有用,审稿人问起具体口径时直接拿得出来;后续做稳健性检验,也可以快速回溯替换字段。

6.2 什么时候该回到原始报表核对

标准化数据集不是万能的。当你发现某个指标异常(比如某家公司毛利率突然从30%跳到60%),不要直接当异常值删掉,先回去查原始年报。有时候是资产重估、有时候是合并范围变更、有时候是会计政策调整,这些“异常”本身就是重要的研究信息,盲目删掉反而会漏掉关键信号。

我个人的操作准则是:数据集负责规模和效率,原始报表负责解释和验证。先用手头标准化的 CnOpenData 港股上市公司利润表跑通全流程,锁定关键样本和疑点;再回到港交所披露易调出对应公司的原始PDF,逐条确认科目和计量口径。这套流程看起来多了一道手工作业,但恰恰是这道工序,让我的实证结果经得起复现和审视。

如果你正准备用港股利润表做研究,我的建议是:从一张年报开始,把从原始报表到标准化字段的链路走通一遍,再扩展到全样本。一次性拿到几百家公司的数字确实方便,但真正理解每一个字段背后的含义,才是保证后续所有分析不出结构性错误的前提。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询