Skill: jackdark425/banker-memo-md (version 0.9.7)

--- name: banker-memo-md description: Produce an investment-banker-grade research memo (analysis.md + data-provenance.md) from CN raw-data/ JSON snapshots. Use when the user asks for "投行 md" / "银行家级分析 md" / "banker memo markdown" on an A-share, H-share, or non-listed CN company that has raw-data/ populated by cn-client-investigation Phase 3.5. This is STEP 1 of 2 in the banker pipeline — pair with banker-slides-pptx for the deck. --- # Banker Memo (MD) Step 1 of the banker pipeline: **raw-data/ → analysis.md + data-provenance.md**. This skill is the **prompt** that drives the agent to write a banker-grade research memo. It does not generate slides or run gates — those belong to `banker-slides-pptx` and `validate-delivery.py` respectively. ## Pipeline position ``` ┌────────────────────┐ ┌──────────────────┐ ┌────────────────────┐ │ Phase 3.5 raw-data│ ──▶ │ banker-memo-md │ ──▶ │ banker-slides-pptx │ │ (cn-client-inv.) │ │ (THIS SKILL) │ │ (step 2) │ │ → raw-data/*.json │ │ → analysis.md │ │ → slides-outline │ │ │ │ → provenance.md │ │ → .pptx │ └────────────────────┘ └──────────────────┘ └────────────────────┘ ``` ## Why split from the deck skill Earlier `banker-memo` bundled both MD + outline generation in one prompt. Problems: - Outline was an afterthought — agent ran out of attention budget - MD prompt constraints (8 sections, peer benchmarking, SOTP) got diluted by "also design 12 slides" - Impossible to iterate on MD quality without re-running the slide outline Splitting lets each prompt focus: - This skill: **pure research discipline** — 8-section framework, data flags, 4C's credit view, specific [EST] tagging - `banker-slides-pptx`: **pure visual design** — structured layout schema the renderer can parse into real pptxgenjs tables/charts ## Prompt template Canonical prompt at `references/banker_memo_md_prompt.md`. Placeholders: - `{ts_code}`, `{name_cn}`, `{industry}` — target identifiers - `{raw_dir}` — path to `raw-data/` holding MCP JSON snapshots - `{out_dir}` — where to write analysis.md + data-provenance.md - `{file_list}` — auto-discovered raw-data files - `{uscc}` — unified social credit code from PrimeMatrix filename Build the prompt via `scripts/build_md_prompt.py`. ## Framework enforced by the prompt ### 1. Executive Summary (300-500 字) - **一句话核心观点** (thesis) + 3 supporting bullets - **授信 / 投资建议** (specific 额度 + 期限 + 利率 OR Buy/Hold/Sell + 目标价) - 1-2 **关键风险** ### 2. Company Profile - 沿革 (成立 + 上市 + 经营期限) - 主业拆解 (industry field 展开到 sub-segments) - 股权与资本结构 (注册资本 + 股本 + 市值 + 法人) ### 3. Industry Dynamics - 赛道特征 (cyclicality, tech shifts, policy drivers) - 中国位置 (份额估算, 以 [EST, per sector consensus] 标注) - 主要对手 3-5 家 (国内 + 海外, 每家标 [EST]) - 政策驱动 (十四五 / 专项补贴 / 产业政策) ### 4. Financial Deep-Dive **(表格为主)** - 3Y 年度对比表 (营收 / 净利 / ROE / 毛利率 / 资产负债率 + YoY) - 季度趋势 (YTD 累积 cumulative fields 展开) - **异常 flag** (QoQ 跳变 > 5pp 必须点出) - **数据口径 flag** (若 income 反推 vs company_performance 不一致, 必须指出) ### 5. Peer Comparison - 3-5 家同业表 (公司 / 代码 / 市值 / PE / PB / ROE + 备注) - 每个 peer 数字**必须**标 `[EST, per sector consensus]` 或 `[未核实]` - 禁用 Wind / 同花顺 / 万得 / 彭博作为来源 - 相对估值分位 (target PE vs peer median) ### 6. Valuation - 当前 PE/PB/PS (from daily_basic) - 历史区间 (PB 历史 min-max, 是否破净) - **SOTP** 分部估值 (成熟业务 PB / 成长业务 PS 等) - **3 档目标价**: 悲观 / 基础 / 乐观 + 假设 + 空间 ### 7. Risk Factors - **表格**: 经营 / 财务 / 行业 / 治理 / 数据 5 类 - 每项有量化依据 + 严重程度 (高 / 中 / 低) ### 8. Credit / Investment View **信贷口径 (4C's)**: - **Character**: 国资背景 / 实控人稳定 / 治理透明度 - **Capacity**: 营收规模 + 偿债能力指标 - **Capital**: 注册资本 + 净资产结构 - **Collateral**: 抵押物 specialised 程度 + 清算折价 **具体授信建议**: 额度区间 + 期限 + 利率 (LPR+bp) + 增信要求 + 财务承诺 **投资口径**: Buy / Hold / Sell + 目标价 + 催化剂 + 反向风险 ## Hard constraints (enforced by prompt, checked by gates) 1. **每个硬数字必须溯源**: `X 亿元（src: income）` 或 `Y%（src: company_performance）` 2. **禁用 Wind / 万得 / 同花顺 / Bloomberg / 彭博** — 这些不是安装的 MCP, `source_authenticity_check` gate 会拦截 3. **不写模糊数字** — "约 XX 亿" / "大约" 必须加 `[EST]` + 推理依据 4. **Q4 单季变化用 pp 单位** — `+3.18pp` 不要 `%` (避开 HARD_NUMBER 误判) 5. **Peer 数字必须标 `[EST, per sector consensus]`** — 永远不能挂一个权威名称 6. **Data Flag 自审** — 若发现 income 反推 vs company_performance 净利率差异 > 0.3pp, 必须单独一段 `> Data Flag N:` 提示需要人工核实 ## Output files Writes **only two files** to `{out_dir}/`: 1. `analysis.md` — 2500-4500 字 8 节 memo 2. `data-provenance.md` — 每个硬数字一行: `| 指标 | 数值 | 单位 | 来源文件 stem | MCP tool |` **Not** slides-outline.md — that's the `banker-slides-pptx` skill's job. ## Usage ```bash # Pre-flight: raw-data/ already populated by cn-client-investigation Phase 3.5 ls <deliverable_dir>/raw-data/*.json # Build + dispatch prompt python3 scripts/build_md_prompt.py <ts_code> <name_cn> <industry> \ <raw_dir> <out_dir> > /tmp/prompt.md openclaw agent --agent main --thinking high --json --timeout 600 \ --message "$(cat /tmp/prompt.md)" # Agent writes analysis.md + data-provenance.md # Close any discipline gaps (agent's own provenance table sometimes misses # numbers it wrote into prose; this post-process bridges the last mile) python3 <cn-ci-scripts>/sync_provenance.py <out_dir> # Now hand off to banker-slides-pptx for Step 2 ``` ## Quality checklist - [ ] 8 sections all present (ES / Profile / Industry / Financial / Peer / Valuation / Risk / 4C's) - [ ] Every `\d+(亿元|%|元|倍)` in analysis.md has a provenance row (or `[EST]` tag) - [ ] Peer comparison has ≥3 companies, all tagged `[EST, per sector consensus]` - [ ] Valuation section has ≥2 methods (relative + SOTP or DCF) + 3 scenarios - [ ] Risk section is a **table** with severity levels (not a bullet list) - [ ] 4C's section gives a specific credit conclusion (额度 + 期限 + 利率 + 增信 + 财务承诺) - [ ] At least 1 `> Data Flag N:` self-audit paragraph (if income vs company_performance diverge) - [ ] `provenance_verify.py` PASS + `source_authenticity_check.py` PASS

path: references/banker_memo_md_prompt.md
content: # Banker Memo MD — Canonical Prompt Template

Substitute placeholders: `{ts_code}` / `{name_cn}` / `{industry}` / `{raw_dir}` / `{out_dir}` / `{file_list}` / `{uscc}`

---

## 身份

你是中资投行（卖方研究）资深分析师，覆盖{industry}板块。当前任务：基于 `{raw_dir}/` 真实 MCP 调用快照，针对 **{name_cn}（{ts_code}）** 写**投行级深度研报 memo 的 MD 文档**，供信贷评审委员会 + 股权投资经理共用。

**本次任务只写 MD + 溯源表，不写 slides-outline（那是下一个 skill 的事）。**

## 你有的真实数据（读取 {raw_dir}/ 目录）

{file_list}

**不可引用此目录之外的数据**。统一社会信用代码：{uscc}。

## 研报框架（8 节必写，表格为主，不要罗列 bullet dump）

### 1. Executive Summary (300-500 字)
- 一句话核心观点（投资/授信 thesis）
- 3 个支撑论据（每个必须带 `(src: 文件名 stem)`）
- **具体授信建议**：额度区间（XX 亿）+ 期限 + 利率（LPR+bp 或 X.X%）+ 增信要求 + 财务承诺；或**投资评级** Buy/Hold/Sell + 目标价区间 + 催化剂
- 1-2 个关键风险

### 2. Company Profile
- 沿革（成立 + 上市 + 经营期限）表格
- 主业拆解（`{industry}` 展开到子细分）
- 股权 + 资本结构表格（注册资本 + 股本 + 市值 + 法人）

### 3. Industry Dynamics
- 赛道特征（周期性 / 技术迭代 / 政策驱动）2-3 段
- 中国市场位置（份额估算，标 `[EST, per sector consensus]`）
- 主要竞争者 3-5 家（国内 + 海外），每家数字标 `[EST]`
- 政策环境（十四五专项 / 产业补贴 / 监管趋势）

### 4. Financial Deep-Dive（表格为主）

**必写表格 1：3 年年度对比**
| 指标 | 2022 | 2023 | 2024 | YoY 24 vs 23 |
|------|------|------|------|-------------|
| 营收（亿元） | ? | ? | ? | ? |
| 归母净利（亿元） | ? | ? | ? | ? |
| ROE | ? | ? | ? | ? |
| 毛利率 | ? | ? | ? | ? |
| 资产负债率 | ? | ? | ? | ? |

**必写表格 2：季度趋势（全 12 季度）**
从 company_performance.json 取 2022Q1 → 2024Q4 的 EPS/ROE/毛利率/净利率/资产负债率，用表格呈现。

**必写 Data Flag**：
- **Flag 1（数据口径）**：若 income.total_revenue / n_income_attr_p 反推的净利率与 company_performance 的 netprofit_margin 差异 > 0.3pp，单独一段 `> **Data Flag 1**：...` 说明口径差异 + 建议评审前向公司 IR 确认
- **Flag 2（Q4 单季 vs YTD）**：Tushare 年终是 YTD 累积，Q4 单季需用 (Q4 累积 - Q3 累积) 近似 → 明确指出这是近似值，精确数字需拉年报
- **Flag 3+（若存在）**：QoQ 跳变 > 5pp / 行业周期底部异常 / 减值集中释放 等必须 flag

### 5. Peer Comparison（必写表格）

列 3-5 家同业（国内 + 海外），关键指标对比。**每个 peer 数字必须标 `[EST, per sector consensus]`**：

| 公司 | 股票代码 | 总市值 | PE(TTM) | PB | ROE 2024 | 备注 |
|------|---------|-------|---------|----|---------|-----|
| **{name_cn}** | {ts_code} | {real} | {real} | {real} | {real} | 本次分析对象 (src: ...) |
| Peer A | XXX.SZ | ~XX 亿 [EST] | ~XXx [EST] | ~X.Xx [EST] | X% [EST] | [EST] + 备注 |
| ... |

**禁用**：Wind / 万得 / 同花顺 / 彭博 / Bloomberg 作为 peer 数据来源。只能标 `[EST, per sector consensus]`。

相对估值分位分析：target PE vs peer median → 溢价/折价百分比 + 背后逻辑。

### 6. Valuation

- 当前 PE/PB/PS (daily_basic)
- 历史估值区间（PB min-max，是否破净）
- **SOTP 分部估值**（成熟业务 PB 0.x / 成长业务 PS 1.x）必写
- **3 档目标价**（必写表格）：

| 情景 | 假设 | 目标价（元） | 空间 |
|------|------|------------|------|
| 悲观 | PE Xx / EPS Y → | X.X | -X% |
| 基础 | PE Xx / EPS Y → | X.X | 0% |
| 乐观 | PE Xx / EPS Y → | X.X | +X% |

### 7. Risk Factors（必写表格，5 行）

| 风险类别 | 具体风险 | 量化依据 | 严重程度 |
|---------|---------|---------|---------|
| 周期性风险 | ? | (src: company_performance) | 高/中/低 |
| 财务杠杆风险 | ? | (src: company_performance) | 高/中/低 |
| 治理 / 诉讼风险 | ? | (src: primematrix 或 EST) | 高/中/低 |
| 行业竞争风险 | ? | [EST] | 高/中/低 |
| 数据口径风险 | ? | Data Flag 引用 | 高/中/低 |

### 8. Credit / Investment View（4C's + 投资评级，必写）

**信贷 4C's 表**：
| 维度 | 结论 | 量化依据 |
|------|------|---------|
| Character (治理) | ? | (src: primematrix) |
| Capacity (经营) | ? | (src: income, company_performance) |
| Capital (资本结构) | ? | (src: daily_basic, primematrix) |
| Collateral (抵押物) | ? | 推理 |

**具体授信建议** 必写完整项目：
- 授信额度 X-X 亿元
- 期限 X 年（滚动 / 一次）
- 利率 LPR+Xbp (X.X-X.X%)
- 增信要求：设备抵押 X% + 应收质押 X% / 担保 / ...
- 财务承诺：资产负债率不超 X% / 利息保障倍数 > X / ...
- 用途限定：营运资金 / 资本支出另议 / 禁止分红

**投资评级**：Buy / Hold / Sell (6 个月视角)
- 目标价 X.X - X.X 元（当前 X.X 元，空间 +/-X%）
- 催化剂：...
- 反向风险：...

## 硬约束（违反直接 reject）

1. **每个硬数字必须溯源**。格式：`X 亿元（src: income）` 或 `Y%（src: company_performance）`；peer 数字用 `[EST, per sector consensus]`
2. **禁用 Wind / 万得 / 同花顺 / Bloomberg / 彭博**。这些不是安装的 MCP 工具，`source_authenticity_check.py` gate 会拦截。
3. **不写模糊数字**。"约 XX 亿 / 大约 / 估计" 必须跟 `[EST]` 标注 + 推理依据说明。
4. **Q4 单季变化用 `pp` 单位**（例 `+3.18pp`），不要 `%` 或 `亿元`（避免 HARD_NUMBER regex 把单季差异也列入 provenance 校验）。
5. **Data Flag 自审**。若 income 反推净利率 vs company_performance 差异 > 0.3pp，**必须**写 `> **Data Flag N**：...` 段落，说明口径差 + 评审前核实动作。
6. **Risk + Credit View 必须表格呈现**，不许 bullet dump。

## 输出（只写入 {out_dir}/）

1. `analysis.md` — 完整 8 节投行 memo（预期 2500-4500 字，表格为主）
2. `data-provenance.md` — 每个硬数字一行：`| 指标 | 数值 | 单位 | 来源文件 stem | MCP tool |`

**不要输出 slides-outline.md 或任何 PPT 内容**——那是下一个 skill（`banker-slides-pptx`）的工作。

全部写完后**仅**告诉我两个文件的绝对路径 + 大致字数，不要把 md 内容贴回来。


path: scripts/build_md_prompt.py
content: #!/usr/bin/env python3
"""Parameterise the banker-memo-md prompt template for a CN listed company.

Usage:
    python3 build_md_prompt.py <ts_code> <name_cn> <industry> <raw_data_dir> <output_dir>

Outputs the full prompt to stdout."""
from __future__ import annotations
import glob, pathlib, sys


def main() -> int:
    if len(sys.argv) != 6:
        sys.exit("usage: build_md_prompt.py <ts_code> <name_cn> <industry> "
                 "<raw_dir> <out_dir>")
    ts_code, name_cn, industry, raw_dir, out_dir = sys.argv[1:6]

    tmpl = (pathlib.Path(__file__).resolve().parent.parent /
            "references" / "banker_memo_md_prompt.md").read_text(encoding="utf-8")

    files = sorted(glob.glob(f"{raw_dir}/*.json"))
    file_list = "\n".join(f"- `{pathlib.Path(f).name}`" for f in files) or \
                "(raw-data/ is empty — run cn-client-investigation Phase 3.5 first)"
    uscc = next((pathlib.Path(f).stem.split("-primematrix-")[0]
                 for f in files if "primematrix" in pathlib.Path(f).name), "N/A")

    out = (tmpl
        .replace("{ts_code}", ts_code)
        .replace("{name_cn}", name_cn)
        .replace("{industry}", industry)
        .replace("{raw_dir}", raw_dir)
        .replace("{out_dir}", out_dir)
        .replace("{file_list}", file_list)
        .replace("{uscc}", uscc))
    print(out)
    return 0


if __name__ == "__main__":
    sys.exit(main())


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)