Skip to content

Proposal: 主营业务抽取 → 多业务预测 → 汇总

状态:设计提案(Draft),待 review 定稿后再实现。 关联:把单 segment 模型升级为「从年报自动长出多个 segment」的端到端工作流。

0. TL;DR

把 sell-side 的 segment revenue build-up(分业务线搭建收入)工程化:从年报抓 3-5 个主营业务 → 每个 segment 独立 driver-based 预测 → 汇总成公司整体预测。

  • 引擎层已就绪RevenueModel(segments=[...], total_revenue) + residual + 蒙特卡洛
  • tornado 本就是多 segment 设计。NovaTech demo 已是 2 segment。
  • 瓶颈在「年报 → 主营识别」:这是本提案的核心,也是相对 market-sizing prompt 生态 (全是 prompt、无引擎)的差异化护城河。
  • 务实路线 = 半自动脚手架:LLM 抽 segment 骨架 + driver 候选,C 级数值人工定。 不追求取代分析师,而是让方法论显式、可审计、可复用。

1. 为什么做

  • 单 segment 颗粒度太粗:把整家公司塞进一个 driver tree,解释力差、假设不可辩护。
  • 不同业务 driver 结构不同:硬件看「销量×ASP」、软件看「订阅数×ARPU×续费率」、 服务看「产能×利用率×单价」——混在一个 segment 会失真。
  • 80/20 原则:抓 3-5 个覆盖 70-80% 收入的核心业务,其余进 residual。 追求 100% 建模要么 C 级堆叠、要么反推失真(违反 design-principles Principle 1)。抓大放小是专业做法。

2. 数据源:A 股年报的「主营业务分析」

A 股年报(披露框架:《公开发行证券的公司信息披露内容与格式准则第2号》)相关章节:

位置 内容 价值
第四节「经营情况讨论与分析」→ 主营业务分析 分行业/分产品/分地区的营业收入、营业成本、毛利率、同比 ★ 主数据源
主营业务分行业/分产品情况表 结构化表格:业务名、收入、占比、YoY、毛利率 ★ 直采
附注·收入分类 更细的产品/区域拆分 细化用(解析难)

关键字段:业务名、收入(元)、收入占比、YoY、毛利率。

多市场差异(后续): - 港股年报「分部资料」(IFRS 8 segment information)——口径偏地理/业务板块 - 美股 10-K segment reporting(ASC 280)——结构最规整但口径不同 - → 先聚焦 A 股,模板跑通后再扩多市场。


3. 端到端工作流(Pipeline)

年报 PDF
   │  [1] 文本+表格解析(PyMuPDF 文字层 + pdfplumber/camelot 抠表)
   ▼
「主营业务分析」章节文本 + 分业务表格(markdown)
   │  [2] LLM 结构化抽取(见 §4 prompt / schema)
   ▼
segment 骨架 JSON:[{name, revenue_history, share, yoy, gross_margin, driver_type, hints}]
   │  [3] driver 模板匹配(见 §5 模板库)
   ▼
每个 segment 的 driver tree 候选(base/penetration/share/price 的占位 + 来源线索)
   │  [4] 人工确认/补充(C 级数值、预测假设)← ABC 分级在此落地
   ▼
完整的 Driver / Segment 对象
   │  [5] 接入 RevenueModel + 蒙特卡洛 + tornado
   ▼
多业务预测 + 汇总(residual 自动吸收未建模业务)

4. LLM 抽取:schema 与 prompt

输入:主营业务分析章节文本 + 分业务表格(转 markdown)。 输出:严格 JSON(用 structured output / function calling 约束)。

{
  "company": "示例科技",
  "fiscal_year": 2024,
  "currency": "CNY",
  "segments": [
    {
      "name": "智能汽车软件",
      "revenue": 410000000,
      "share": 0.62,
      "yoy": 0.35,
      "gross_margin": 0.72,
      "driver_type": "software_subscription",
      "driver_hints": {
        "market_base_source": "年报披露客户数/装机量",
        "penetration_source": "行业第三方(高工/IDC)",
        "price_source": "年报均价或对标竞品"
      },
      "evidence": "「报告期内智能汽车软件收入 4.10 亿元,同比+35%」(年报 p.28)",
      "confidence": "A"
    }
  ],
  "unmodeled": "其他业务(零散项,合计占比<8%)→ 进 residual"
}

prompt 要点: - few-shot:给 1-2 个标注样例(含一个多业务、一个单业务的)。 - 受控词表driver_type 必须从 §5 模板库枚举里选,禁止自由发挥。 - 占比求和校验:要求 Σ share + unmodeled_share ≈ 1,否则自查。 - with evidence:每个数字必须带 evidence(引用原文片段+页码),抑制幻觉。 - confidence 自评:A/B/C 自标,与引擎的 data grading 对齐。

模型与密钥:用智谱 GLM / OpenAI 兼容 endpoint;API key 走 secrets_loader (项目内绝不硬编码;demo 用占位符 <your-llm-key>)。


5. driver 模板库(按业务类型)

每个 segment 自动套用最接近的模板,展开成 4 个 driver 占位:

driver_type driver tree 适用
hardware_product 市场基数(销量池) × 渗透率 × 市占率 × ASP 消费电子、汽车零部件、半导体
software_subscription 客户池 × 渗透率 × 市占率 × ARPU ×(续费率→并入 share) SaaS、授权软件
service_project 产能/人天 × 利用率 × 单价 IT 服务、外包、工程
advertising 流量(DAU×时长) × ad_load × 市占率 × eCPM 互联网平台
financial_interest 生息资产规模 × 收益率(映射为 base×price) 银行、租赁、消金
retail_store 门店数 × 坪效(或 客单价 × 客流) 连锁零售、餐饮

模板存为 Python 配置 / YAML。driver_type 选定后自动生成 4 个 Driver 占位, 人工只需填数值 + 来源 + ABC 等级。

映射约定:所有模板归一到 base × penetration × share × price 四因子。 例如 service_project:base=人天产能、penetration=利用率、share=市占、price=人天单价。


6. 与现有引擎的衔接

  • 抽取的 segment → Segment(name, base=Driver(...), penetration=..., share=..., price=...)
  • 历史收入填入对应年份 → RevenueModel.validate_all() 对齐年报总收入
  • residual 自动 = total − Σ(segments),吸收 §4 里 unmodeled 的零散业务
  • 各 segment 独立跑蒙特卡洛 / tornado → 汇总到 RevenueModel
  • ABC 分级的杠杆点:抽取出的 driver 大量是 C 级(估算),分级天然标记 「哪些要人工加固、哪些可直接信」——tornado 的 per-driver 区间也据此设宽窄。

7. 半自动边界(自动 vs 人工)

环节 自动 人工
年报解析 PDF → 文本/表格 校验解析正确(尤其合并单元格/跨页表)
segment 识别 LLM 抽业务列表 + 收入 确认业务划分口径(产品/地区/行业维度)
driver 结构 模板匹配 driver_type 选/调模板
driver 数值(A/B 级) 从年报/行业库取候选 核对来源
driver 数值(C 级) 给候选区间 定值 + 不确定性区间
预测假设 给候选(增量法、确定性金字塔) 拍板(政策/产品周期判断)

定位:脚手架,不是全自动。价值在「把分析师的重复劳动(找章节、抄数字、搭结构) 自动化,把判断劳动(C 级估值、预测假设)留给人并强制留痕」。


8. 难点与风险

风险 说明 对策
PDF 表格解析 A 股表格格式不统一(合并单元格、跨页),解析成功率非 100% pdfplumber+camelot 双引擎 + 人工兜底 + 累积规则库
披露颗粒度不一 有的按产品、有的按地区、有的按行业 LLM 判断「主营」维度;模板支持多维度
跨年口径变化 业务重组、口径调整导致历史序列断裂 对齐校验 + 标注「口径变更」断点
LLM 幻觉 可能编造数字 强制 evidence 引用原文 + 占比求和校验 + A 级回查
合规 真实公司年报开源的著作权 / 非法荐股风险 见下方 §8.1(已调研,真实数据可用)

8.1 合规方案(真实 A 股年报可用 — 已调研)

经法律调研(大成律所《证券投资咨询业务合规问题研究》+ 证监会《2001》207 号文 + 刑法 225 条),真实年报可用,守住三条边界即可。完整声明见 DISCLAIMER.md

两层风险: - 著作权(低):年报财务数据是事实,不受著作权保护,可抽取、存储、开源;叙述文字 少量引用 + 标来源属合理使用。 - 非法荐股(可控):非法经营罪(刑法 225)三要件 = 无资质 + 经营行为(持续有偿获利) + 扰乱市场秩序。本项目免费开源 → 不满足第②要件(核心护城河)。

三道防线: 1. 非经营性:免费开源、MIT、不收费、不定向推送 → 不构成「经营行为」。 2. 非咨询性:输出 driver tree / 收入模型,绝不输出买卖建议 / 目标价 / 投资评级。 3. 教育 / 研究定位:归投资者教育与学术研究(同 FinRobot 等开源先例)。

四条措施:① 强免责声明(中英,README + 每次输出);② 数据走公开渠道(巨潮 / 交易所 / tushare),不大段复制年报叙述原文,引用标来源+页码;③ 输出只到「收入预测 / driver 分析」, 不到「买卖建议」;④ 真实公司作「功能演示数据源」而非「投资结论」。

红线(绝不触碰):收费 / 会员 / 利润分成 ❌ | 目标价 / 评级 / 买卖建议 ❌ | 承诺收益 / 暗示操作 ❌ | 大段复制年报原文 ❌ | 定向荐股推送 ❌。

⚠️ 警示案例(廖某案):以「投资者教育」名义有偿提供证券分析被判非法经营罪。律所原话: 「无论命名如何,业务实质离不开对具体证券的分析预测…未获资质便有风险」——前提仍是有偿 经营。这反而强化了防线①(绝不收费)。


9. 分阶段实施

  • Phase 1(MVP):手动喂「主营业务分析」章节文本 → LLM 抽 segment JSON → 转 Segment 对象 → 接 RevenueModel不做 PDF 解析(文本人工复制)。 目标:端到端走通,证明思路。
  • Phase 2:加 PDF 解析(PyMuPDF + pdfplumber),自动定位主营业务章节。
  • Phase 3:driver 模板库(§5)+ 自动模板匹配。
  • Phase 4:多市场(港股 IFRS 8、美股 ASC 280)。

每个 Phase 独立 commit + 测试,保持开源迭代节奏。


10. 决策记录与开放问题

已定(2026-07-28 review): - ✅ 市场聚焦:先 A 股,多市场(IFRS 8 / ASC 280)放 Phase 4。 - ✅ LLM 选型:智谱 GLM(已有 key,走 secrets_loader,不硬编码)。 - ✅ MVP 年报样本:真实 A 股年报(合规已调研,见 §8.1,可用)。

待定: 1. 抽取结果存储:JSON 文件 / YAML / 直接构造 Python 对象?影响可复现与版本管理。 2. 交互形态:纯库 API(extract_segments(text) -> list[Segment])还是带 CLI? 3. 模板库归属:放项目内 revenue_model/templates/,还是单独配置文件? 4. MVP 目标公司:用哪只 A 股?建议选业务清晰、主营披露颗粒度好的(消费电子 / 软件 / 半导体类)。


本提案由 GLM 老师起草,2026-07-28。Review 定稿后进入 Phase 1 MVP。