尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用数据工程解读Chemring半年报:从PDF解析到订单积压分析

用数据工程解读Chemring半年报:从PDF解析到订单积压分析 简介来自Jefferies的Chemring集团CHG2025财年上半年业绩及下半年展望分析报告面向航空航天与国防行业投资者、分析师与研究人员旨在解答公司财务表现、订单积压对收入支撑及估值预期等核心问题。报告显示公司上半年营收2.34亿英镑同比增长6%调整后EBITA 2710万英镑同比增长10%订单积压达13亿英镑并覆盖下半年约85%收入其中对抗措施与能量材料部门订单增长68%传感器与信息部门虽收入下滑12%但近期合同恢复带来积极信号。Jefferies维持买入评级目标价530便士并预计未来12个月回报率超15%对2030财年实现10亿英镑收入充满信心。该资源共1个PDF文件大小105KB目前已吸引119人学习下载。适合需要跟踪国防电子龙头订单趋势、评估投资价值及学习券商研报框架的读者。1. Chemring集团CHG这份业绩标题在航空航天与国防电子行业该怎么读Chemring集团CHG这份“营收增长与订单积压支持未来预期”的业绩标题在航空航天与国防电子行业里并不少见。少见的是分析路径如果只是把新闻稿里的增速和订单数字抄下来结果既不可复核也没法拿来做下半年预判。真正值钱的部分在中间层把半年报PDF里的财务表抽成结构化数据再用“积压订单覆盖倍数”“订单转化率”“汇率中性增速”这几个指标把管理层那句“支持未来预期”翻译成可以测算的假设。这篇文章以CHG为例讲的是IT从业者做行业研究时最顺手的那套方案——按数据工程思路走不依赖新闻摘要每一步都能回查适合要对结论负责的人。2. Chemring半年报的数据获取与PDF解析2.1 数据源选型官网投资者页、伦敦证交所RNS与EDGAR做分析的第一步是确认数据源。Chemring在伦敦证券交易所挂牌代码CHG半年报有两个正规出口公司官网的投资者关系栏目以及伦敦证交所的RNS公告系统。英国上市公司在发布中期财报时通常会在官网的“Results Presentations”目录下挂出完整PDF同时给RNS一份新闻公告和业绩演示文稿。美国国防电子公司如Northrop Grumman、L3Harris则走SEC的EDGAR系统数据结构化程度高字段级抓取比PDF容易得多。经验是先看官网投资者页没有再查RNSEDGAR在拉美国可比公司时用因为XBRL字段可以不依赖版面解析。数据源适用对象数据类型适合做的分析公司官网投资者页多数上市公司PDF、XLSX、网页报表解读、指标测算伦敦证交所RNS英国及欧盟上市公司新闻公告、PDF事件时间线、业绩快报SEC EDGAR美股上市公司XBRL、HTML可比公司分析、字段级对比Companies House英国注册公司FRS报表法律归档、审计信息交叉验证表格里Companies House是英国公司注册处的公开归档账目适合验证年报里净利润与净资产是否和提交的法定账目一致。实际操作时我习惯把官网下载的PDF统一命名为chemring_h1_2025.pdf放进data目录避免后续脚本被乱码文件名干扰。2.2 用pdfplumber把半年报PDF转成DataFrame拿到PDF后不建议直接用pandas.read_html硬啃因为半年报里的合并损益表经常跨页单元格合并也频繁。常见做法是用pdfplumber按页提取表格再用关键字定位目标表。下面这段代码在PDF里自动找“Revenue”所在页并导出成CSVimport pdfplumber import pandas as pd pdf_path data/chemring_h1_2025.pdf with pdfplumber.open(pdf_path) as pdf: for page_no, page in enumerate(pdf.pages, start1): tables page.extract_tables() for table in tables: # 空表直接跳过避免后面取表头时越界 if not table: continue header_cells [str(c).strip() if c else for c in table[0]] # 同时匹配英国报表里常见的 Turnover joined .join(header_cells) if Revenue in joined or Turnover in joined: df pd.DataFrame(table[1:], columnstable[0]) csv_path foutput/revenue_table_page_{page_no}.csv df.to_csv(csv_path, indexFalse) print(f第{page_no}页找到收入表已保存到 {csv_path})逻辑说明extract_tables返回的是页面内所有表格的嵌套列表每一层list代表一行第一个元素通常是表头。先用表头字符串做关键字匹配再把剩余行转成DataFrame。这里同时匹配Revenue和Turnover因为英国公司报表更习惯用Turnover指代营业收入。参数说明page_no从1开始计数是为了文件名能直接对应PDF原页table[1:]与table[0]对齐的前提是表头只有一行。遇到合并单元格跨两行表头时这个对齐会失败需要先打印table前两行人工确认再决定是否手动拼接表头。2.3 字段归一化把财务报表装进统一Schema不同年份或不同公司的报表列名差异比想象中大。上半年叫“Revenue”下半年改成“Group revenue”到了附注又变成“Continuing operations”。为了让指标计算代码不被列名牵着走我会先做一层字段别名映射field_alias { revenue: [Revenue, Turnover, Group revenue, Revenue from continuing operations], adjusted_op: [Adjusted operating profit, Underlying operating profit], order_book: [Order book, Closing order book, Total order book], net_debt: [Net debt, Net (debt) / cash], } def normalize_columns(df: pd.DataFrame) - pd.DataFrame: rename_map {} for standard_name, aliases in field_alias.items(): for alias in aliases: match_cols [c for c in df.columns if c and alias.lower() in str(c).lower()] if match_cols: rename_map[match_cols[0]] standard_name return df.rename(columnsrename_map)逻辑说明这段代码把“Revenue”和“Turnover”归一化成revenue。匹配时统一转小写避免“REVENUE”和“Revenue”大小写不一致造成遗漏。参数说明alias.lower() in str(c).lower()是模糊匹配容错能力强但可能把“Net debt / (cash)”这类带修饰词的列名匹配到错误别名。处理办法是让别名列表按长度降序排列优先匹配更完整的列名。如果出现“Adjusted operating segment result”这种既有“Adjusted”又有“operating”的列宁可抛出来人工确认也不要静默匹配错列。2.4 两个最容易翻车的解析坑表头混行与单位不一致PDF解析翻车率最高的不是缺库而是表头混行。半年报里的损益表经常把“Unaudited six months ended 30 April 2025”和“Audited year ended 30 September 2024”拆成两行pdfplumber会把它们当成独立的行导致表头错位。处理方式是打印前两行人工确认后把两行拼成一行或者用table[2:]跳过干扰行。单位问题同样隐蔽。英国公司习惯用“£m”但表格里可能出现“£000”甚至“$m”。不对齐单位就做环比结果会差三个数量级。我通常会在读取数字时把“£m”从单位行剥离所有数值统一乘以1_000_000转成英镑绝对数存进DataFrame后续计算不再关心单位。提示解析出来的任何一张表都要和PDF原表逐格核对一遍。pdfplumber对无边框表格的列切分偶尔会偏一位常规检查点是“Revenue”和“Operating profit”两行的数字是否与原表一致。宁愿多花两分钟核对也不要带着错位数据往下跑。3. 用订单积压与营收增长重建业绩分析框架3.1 积压订单不是合同额先看懂“支持未来预期”这句话Chemring半年报里最常被引用的组合是“营收增长与订单积压”。拆开看营收增长是过去半年的结果订单积压是未来收入的蓄水池。航空航天与国防电子合同的交付周期通常按数年计客户会预付部分款项但收入确认按IFRS 15里的履约义务完成进度走。也就是说公司签下一笔大合同的当年账面可能只确认一小部分收入其余金额全部计入积压订单在后续年度逐步释放。这意味着判断一家国防电子公司的下半年预期不能只看积压订单的绝对值要看它相对年收入的倍数。假设期初积压订单相当于2.5倍年收入即使新签订单放缓现有合同也足够支撑相当长时间的营收如果倍数只有0.8下半年就要靠新签订单“现签现做”业绩能见度明显更低。所以“积压覆盖倍数”比单看增长百分比更能解释“支持未来预期”这句话的分量。积压订单的披露位置也值得注意。管理层讨论里出现的通常是总积压金额正式附注里才会拆分“已获得资金合同”和“未获得资金合同”。做分析时尽量用附注里的拆分数据因为未获得资金的合同在执行时间上有不确定性全部混在一起会高估业绩可见度。3.2 先建一张核心指标表再谈公式分析一家公司我会把计算口径全部收在一张表里后续讨论只引用这张表的字段名避免一篇文章里同一指标出现两种说法。指标计算逻辑数据出处用途营收同比增速(H1本年度营收 - H1上年度营收) / H1上年度营收合并损益表判断业绩趋势调整后营业利润率调整后营业利润 / 营收利润表及分部附注剔除一次性损益后的盈利水平积压覆盖倍数期末积压订单 / 最近12个月营收资产负债表附注或管理层讨论判断未来营收可见度订单转化率本期确认收入 / 期初积压与期内新签合同之和积压订单变动表判断履约节奏净债务/EBITDA净债务 / 调整后EBITDA资产负债表与利润表评估财务弹性现金转化率经营现金流净额 / 调整后营业利润现金流量表识别利润含金量下面是示意数据的计算脚本实际分析时把PDF解析出的真实数值填进字典即可。用字典取值而不是直接从DataFrame找列是为了让修数字的过程更直观metrics { revenue_h1_2024: 250, # 百万英镑 revenue_h1_2025: 285, adj_op_h1_2025: 40, closing_order_book: 760, rolling_revenue: 560, # FY2024全年营收 net_debt: 95, adj_ebitda: 78, op_cash_flow: 28, } yoy_growth (metrics[revenue_h1_2025] / metrics[revenue_h1_2024] - 1) * 100 adj_op_margin metrics[adj_op_h1_2025] / metrics[revenue_h1_2025] order_coverage metrics[closing_order_book] / metrics[rolling_revenue] leverage metrics[net_debt] / metrics[adj_ebitda] cash_conversion metrics[op_cash_flow] / metrics[adj_op_h1_2025] print(f营收同比增速: {yoy_growth:.1f}%) print(f调整后营业利润率: {adj_op_margin:.1%}) print(f积压覆盖倍数: {order_coverage:.2f}倍) print(f净债务/EBITDA: {leverage:.2f}倍) print(f现金转化率: {cash_conversion:.1%})逻辑说明积压覆盖倍数用rolling_revenue而不是当期半年营收乘以2是因为下半年营收有季节性直接把H1乘以2会把覆盖倍数算低。参数说明净债务/EBITDA里的EBITDA要使用调整后口径剔除已终止经营业务和重组费用否则和净债务之间的对应关系会失真现金转化率在这个行业通常较高因为客户是政府或大型承包商坏账率低但高转化率不代表利润质量高还要看预收款比例。3.3 三个必调参数订单覆盖倍数、现金转化率与汇率中性增速3.3.1 订单覆盖倍数的异常值判断订单覆盖倍数如果突然从2倍跳到4倍先不要高兴要确认是“新签大合同”还是“确认收入停滞”。前者是利好后者意味着交付节奏出问题。我会把期末积压的变动拆成“新增订单贡献”和“汇率重估贡献”两块。英国公司大量美元订单在折算英镑时会产生账面增加这种增加不带来任何现金流入必须剔除后再判断真实增速。3.3.2 汇率中性增速的计算Chemring是英国公司但收入里美元占比相当高。分析“营收增长”时如果公司自己披露了汇率中性增长优先采用没有披露时用两期报表附注里的平均汇率做还原revenue_h1_2025_usd 380 # 按美元功能货币口径 revenue_h1_2024_usd 345 usd_growth (revenue_h1_2025_usd / revenue_h1_2024_usd - 1) * 100 gbp_growth yoy_growth # 上一小节算出的报表口径 fx_impact gbp_growth - usd_growth print(f美元本币口径增速: {usd_growth:.1f}%) print(f英镑报表口径增速: {gbp_growth:.1f}%) print(f汇率影响约: {fx_impact:.1f}个百分点)逻辑说明fx_impact为正表示英镑贬值放大了报表营收为负则是英镑升值挤压了折算收入。参数说明这段代码成立的前提是公司以美元作为分部功能货币并披露了本币口径数据如果报表里没有就用现金流量表里的汇率影响数列反推。这个参数直接影响对下半年预期的判断——如果管理层说的增长主要来自汇率红利那订单积压本身的价值就需要重新评估。4. 航空航天与国防电子的行业底色与可比公司选择4.1 现金流结构决定了EV/EBITDA比PE更有用航空航天与国防电子公司和互联网公司最大的区别在现金流结构。前者合同周期长、客户集中、收入可预测性强但前期要投入大量工程开发和产线准备。订单积压提供了业绩能见度也让营运资金占用变得可测算。在这个行业做估值EV/EBITDA通常比PE更能反映真实价值。原因有三递延税项和预收合同款让净利润容易偏离经营实质这些公司普遍有净债务或养老金负债EV把资本结构差异暴露出来国防电子固定资产和无形资产占比高折旧摊销规模不可忽略。研发投入的会计处理也直接影响利润对比。有些公司把研发全部费用化有些则资本化一部分导致毛利率和净利率看起来差距很大。做横向对比时要么把资本化研发加回费用化口径要么统一用EBITDA作为分母否则“谁家研发效率高”这个问题根本谈不上。4.2 拿BAE Systems、Thales、Rheinmetall和CHG放在同一张表里做行业分析时我习惯把可比公司放进统一表格每家公司列出财务特征和对比时须修正的项目不对齐则不参与对比。公司上市地主要业务方向财务特征对比时需修正的项ChemringCHG伦敦航空航天与国防电子、传感与对抗现金流稳定订单积压覆盖倍数较高美元收入占比高需做汇率中性还原BAE Systems伦敦航空航天、军工平台收入规模大长周期合同多养老金负债及资本化开发支出Thales巴黎国防电子、网络安全多元业务电子与数字占比高收购摊销与研发资本化率Rheinmetall法兰克福国防电子、车辆与弹药增速与产能扩张同步新建产能的资本开支对自由现金流的影响Northrop Grumman纽约航空航天、电子系统美国市场为主回报率稳定美国口径下的合同负债与预付款规则表格里“对比时需修正的项”才是真正需要花时间的部分。如果不做修正直接把五家的调整后营业利润率摆在一起结论基本是噪音。Thales的调整后利润排除了收购摊销BAE可能把养老金服务成本拆出了经营利润Chemring的“调整后”是否包含已终止业务都要在半年报附注里查实。4.3 用归一化代码修正口径差异修正口径差异的做法不复杂难在把每一项消失在“调整后”三个字里的项目找出来。我一般会维护一个adjustments数组把非经常性损益逐项列出analyst_adjustments { one_off_restructuring: 3.2, # 重组费用百万英镑 acquisition_amortization: 5.6, pension_service_cost: 1.1, foreign_exchange_gain: 0.8, # 非经营汇兑收益需冲减 } reported_adj_op 40.0 normalized_op reported_adj_op sum(analyst_adjustments.values()) print(f报表调整后营业利润: {reported_adj_op:.1f}) print(f归一化营业利润: {normalized_op:.1f})逻辑说明sum把所有需要加回的项目汇总。重组费用和收购摊销属于非经常性项目加回是为了得到可持续营业利润养老金服务成本和汇兑收益需仔细判断——养老金服务成本在各家报表里的列示位置不同汇兑损益如果来自长期合同套保则应视作经营相关而非一次性损益。参数说明每个数值的来源都应在注释里标明页码或附注编号。这是让分析可被复核的最低要求也是让团队其他成员能接手继续改代码的基础。注意归一化不是为了粉饰数字而是让Chemring与这一组可比公司处于相同口径。如果某家公司的调整后利润和归母净利润差距过大反而要怀疑它的“调整后”是不是把太多正常经营成本排除在外。5. 把下半年展望做成可回测的敏感性模型5.1 用三个情景测算FY2025营收区间下半年展望不要只引用管理层的一句话把它拆成三个变量H2营收增速、订单转化率、汇率中性影响。下面用示意数据测算全年营收区间h1_revenue 285 # 百万英镑 scenarios {保守: 0.02, 中性: 0.06, 乐观: 0.10} for name, h2_growth in scenarios.items(): h2_revenue h1_revenue * (1 h2_growth) fy_revenue h1_revenue h2_revenue print(f{name}情景: H2{h2_revenue:.1f}, FY2025{fy_revenue:.1f})逻辑说明H2增速的参照系是上一财年H2占全年营收的比例以及订单积压的释放节奏。参数说明如果公司历史上H2营收占比在52%左右用这个公式成立如果H2占比偏离较大应改为h2_revenue h1_revenue * seasonal_ratio。5.2 从订单积压倒推下半年收入实现率更硬核的复核方式是用期初积压、新签订单、确认收入三者的关系反推年底积压。关系是期末积压 期初积压 新签订单 - 已确认收入。用这个关系式的变形可以倒推出下半年需要达到的收入实现率实现率 下半年确认收入 / 期初可用于确认的积压与新增订单之和。如果推算出的实现率明显高于公司历史水平说明情景假设里隐含了交付提速需要补充项目层面的证据。5.3 用去年数据回测预测口径敏感性模型建好后先拿上一财年的真实数据跑一遍同样代码把预测值和实际披露值做对比。偏差在5%以内说明变量选得合理偏差超过10%要检查是不是忽略了汇率的非线性影响。我习惯先固定其他变量只改订单转化率看产出变化幅度确定哪个参数对结果最敏感再决定要不要展开敏感性区间。最终把“变量-影响幅度-置信度”输出成一张小表连同CSV文件一起放进分析报告附录其他同事复核时只需要跑一遍代码就能看到每个假设对应的结论变化。本文还有配套的精品资源点击获取
返回列表