个股深度分析的核心工作流。当用户要求"深度分析 / 全面分析 / 帮我看看 / 值不值得买 / DCF / 机构建模 / 首次覆盖 / 投委会备忘录"等涉及个股研究的请求时触发。覆盖 A 股、港股、美股,产出 22 维数据 + 66 位大佬量化评审 + 6 种机构级估值建模 (DCF/Comps/LBO/3-Stmt/Merger) + 7 种研究产物 (首次覆盖/财报解读/催化剂日历/投资逻辑追踪/晨报/量化筛选/行业综述) + 6 种决策方法 (IC Memo/DD/Porter/单位经济/VCP/再平衡) + 杀猪盘检测,最终生成 Bloomberg 风格 HTML 报告 + 社交分享战报。关键词:股票、个股、深度分析、估值、DCF、comps、首次覆盖、IC memo、杀猪盘、龙虎榜、akshare。
Scanned 9/2/2026
Install to Claude Code
npx -y skills add Serennity007/awesome-stock-quant-skills --skill deep-analysis --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Deep Analysis?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/serennity007-deep-analysis)More formats (shields.io, HTML) on the badges page.
---
name: deep-analysis
description: 个股深度分析的核心工作流。当用户要求"深度分析 / 全面分析 / 帮我看看 / 值不值得买 / DCF / 机构建模 / 首次覆盖 / 投委会备忘录"等涉及个股研究的请求时触发。覆盖 A 股、港股、美股,产出 22 维数据 + 66 位大佬量化评审 + 6 种机构级估值建模 (DCF/Comps/LBO/3-Stmt/Merger) + 7 种研究产物 (首次覆盖/财报解读/催化剂日历/投资逻辑追踪/晨报/量化筛选/行业综述) + 6 种决策方法 (IC Memo/DD/Porter/单位经济/VCP/再平衡) + 杀猪盘检测,最终生成 Bloomberg 风格 HTML 报告 + 社交分享战报。关键词:股票、个股、深度分析、估值、DCF、comps、首次覆盖、IC memo、杀猪盘、龙虎榜、akshare。
version: 3.9.4
author: FloatFu-true
license: MIT
metadata:
hermes:
tags: [finance, stocks, a-share, hong-kong, us-stocks, dcf, valuation, equity-research, trap-detection]
related_skills: [investor-panel, lhb-analyzer, trap-detector]
---
# Stock Deep Analysis · 深度分析工作流 v2.2
> 你正在扮演一位**首席股票分析师**。你身边有一套完整的量化工具箱,但最终的判断和叙事**必须你来写**。
> 脚本负责算数,你负责推理和下结论。
## 🎯 角色定位(非常重要)
- **你不是脚本的搬运工** — 不要只把 `cat xxx.json` 的结果往报告里贴。
- **你是分析师** — 你读原始数据 + 量化结果,然后用自己的判断串起一个有冲突感、有洞察的叙事。
- **脚本给你提供 5 类产物**:
1. **原始数据** (Task 1 · 22 维 fetcher)
2. **机构建模结果** (Task 1.5 · DCF/Comps/LBO/3-Stmt/IC Memo/Porter 等 22 种方法的计算输出)
3. **65 人评委量化裁决** (Task 3 · 每人引用具体规则)
4. **数据完整性报告** (哪些字段缺失 / 哪些降级)
5. **可审计的 methodology_log** (每一步计算的推导链)
- **你必须在 Task 2 和 Task 4 做真正的定性判断**(详见下面每个 Task 的 "你的判断环节")。
## ⛔ 硬性门控规则(违反即停止)
1. **必须按 Task 1 → 1.5 → 2 → 3 → 4 → 5 顺序**。前一 Task 的产物 JSON 不存在时禁止开始下一步。
2. **数据必须来自脚本或真实 web search**,禁止编造数字。任何推断都要标注来源。
3. **每个 Task 完成后打进度条**(20 字符宽度),让用户看到节奏。
4. **Task 5 报告组装禁止空泛话术**("基本面良好" / "前景广阔" / "值得关注" — 这三个词组出现即失败)。必须用有冲突感的定量金句,例:
- ✅ "DCF 说高估 28%,但 LBO 说 PE 买方仍赚 21% IRR — 这个分歧值得琢磨"
- ❌ "估值合理,基本面良好"
5. **矛盾必须呈现,不准和稀泥**:DCF 与 Comps 结论冲突时,**把冲突写进报告**;65 评委分歧大时,**强调分歧本身是信息**。
6. **Task 1 必须并行执行**(4 个子 agent / wave),串行跑 22 个 fetcher 直接扣分。
### ⛔ HARD-GATE-UPDATE-PROMPT · 新版本提示(v2.14)
<HARD-GATE>
会话启动 hook 会后台检查 GitHub 最新 release,如果本地版本落后,会在
`skills/deep-analysis/scripts/.cache/_global/update_prompt.md` 写入完整提示文案。
**你必须在第一次回应用户前检查这个文件**:
1. 读 `.cache/_global/update_prompt.md`(不存在 = 无需提示,跳过即可)
2. 若存在 · 把文件完整内容作为 **第一条消息** 展示给用户
3. 用 `AskUserQuestion` 或自然语言收集用户回答(y / s / n)
4. 调用 `python3 -c "from lib.update_check import handle_answer; print(handle_answer('<ans>', '<latest>'))"` 把用户回答写回状态文件 · latest 从提示文案里的版本号提取
5. 处理完删除 `.cache/_global/update_prompt.md`,这样同一会话不会重复弹
6. 根据用户选择:
- `y` → 告诉用户按 README 安装章节的命令执行(Claude Code: `/plugin update stock-deep-analyzer` · git clone: `cd UZI-Skill && git pull` · Hermes: `hermes skills update wbh604/UZI-Skill/skills/deep-analysis`),然后继续用户原请求
- `s` → 直接继续用户原请求(handle_answer 已记 skip 到 cache)
- `n` → 直接继续用户原请求
如果用户没有原请求(首次进入会话),展示完提示后等待用户开始对话。
**绝不能**:
- ❌ 跳过这个检查直接回应用户的分析请求
- ❌ 把提示文案改短、改写、合并到其他消息里
- ❌ 在用户只说 "分析 XX" 时直接开跑不先展示更新提示
</HARD-GATE>
### ⛔ HARD-GATE-NAME · 股票名纠错(v2.3)
<HARD-GATE>
若 `stage1()` 返回 `{"status": "name_not_resolved", "candidates": [...]}`(或生成了
`.cache/{input}/_resolve_error.json`),你**绝不能**假装猜到正确股票继续跑。
你必须:
1. 读 `_resolve_error.json` 拿到 `user_input` 和候选列表
2. 用 `AskUserQuestion` 把 Top 3-5 候选呈现给用户("你是不是想输入 X?")
3. 用户确认后,用**选中的代码**(如 `000582.SZ`)而不是原始名字重跑 `stage1()`
4. 若候选为空(真查不到),告知用户并建议直接输入代码
唯一例外:用户原话含"自动选最相近的"或明确说"就是 Top1" — 此时可以不问
</HARD-GATE>
### ⛔ HARD-GATE-NON-STOCK · ETF/LOF/可转债 必须引导到成分股(v2.9.2)
<HARD-GATE>
若 `stage1()` 返回 `{"status": "non_stock_security", "security_type": "etf|lof|convertible_bond", ...}`
(或 `.cache/{ticker}/_resolve_error.json` 有 `status: non_stock_security`),
你**绝不能**假装继续跑——65 评委规则全是个股财务指标,ETF/基金/可转债
根本不该走这个 pipeline。
你必须:
1. 读 `_resolve_error.json`,拿 `label` / `why` / `top_holdings`
2. **向用户明确说明**:"本插件是**个股**深度分析引擎,{label} 未覆盖"
3. **若是 ETF**(`top_holdings` 非空):
- 列出前 10 大持仓(已在 payload 里):rank / name / code / weight_pct
- 用 `AskUserQuestion` 问:"你想分析 ETF 里的哪只成分股?"
- 用户选定后用**成分股代码**(如 `601899.SH`)重跑 `stage1()`
4. **若是 LOF 基金**:告知"基金评估用专门工具,本插件只分析个股"
5. **若是可转债**:建议"分析正股或用集思录可转债工具"
**绝不能**:
- 硬把 ETF 跑完 stage1(22 维大多 N/A)
- 虚构"ETF 评委意见"(65 评委从没为 ETF 设计过规则)
- 看到 `_resolve_error.json` 就忽略继续调 stage2
Payload 示例(agent 看到这个就知道该走 ETF 引导流程):
```json
{
"status": "non_stock_security",
"security_type": "etf",
"ticker": "512400.SH",
"label": "ETF",
"top_holdings": [
{"rank": 1, "code": "601899.SH", "name": "紫金矿业", "weight_pct": 12.5},
{"rank": 2, "code": "603993.SH", "name": "洛阳钼业", "weight_pct": 9.8},
...
],
"user_prompt": "请选择要分析的成分股(输入编号或代码)"
}
```
</HARD-GATE>
### ⛔ HARD-GATE-SCHOOL-LOCK · 用户锁定单一流派视角(v3.5.0)
<HARD-GATE>
当用户用 `python run.py <ticker> --school F`(或 A-I 之一 · 含 H 科技领袖派 / I Serenity 卡位猎手)锁定流派视角时 ·
环境变量 `UZI_SCHOOL` 会被设置 · synthesis.json 里 `school_lock` 字段也会标注。
**进入 stage1 后的 role-play 阶段 · 你必须**:
1. **读 `panel.json` 里 group == UZI_SCHOOL 的评委**(通常 5-8 人)· 只 role-play 这些人
2. 其他派评委已被规则引擎标 `signal=skip` · reason="用户锁定 X 派视角" · 你**不要再给他们写评语 / 翻盘**
3. `agent_analysis.json` 必须自我约束:
- `panel_insights` 仅讨论该派内部分歧 · 不要写"巴菲特说 X · 赵老哥说 Y"这种跨派对比
- `great_divide_override.bull_say_rounds / bear_say_rounds` 必须都来自该派评委
- 若该派 5-8 人全看多 · 多空辩论也得**派内分歧版本**(如游资里"打板派 vs 卡位派")
4. **报告顶部已渲染 SCHOOL LOCK banner** · 用户/分享者一眼能看出本次仅看了该派 · 避免被误读为全 65 评委结论
**绝不能**:
- ❌ 不顾 `UZI_SCHOOL` 把 65 人都 role-play 一遍(其他派 skip 状态会被你的 override 覆盖 · 误导用户)
- ❌ 在 `panel_insights` 里写"价值派看空但游资看多"这种跨派叙事(用户已选了一派 · 不需要外部对比)
何时 skip 本 HARD-GATE:
- `UZI_SCHOOL` 未设置(默认 · 全 65 评委正常 role-play)
- `synthesis.json["school_lock"] is None`
</HARD-GATE>
### ⛔ HARD-GATE-PERSONA-ROLEPLAY · 65 评委 role-play 必须读 YAML persona(v2.15)
<HARD-GATE>
从 v2.15.0 起,`skills/deep-analysis/personas/*.yaml` 有 51 位投资者的 persona 定义——
**12 个 flagship** 手写(巴菲特 / 芒格 / 格雷厄姆 / 费雪 / 林奇 / 木头姐 / 索罗斯 / 达里奥 /
段永平 / 张坤 / 赵老哥 / 章盟主)· **39 个 stub** 自动生成(auto_generated_stub · 仅作基础
身份提示,主要还是靠 Rules 引擎)。**13 位 v3.7.0 新晋**(Andreessen/Naval/黄仁勋/Musk 等)
暂无 YAML · 由 `lib/investor_personas.py` 台词库 + Rules 引擎驱动 · role-play 时按其公开
言论风格演绎即可。
**当你进入 stage1 后的 role-play 阶段时,必须**:
1. **读 `skills/deep-analysis/personas/{investor_id}.yaml`**(id 跟 panel.json 里一致,如
`buffett.yaml` / `zhao_lg.yaml`)
2. 对 **flagship persona**(12 个)· YAML 优先级 > Rules headline:
- 每条 headline 必须引用 `key_metrics` 里的具体条目(如巴菲特说"ROE 连续 10 年 > 15%",
段永平说"PE 40 红线",林奇说"PEG < 1",赵老哥说"封板时间 + 市值 1000 亿上限")
- 每条 reasoning 必须带 `voice` 字段的风格词(巴菲特的"Mr. Market"、林奇的"tenbagger"、
木头姐的"Wright's Law / exponential disruption"、赵老哥的"龙头战法")
- **signal 必须与 persona 历史立场对齐**:巴菲特不会对 PE 882 的股票说买入;木头姐不会
对白酒说"五大平台之一";赵老哥不会对 9000 亿市值说"打板"
3. 对 **stub persona**(39 个 · _meta.status=auto_generated_stub)· Rules 引擎输出优先:
- YAML 仅补充身份信息(school / group)
- 不要假装比 Rules 知道更多
- 可以按 group 风格模板补充简短 voice,但不得编造具体历史言论
4. **prefix-stable system message**(如果走 `lib.personas.build_system_message`):
- 同一 SNAPSHOT JSON 只拼一次
- 65 persona 调用时 system message 字节级一致(prompt cache 命中)
**绝不能**:
- ❌ 给某个投资者写他历史上不可能持的立场(林奇对 EPS 0 的股票说 PEG 可算 · 木头姐对
OEM 代工说"必须重仓")—— Rules 引擎历史上有 4 个此类硬伤,v2.15 就是为修这个
- ❌ 用千篇一律的模板话术("基本面良好"、"值得关注"、"估值合理")—— 每个 persona 必须有
自己 voice 字段里的特色语言
- ❌ 绕过 YAML 直接编 persona 历史立场(尤其是有 flagship 档案的 12 位 · 必须读档案)
</HARD-GATE>
### ⛔ HARD-GATE-QUALITATIVE · 6 维定性维度必须 agent 深度分析(v2.4)
<HARD-GATE>
在 stage2 之前,**3_macro / 7_industry / 8_materials / 9_futures / 13_policy / 15_events**
这 6 个定性维度必须由 agent 做跨域联想 + 多源抓取后产出结构化分析,不得直接用爬虫片段
拼到 dim_commentary 里。
**强制流程**(详见 `references/task2.5-qualitative-deep-dive.md`):
1. 读 `task2.5-qualitative-deep-dive.md` — 这是详尽操作手册(6 维每维 4-7 问、6 条跨域
因果链、各维度浏览器 URL 模板、输出 schema)
2. **Spawn 3 个并行 sub-agent**(Agent tool · subagent_type=general-purpose):
- **A · Macro-Policy**:3_macro + 13_policy
- **B · Industry-Events**:7_industry + 15_events
- **C · Cost-Transmission**:8_materials + 9_futures
3. 每个 sub-agent 必须使用:
- `WebSearch`(精确到公司名 + 代码 + 行业关键词)
- `Chrome/Playwright MCP`(打开 cninfo/xueqiu/gov.cn/证监会/工信部 抓原文)
- `mx_api.MXClient`(若 `MX_APIKEY` 已设置)
4. 合并三个 sub-agent 的输出,写入 `.cache/{ticker}/agent_analysis.json` 的
`qualitative_deep_dive` 字段(schema 见 task2.5 第 5 节)
5. **质量硬红线**:
- 每维 `evidence` ≥ 2 条且每条必有具体 URL
- 6 维合计 ≥ 3 条 `associations`(跨域因果链,对应 task2.5 第 3 节的 6 条里选 3)
- `dim_commentary` 每句必须 cite `qualitative_deep_dive.*.evidence[*].url` 之一
**绝对禁止**:
- 单 agent 串行覆盖 6 维(必须 3 个并行 sub-agent)
- 把 raw_data 的爬虫片段直接粘贴当 commentary
- evidence 为空、url 空字符串、或仅用"值得关注/基本面良好/需要观察"这三个废话词
- 跳过 task2.5 的问题清单自由发挥
用户要求原话:"不能只靠数据爬取,必须要 agent 介入高强度分析 + 多 agent 操作一定要加入进去"
</HARD-GATE>
### ⛔ HARD-GATE-PLAYWRIGHT-AUTOFILL · agent 必须主动触发 Playwright 兜底(v2.13.5)
<HARD-GATE>
用户反馈:"我使用下来,并没有遇到模型主动使用 Playwright 的问题"。
v2.13.5 起 **agent 介入阶段(stage1 → stage2 之间)必须主动触发 Playwright
兜底**,不能等脚本 stage1 末尾自动跑就算完。原因:
1. Stage1 末尾的 `autofill_via_playwright` 只跑一次 · 如果那时某维度 data 非空
但全是 "—",`_dim_needs_fallback` 判不需要兜底,会被跳过
2. Agent 介入后往往知道"哪些维度不够"(自查报告里报 warning/critical)· 应该
主动再跑一次 Playwright · 而不是在 `dim_commentary` 里写"数据缺失,参考同业"
这种废话
**强制流程**(agent role-play 开始前必走):
**Step A · 读网络 profile**(新 v2.13.5 · `.cache/_global/network_profile.json`)
```python
import json
from pathlib import Path
prof_path = Path(".cache/_global/network_profile.json")
if prof_path.exists():
net = json.loads(prof_path.read_text(encoding="utf-8"))
# net["domestic_ok"] / net["overseas_ok"] / net["search_ok"]
# net["recommendation"] 人读的一句话建议
print(f"网络: {net['recommendation']}")
```
**Step B · 读自查 issues 找低质量维度**
```python
issues_path = Path(f".cache/{ticker}/_review_issues.json")
issues = json.loads(issues_path.read_text())
low_quality_dims = [
i["dim"] for i in issues.get("issues", [])
if i.get("severity") in ("critical", "warning") and i.get("category") == "data"
]
# 例:["4_peers", "7_industry", "8_materials"]
```
**Step C · 主动触发 Playwright 兜底**(即使 stage1 跑过也再跑一次 · 用 FORCE=1)
```python
import os
os.environ["UZI_PLAYWRIGHT_FORCE"] = "1"
from lib.playwright_fallback import autofill_via_playwright
summary = autofill_via_playwright(raw, ticker)
# summary: {"attempted": X, "succeeded": Y, "failed": Z, "skipped_reasons": {...}}
```
**Step D · Playwright 失败的 dim · agent 用知识 + web_search 手工补**
Playwright 也抓不到的维度(比如某些需要登录的页面)· **不能**在 commentary 里
写空话 · 应该:
1. 调 `WebSearch` 或 `web_search_trusted` 补原始资料
2. 调 `mx_api`(若 MX_APIKEY 已设)
3. 最后降级到 agent 的常识 + 明确标注"基于公开信息推断,非一手"
**绝对禁止**:
- 看到 `data.growth = "—"` 直接在 dim_commentary 里写"增速待补充"
- 忽略 `_review_issues.json` 的 warning 直接出报告
- Playwright summary.attempted=0 但未检查 `network_profile.json` 是否能用
**绕过方式**(仅 lite / CI 环境):
- `UZI_DEPTH=lite` · lite 模式 `playwright_mode=off` · 此 HARD-GATE 自动跳过
- `UZI_PLAYWRIGHT_ENABLE=0` · 显式禁用(但 deep 档不建议)
v2.13.5 改动:
- `lib/network_preflight.py` 升级 NetworkProfile(国内/境外/搜索 9 目标)· 写 cache
- `lib/playwright_fallback.DIM_NETWORK_REQUIREMENTS` 每维声明所需网络能力
- `autofill_via_playwright` 按 profile 自动跳过网络不可达的维度
</HARD-GATE>
### 🎯 STYLE-WEIGHTING · 按股票风格动态加权(v2.7 · 自动)
stage2 自动识别股票 style(白马 / 高成长 / 周期 / 小盘投机 / 分红防御 /
困境反转 / 量化因子 / 中性兜底),按 style 调整:
- 65 评委组级权重(A-I × style 矩阵)+ 8 个个体 override
- 22 维 fundamental dim multiplier
- neutral 半权计入 consensus(修正旧公式 0% 权重的问题)
报告 hero 区会显示 style chip + 加权前后分数对比。
**Agent 可在 `agent_analysis.json` 显式覆盖 style**(若你认为脚本误判):
```json
{
"agent_reviewed": true,
"detected_style_override": "growth_tech",
"style_override_reason": "市值虽大但属于科技成长轨道,不是传统白马"
}
```
**量化因子型 detection(用户特别要求)**:
- `lib/quant_signal.detect_quant_signal` 用结构性特征:基金 top-1 持仓 < 2%
→ 疑似量化(无需名字含"量化")
- 持有目标股票的基金里 ≥ 3 家量化基金且把目标股放进 top-10 → quant_factor
**私募量化交叉验证**(agent 可选):
若 quant_signal.count < 3 但你怀疑有私募量化重仓本股:
1. 查 dim_16_lhb 前 10 大游资席位是否含 `lib.quant_signal.KNOWN_PRIVATE_QUANTS`
(幻方 / 九坤 / 灵均 / 鸣石 / 因诺 / 明汯 / 玄信 / 衍复 / 宽德 / 念空)
2. `web_search "{name} 幻方 OR 九坤 OR 灵均 OR 明汯 重仓"`
3. `akshare.stock_main_stock_holder({code})` 看大股东列表
若交叉验证有 ≥ 1 家私募 + ≥ 1 家公募 → 升级 detected_style 为 quant_factor
### ⛔ HARD-GATE-AGENT-SELF-REVIEW · 机械级自查 · 必须通过才能出 HTML(v2.9)
<HARD-GATE>
**v2.9 起这个 gate 是机械强制的**——`assemble_report.py::assemble()` 会自动跑
`lib/self_review.py` 检查 ~13 条规则;有 critical 就 raise RuntimeError **拒绝**
生成 HTML。不会再依赖 agent 记性 / 自觉 / 手工核查。
**Agent 的职责**:在 stage2 合并完、准备发链接前,先跑:
```bash
cd skills/deep-analysis/scripts && python review_stage_output.py <ticker>
# → exit 0 = 可以出 HTML
# → exit 1 = 有 critical,必须先修
# → exit 2 = 有 warning,可以出但建议 ack
```
输出文件:`.cache/<ticker>/_review_issues.json`,含每条 issue 的 severity /
category / dim / issue / evidence / suggested_fix。
**自查覆盖的规则**(13 条,对应每次 BUG 经验):
| severity | check | 背后 BUG |
|---|---|---|
| 🔴 | `check_industry_mapping_sanity` | BUG#R10 行业碰撞(工业金属→农副食品加工) |
| 🔴 | `check_all_dims_exist` | wave2 timeout 导致 12_capital_flow 缺失 |
| 🔴 | `check_empty_dims` | crash / timeout 产生的空维度 |
| 🔴 | `check_hk_kline_populated` | BUG#R8 HK kline 无 fallback |
| 🔴 | `check_hk_financials_populated` | BUG#R7 HK financials 空 stub |
| 🔴 | `check_panel_non_empty` | panel 全 skip / avg_score 异常 |
| 🔴 | `check_coverage_threshold` | `_integrity.coverage_pct < 60` |
| 🔴 | `check_placeholder_strings` | synthesis 含 "[脚本占位]" |
| 🔴 | `check_agent_analysis_exists` | agent_analysis.json 缺失 / agent_reviewed!=True |
| 🟡 | `check_valuation_sanity` | DCF/Comps 全 0 |
| 🟡 | `check_metals_materials_populated` | 有色金属股票 materials 空 |
| 🟡 | `check_industry_data_coverage` | 7_industry 定性字段需 web_search 补 |
| 🟡 | `check_factcheck_redflags` | 编造"苹果产业链"无 raw_data 证据 |
**迭代流程**(agent 必须照做):
```
loop:
1. python review_stage_output.py <ticker>
2. 读 _review_issues.json
3. if critical_count > 0:
for each critical issue:
- 读 issue.suggested_fix
- 用 WebSearch / mx_api / Chrome MCP 补数据 OR 写 agent_analysis.json 覆盖 OR 重跑 stage1/stage2
重跑 review
4. if warning_count > 0:
for each warning: 要么修,要么在 agent_analysis.review_acknowledged 显式写原因
5. 若 critical_count == 0: 进入 HTML 生成
```
**绝不能**:
- 看到 exit 1 就 export UZI_SKIP_REVIEW=1 绕过(那是调试用的,生产发 HTML 给用户绝不该用)
- 修一半 critical 就出报告(review 不过 = 报告不 ship)
- 修了但不重跑 review(必须最后跑一次确认 passed=true)
**设计意图**(用户原话):
- "所有数据的补全问题都要做 agent 兜底和最后核查"(v2.7)
- "必须要有agent自己核对一遍所有内容,如果有问题就要修改"(v2.9)
v2.7 时这是软要求(agent 可能跳过)。v2.9 起是硬编码 block —— `assemble_report`
跑前强制跑 review,critical 不过就 RuntimeError。
</HARD-GATE>
### ⛔ HARD-GATE-FACTCHECK · 禁止编造未在 raw_data 出现的事实(v2.6)
<HARD-GATE>
论坛反馈过实际事件:分析"药明康德"时把它和"苹果订单"关联(药明康德是 CRO 不是
果链供应商)。这是 LLM 联想编造典型。
每条 dim_commentary / debate_say / risks 必须满足:
1. 引用的公司业务必须在 `raw_data.dimensions["0_basic"].data.main_business`
或 `["5_chain"]` 或 `["15_events"]` 中能找到出处
2. 引用的财务数字必须在 `["1_financials"]` 中
3. 引用的政策必须在 `["13_policy"]` snippets 里
4. 不确定的关联用 "据公开报道"/"待 web search 验证" 而不是肯定语气
5. 任何"X 公司是 Y 行业供应链一环"这种宏大叙事,必须 cite raw_data 里的具体证据
绝对禁止:
- "X(光学公司)受益于 Apple 订单" — 除非 raw_data 里有 Apple 客户关联
- "Y 公司是新能源核心标的" — 除非 raw_data 提到具体新能源业务
- "国家战略支持本股" — 除非 dim_policy 有具体政策原文 cite
非 Claude 模型(Codex/国产模型)尤其容易踩这个坑。stage2 不会自动检测事实正确性,
质量靠 agent 自查。
</HARD-GATE>
### ⛔ HARD-GATE-DATAGAPS · 数据缺口 agent 必须接管(v2.3)
<HARD-GATE>
若 `.cache/{ticker}/_data_gaps.json` 存在且 `tasks` 非空,你**必须**在调用
`stage2()` 之前逐条尝试补齐,按优先级:
1. **浏览器自动化**(最稳)— 用 Chrome/Playwright MCP 打开 xueqiu.com/S/{code}
或 quote.eastmoney.com/{code}.html 手动抓字段。特别是 `push2.eastmoney.com`
被反爬时,浏览器是唯一能拿到实时行情的通道。
2. **MX 妙想 API**(若 `MX_APIKEY` 已设置)— 用 `mx_api.MXClient.query()`
3. **WebSearch** 精确到代码(不要只搜公司名 — 会命中同名无关内容)
4. **逻辑推导** — 从已有数据算(净利率 = 净利润 / 营收;PE = 市值/净利润)
**仍然拿不到的字段**:在 `agent_analysis.json` 里写:
```json
"data_gap_acknowledged": {
"0_basic.industry": "已尝试 xueqiu/eastmoney/ws,均返回空 — 可能是新股或暂停上市",
"4_peers": "该细分行业上市公司不足 3 家,真的找不到同行"
}
```
stage2 会把这些字段标为"已确认拿不到",HTML 报告显示划线 chip + "—"而不是假数据。
**绝对禁止**:在补不到数据时用默认值(0 / 空字符串 / "—")当真实数据用、让规则引擎
对空 features 打分(会产生"没数据的幻觉",像之前"北部港湾"那次 panel 35.4% 共识
其实是空 features 导致的全 fail_msg)。
</HARD-GATE>
## 📊 进度条规范
每完成一个 Task,输出一行进度条(20 字符固定宽度):
```
[███░░░░░░░░░░░░░░░░░] 17% · Task 1/6 · 数据采集 ✓
[██████░░░░░░░░░░░░░░] 33% · Task 1.5 · 机构建模 ✓
[██████████░░░░░░░░░░] 50% · Task 2/6 · 维度打分 ✓
[█████████████░░░░░░░] 67% · Task 3/6 · 65 评委 ✓
[████████████████░░░░] 83% · Task 4/6 · 综合研判 ✓
[████████████████████] 100% · Task 5/6 · 报告组装 ✓
```
## 📋 6 Task 概览
| Task | 名称 | 产物 | 角色 |
|---|---|---|---|
| 1 | 22 维数据采集 | `.cache/{ticker}/raw_data.json` | 🤖 脚本 |
| 1.5 | 机构级建模 (DCF/Comps/LBO/3-Stmt/IC/Porter/…) | 内联在 raw_data.json 的 `dim 20/21/22` | 🤖 脚本 + **🧠 你的假设审查** |
| 2 | 22 维打分 + **定性判断** | `.cache/{ticker}/dimensions.json` | 🤖 脚本 + **🧠 你写定性评语** |
| 3 | 65 评委量化裁决 | `.cache/{ticker}/panel.json` | 🤖 规则引擎 |
| 4 | 综合研判 + **叙事合成** | `.cache/{ticker}/synthesis.json` | **🧠 你主导** |
| 5 | 报告组装 | `reports/{ticker}_{YYYYMMDD}/full-report.html` + share-card + war-report | 🤖 脚本 + **🧠 你的金句** |
---
## ⚡ 两段式执行(数据靠脚本,判断靠你)
流水线分两段——**中间你必须介入做 agent 分析**:
### Stage 1 · 数据 + 骨架分(立即执行,不要犹豫)
```bash
cd <repo_root>/skills/deep-analysis/scripts
pip install -r ../../../requirements.txt 2>/dev/null
python -c "from run_real_test import stage1; stage1('<股票名或代码>')"
```
Stage 1 自动完成:Task 1(22 维采集)→ Task 1.5(机构建模)→ Task 2(打分)→ Task 3(规则引擎骨架分)
### 你的分析环节(Stage 1 之后、Stage 2 之前)
<HARD-GATE>
Do NOT run stage2() until ALL of the following are complete:
1. You have READ .cache/{ticker}/panel.json and reviewed the 52 skeleton scores
2. You have SPAWNED sub-agents (or personally analyzed) each investor group
3. You have MERGED agent results back into panel.json with updated headline/reasoning/score
4. You have WRITTEN agent_analysis.json with dim_commentary (≥5 dimensions) + panel_insights
5. You have SET agent_reviewed: true in agent_analysis.json
Skipping this step produces a report with mechanical rule-engine output instead of
genuine investment analysis. The whole point of this plugin is agent-driven judgment.
</HARD-GATE>
核心是:
1. 读 `.cache/{ticker}/panel.json` 中 65 人的骨架分
2. **Spawn 4 个并行 sub-agent 分组 role-play 投资者**——让他们真正"扮演"巴菲特/赵老哥思考
3. 用 agent 的判断覆盖 panel.json 中的 headline/reasoning/score
4. **写 `agent_analysis.json`** 到 `.cache/{ticker}/` — 这是闭环的关键!
**agent_analysis.json 必填字段(缺字段 stage2 会 schema warning/error):**
| 字段 | 要求 | 触发校验 |
|---|---|---|
| `agent_reviewed` | 必须 `true` | ⚠️ 缺 → warning |
| `dim_commentary` | 至少 5 个维度,**每条 ≥20 字**(引用具体数字,禁止空泛) | 🔴 <20 字 → warning |
| `panel_insights` | **≥30 字**,评委投票分布 + 多空分歧分析 | ⚠️ <30 字 → warning |
| `great_divide_override` | punchline(≥10 字) + bull_say_rounds(≥3 条) + bear_say_rounds(≥3 条) | 🔴 缺字段 → error |
| `narrative_override.core_conclusion` | **≥20 字**综合定论 | ⚠️ <20 字 → warning |
| `narrative_override.risks` | **≥3 条**风险 | ⚠️ <3 条 → warning |
| `narrative_override.buy_zones` | **必须含 value/growth/technical/youzi 四个 key**,每个 key 内含 `price`(数值) + `rationale`(≥5 字解释) | 🔴 缺 key → error / ⚠️ 缺子字段 → warning |
| `qualitative_deep_dive` | 覆盖 3_macro/7_industry/8_materials/9_futures/13_policy/15_events 共 6 维。每维含:`evidence` 数组(≥2 条 `{source, url, finding, retrieved_at}`)、`associations` 跨域因果链(**6 维合计 ≥3 条** `{link_to, chain_id, causal_chain, estimated_impact}`)、`conclusion`(1-2 句)。详见 `references/task2.5-qualitative-deep-dive.md` 第 5 节 | 🔴 evidence 非 list → error / ⚠️ associations<3 → warning |
| `data_gap_acknowledged` | v2.3+ 推荐。dict 格式 `{"dim_key": "已尝试 X 但失败的原因"}`。标记数据采集失败但 agent 已知晓的维度,HTML 报告显示 ⚠️ 橙色徽章而非空白 | 🔴 类型非 dict → error |
#### agent_analysis.json 格式
```json
{
"agent_reviewed": true,
"dim_commentary": {
"0_basic": "建筑央企,主营市政/房建。市值偏小,营收稳但利润率极薄(1.2%),典型低毛利基建股。",
"1_financials": "ROE 不到 8%,连续 3 年下滑。现金流波动大,应收账款占营收比偏高,回款风险明显。",
"2_kline": "均线空头排列,MACD 死叉,量能萎缩。典型下跌趋势,不满足 Stage 2 条件。"
},
"panel_insights": "65 评委中,价值派集体看空(ROE 太低+无护城河),游资中性(有地方城投概念但板块热度不够),只有少数逆向投资者给出中性偏多。整体共识 32%,偏弱。",
"great_divide_override": {
"punchline": "DCF 说高估 23%,但城投重组预期让 LBO 视角的 IRR 仍有 18% — 这个冲突值得关注。",
"bull_say_rounds": [
"宁波城投整合预期 + 地方债化解受益,估值有弹性",
"PB 仅 0.9x,历史底部区间,安全边际够",
"综合看 62 分,城投故事讲通了就是翻倍"
],
"bear_say_rounds": [
"ROE 连降 3 年,基建毛利率 8% 是天花板",
"应收账款 / 营收 > 60%,回款是生死线",
"综合看 35 分,低质量资产不值得冒险"
]
},
"narrative_override": {
"core_conclusion": "宁波建工 · 48 分 · 谨慎。典型地方基建股,ROE 不到 8%、毛利率 8%,靠城投整合讲故事。66 位大佬 12 人看多,29 人看空。DCF 高估 23%,但 LBO 压力测试 IRR 18% — 博弈价值存在但风险更大。",
"risks": [
"ROE 持续下滑,连续 3 年低于 8%",
"应收账款占比过高,回款周期拉长",
"地方财政压力传导至工程款支付",
"行业竞争加剧,中标价格战",
"房建业务受地产下行拖累"
],
"buy_zones": {
"value": {"price": 3.85, "rationale": "PB 0.8x · 历史底部 + 净资产折价"},
"growth": {"price": 4.10, "rationale": "城投整合落地前的博弈价"},
"technical": {"price": 4.25, "rationale": "MA120 支撑位 · 需放量确认"},
"youzi": {"price": 4.50, "rationale": "城投板块联动时的短线切入点"}
}
}
}
```
**stage2() 会自动读取 agent_analysis.json,合并到 synthesis 中。** Agent 写入的字段优先级高于脚本生成的 stub。
### Stage 2 · 生成报告
```bash
python -c "from run_real_test import stage2; stage2('<ticker>')"
```
Stage 2 读取你更新后的 panel.json + agent_analysis.json,合并生成 HTML 报告。
如果没有 agent_analysis.json,退化为纯脚本模式(会打印警告)。
### 快速模式(跳过 agent 介入 · 仅 lite/medium)
如果用户说"快速分析"或时间紧:
```bash
cd <repo_root>
python run.py <股票> --no-browser
```
这会 stage1 + stage2 一把跑完,不做 agent 分析。速度快但评委判断全是规则引擎的机械输出。
> ⚠️ **v3.9.4 明确**:此模式只适用于 lite/medium 档。**`--depth deep` 不属于快速模式**——deep 档必须由你介入 role-play 66 评委并写 `agent_analysis.json`(见上方 HARD-GATE-PERSONA-ROLEPLAY)。看到 deep 档时不要直接 `run.py --depth deep` 一把梭。
---
## 🚀 详细流程(run.py 跑完后的人工审查)
### 第 0 步 · 识别股票
- `run.py` 已经自动识别了 ticker 并跑完所有 Task
- 读 `.cache/{ticker}/raw_data.json` 确认数据
- 向用户汇报:"**{name} ({ticker})** 分析完成,正在审查数据质量..."
---
### Task 1-3 · 已由 run.py 自动完成
`run.py` 内部执行了:
这个脚本会:
1. Wave 1 快速 fetcher(basic/kline/financials/valuation)
2. Wave 2 慢速 fetcher(research/events/macro/industry/materials/policy/sentiment/trap)
3. Wave 3 特殊维度(fund_managers, similar_stocks)
4. **Task 1.5 自动跑**:compute_dim_20/21/22 (DCF/Comps/LBO/3-Stmt/IC Memo/Porter/…)
5. 数据完整性校验(`lib/data_integrity.py`)
6. 65 评委量化引擎自动执行
脚本跑完后你读 `.cache/{ticker}/raw_data.json`,向用户汇报:
- 数据快照时间 + 市场状态
- 完整性报告(`_integrity` 字段)
- 有多少个 fallback 维度
- Task 1.5 的核心输出预览
### 🧠 逐维数据质量审查(每一步都必须 agent 介入)
<HARD-GATE>
Do NOT proceed to Stage 2 until you have personally inspected EVERY dimension's data
and fixed any garbage. Scripts collect data, YOU guarantee quality.
If a dimension has irrelevant content (city tourism guides for a stock analysis),
you MUST re-search and replace the data yourself.
</HARD-GATE>
**脚本只是第一道粗搜**。DuckDuckGo 中文搜索经常返回无关结果(搜"宁波建工"返回"宁波旅游攻略")。你必须**逐维审查 + 修复**:
#### 审查清单(每条都要过)
| 维度 | 检查什么 | 垃圾特征 | 你怎么修 |
|---|---|---|---|
| **0_basic** | name/industry 是否正确 | industry=None | 你 web search `"{code} 所属行业 主营业务"` 补上 |
| **5_chain** | upstream/downstream 是否是这家公司的 | 文字截断或无关 | web search `"{name} 上游供应商 下游客户"` 重写 |
| **7_industry** | 行业增速/TAM 有没有数据 | 全是默认值或空 | web search `"{industry} 行业规模 增速 2026"` |
| **8_materials** | 原材料描述是否相关 | 和主营无关 | web search `"{name} 原材料 成本构成"` |
| **13_policy** | 政策是否与该公司/行业相关 | 搜到无关政策 | web search `"{industry} 最新政策 2026"` |
| **14_moat** | 文字是否是公司分析 | 出现"拼音"、"字典释义"、"汉字演变" | web search `"{name} 竞争优势 核心技术 壁垒"` |
| **15_events** | 事件是否与这家公司相关 | "如何评价宁波"、"宁波旅游"、城市生活指南 | web search `"{name} {code} 最新公告 合同 中标 研发"` |
| **17_sentiment** | 舆情是否在说这家公司 | 短公司名匹配到同名无关内容 | web search `"site:xueqiu.com {name} 股票"` |
| **3_macro** | 宏观环境描述是否有内容 | 全是空或默认 | web search `"中国 {industry} 宏观环境 利率 2026"` |
| **同行对比** | similar_stocks 是否同行业 | 建筑股配了光学同行 | 检查行业是否正确,手动指定正确同行 |
#### 审查流程
```
for each dimension in raw_data.dimensions:
1. 读数据 → 肉眼扫一遍文字内容
2. if 内容与公司主营无关 or 明显是垃圾:
→ web search 重新搜(用公司名 + 行业关键词)
→ 用搜索结果替换 raw_data 中的内容
3. if 数据完全缺失:
→ web search 补充
→ 如果搜不到 → 在报告中标注"数据缺失"而非留空
4. if 数据看起来合理:
→ 通过,下一个维度
```
#### 重搜模板
当你发现某个维度数据有问题时,用 web search 重搜:
**事件驱动**(最容易出垃圾):
```
搜索 "{公司全称} {股票代码} 最新公告 合同中标 研发进展 2026"
不要搜 "{城市名}"——只搜公司名和代码
```
**宏观环境**(脚本经常搜不到):
```
搜索 "中国 {行业} 宏观环境 利率政策 景气度 2026"
```
**护城河**(容易搜到字典页):
```
搜索 "{公司名} 核心竞争力 技术壁垒 市场份额 护城河"
```
**舆情**(短名容易误匹配):
```
搜索 "site:xueqiu.com {股票代码}" 或 "site:guba.eastmoney.com {股票代码}"
```
#### 数据缺失时的升级策略
脚本拿不到数据时,**不要留空**,按优先级升级:
1. **Web search**(最快)— 用 WebSearch tool 直接搜
2. **浏览器搜索**(更准)— 用 Chrome/browser tool 打开东方财富/雪球,手动查数据
3. **计算推导**(兜底)— 从已有数据推算(如 从营收和净利算净利率)
4. **标注缺失**(最后手段)— 在报告中明确写"该维度数据暂缺",不要假装有数据
**每个维度都要有内容。如果 22 个维度里有超过 3 个是空的或垃圾,你的报告就是不合格的。**
**原则:脚本是你的数据采集助手,但你是质量把关人。垃圾数据进报告 = 你的失职。**
### 🧠 你的判断环节(Task 1.5 假设审查)
脚本跑 DCF / LBO / 3-Stmt 用的是默认假设(见 `references/task1.5-institutional-modeling.md`):
- Stage 1 growth 10% · Stage 2 growth 5% · terminal g 2.5%
- Beta 1.0 · target debt ratio 30% · tax 25%
**你必须审视这些默认值对这只股是否合理**:
- 如果是光学/半导体 → beta 应该 1.3+,stage1_growth 可能 15-20%
- 如果是消费白马 → terminal g 可以给到 3%,beta 可以 0.8
- 如果是 ST / 周期低谷 → stage1_growth 负值,别用 10%
**如果默认假设明显不对**,你应该:
1. 在 Task 4 的叙事里**明说**: "默认 DCF 用 stage1 10% 偏低,行业实际 18%"
2. 或重跑一次:
```python
from lib.fin_models import compute_dcf
adjusted = compute_dcf(features, assumptions={"stage1_growth": 0.18, "beta": 1.3})
```
将调整后的数字写入 `synthesis.json` 的 `adjusted_dcf` 字段供报告引用。
---
### Task 2 · 22 维打分 + **Agent 定性判断** (🤖 脚本 + **🧠 你**)
**脚本部分**:`score_dimensions(raw)` 给每个维度一个 1-10 打分 + weight。
### 🧠 你的判断环节(最重要 — 不能跳过)
脚本的打分是"看数字给分",但很多维度需要你**真正理解背后的故事**。
**推荐做法**:对关键维度(财报 / 估值 / 护城河 / 行业),spawn 一个 sub-agent 去做 web search,搜索这家公司的最新深度分析文章:
```
Agent prompt:
搜索 "{company_name}" 的最新深度分析,重点关注:
1. 最近一个季度的业绩亮点和隐忧
2. 行业竞争格局变化
3. 管理层最近的公开表态
4. 券商研报的核心观点分歧
来源:雪球 / 东方财富 / 券商研报 / 财经媒体
```
用搜索结果来写每个维度的定性评语——这样你的评语是**基于真实信息的判断**,不是对着数字编故事。
**每个维度你都要写一条 1-2 句话的定性评语**,回答 5 个问题:
1. **数据可信吗?** (数据源 / 时效 / fallback 比例)
2. **数字背后的故事是什么?** (光看 ROE 11.8% 不够 — 为什么从 18% 掉到 11.8%?)
3. **与同行比怎么样?** (peer comparison 里它排第几)
4. **有哪些结构性问题?** (一次性损益 / 关联交易 / 存货堆积)
5. **对论点影响大吗?** (这维度该加权还是降权)
把你的评语写到 `synthesis.json` 的 `dim_commentary` 字段,格式:
```json
"dim_commentary": {
"1_financials": "ROE 从 2021 年的 18% 掉到 2024 年的 11.8%,主因是…(你的解读)",
"2_kline": "Stage 2 但距 60 日高点仅 -5%,动量接近顶部…",
...
}
```
**没有评语的维度会被标红显示 ⚠️ 未分析**,所以别跳过。
---
### Task 3 · 65 评委审判 (**🧠 Agent 主导 · 规则引擎仅为参考**)
> **核心原则**:每个投资者的判断不是"跑公式",而是 Claude 真正站在这个人的角度思考。规则引擎给出量化参考分,最终判断由你做。
>
> 详细架构见 `references/task3-agent-evaluation.md`
### Step 3.1 · 跑规则引擎获取骨架分
`run_real_test.py` 已经自动完成了三层评估(`investor_knowledge.py` 现实检验 → `investor_criteria.py` 规则打分 → 合成)。读 `.cache/{ticker}/panel.json` 拿到结果。
### Step 3.2 · Spawn 并行 Sub-Agent(核心步骤)
**你必须 spawn 4 个并行 sub-agent**(用 Agent tool),每个负责一组投资者。**不是让他们跑脚本,而是让他们 role-play 这些投资者做判断**:
**Agent 1 · 价值 + 成长派**(巴菲特/格雷厄姆/费雪/芒格/邓普顿/卡拉曼/林奇/欧奈尔/蒂尔/木头姐 · 10 人)
```
你要扮演 10 位投资大佬,逐一对 {stock_name} ({ticker}) 给出判断。
公司数据摘要:
{raw_data 的关键数据:价格/PE/ROE/行业/护城河/FCF/增速/估值分位...}
规则引擎参考分(仅供参考,你可以覆盖):
{每人的 rule_score + pass_rules + fail_rules}
真实世界信息:
{investor_knowledge 里的持仓/行业亲和度}
要求:
1. 对每个人,先想"如果我是他,看到这些数据,我会怎么想?"
2. 巴菲特看苹果 → 他实际持有,这比任何规则都重要
3. 格雷厄姆看科技股 → PE > 15 他就不买,但要解释 WHY,不是只说数字
4. 木头姐看量子 → 她会兴奋,看传统制造 → 她会说"不在我们平台里"
5. 每人输出: {investor_id, signal, score, headline(引用数字), reasoning(2-3句)}
```
**Agent 2 · 宏观 + 技术派**(索罗斯/达里奥/马克斯/德鲁肯米勒/罗伯逊 + 利弗莫尔/米内尔维尼/达瓦斯/江恩 · 9 人)
```
宏观派关心:利率周期/汇率/地缘/大宗商品 对这只票的影响
技术派关心:Stage/均线排列/MACD/成交量/距高点距离
数据:{macro_dim + kline_dim 摘要}
```
**Agent 3 · 中国价投 + 量化**(段永平/张坤/朱少醒/谢治宇/冯柳/邓晓峰 + 西蒙斯/索普/肖 · 9 人)
```
中国价投关心:好生意+好价格+好管理,长期持有
量化关心:因子暴露(动量/价值/质量/波动率)
数据:{financials + valuation + moat 摘要}
真实持仓:{段永平持有苹果/茅台/腾讯,张坤重仓白酒...}
```
**Agent 4 · 游资组**(23 人 — 只有 A 股才需要 spawn)
```
如果这只票不是 A 股 → 直接输出 23 人全部 "skip: 不看{market}市场"
如果是 A 股:
- 市值是否在各人射程内?(赵老哥 > 20 亿、章盟主 > 200 亿...)
- 龙虎榜数据:{lhb_dim}
- 最近涨停板:{kline 最近连板情况}
- 板块热度:{sentiment}
- 每人风格不同:赵老哥打板/章盟主趋势/炒股养家情绪/佛山无影脚快进快出
```
### Step 3.3 · 合并 Sub-Agent 结果
4 个 agent 返回后,你逐一把他们的 `{signal, score, headline, reasoning}` 覆盖到 `panel.json` 对应的投资者上。
**如果 sub-agent 给的分和规则引擎差 > 30 分**,在 `panel_insights` 里标记为"分歧点"——这本身是有价值的信息(说明量化指标和主观判断不一致)。
### Step 3.4 · 整体审查
合并后检查:
1. **Great Divide 选角**:最高分的 bull 和最低分的 bear 各是谁?他们的 headline 有没有说服力?
2. **派系一致性**:价值派全看空但技术派全看多 → 这是结构性分歧,写进 synthesis
3. **异常值**:有没有谁的分数明显不合理?(比如巴菲特给苹果 0 分 — 这在新架构下不应该发生了)
4. **Skip 统计**:多少人 skip 了?如果分析美股,23 个游资全 skip 是正常的
将观察写进 `synthesis.json` 的 `panel_insights`。
---
### Task 4 · 综合研判 + 叙事合成 (**🧠 你主导**)
这是整个流程里最依赖你判断的 Task。脚本只给你原材料,最终叙事**必须你写**。
### 🧠 你必须完成的 5 件事
**4.1 构建 Great Divide(多空大分歧)**
找出最有说服力的多方和最有说服力的空方:
- 从 panel 里选 bull 得分最高 + bear 得分最低的两人
- 读他们的 `pass_rules` 和 `fail_rules`
- 让他们"辩论" 3 轮(每轮 2 句话),**引用具体数字**
**4.2 写 3 条核心结论**
用 "但是" 结构,不要和稀泥:
- ✅ "ROE 连续 6 年盈利但从未破 15%,典型的长期平庸。" — 有定论
- ❌ "ROE 有起伏,需要观察。" — 废话
**4.3 估值三角验证**
- DCF 说什么?(dim 20)
- Comps 说什么?
- LBO 说什么?
- 三者**冲突时**,写出冲突并给出你的解读
**4.4 催化剂 + 风险排序**
- 从 dim 21 `catalyst_calendar` 取未来 60 天高影响事件
- 按概率 × 影响度排序 Top 3 催化剂
- 再挑 Top 3 风险(来自 dim 22 IC Memo 的 risks_mitigants)
**4.5 四派系买入区间**
给出 4 个有说服力的价位:
- **价值派**:DCF 内在价 × 0.85 (要 15% 安全边际)
- **成长派**:3 年 EPS × 中位数 PE
- **技术派**:60 日均线附近 或 Stage 2 起涨点
- **游资派**:龙虎榜集中区间
每个价位**必须附一句解释**。
### 写入(v2.2 闭环机制)
以上 5 件事全部写入 **`.cache/{ticker}/agent_analysis.json`**(不是直接写 synthesis.json!)。
stage2() 的 `generate_synthesis()` 会自动读取 agent_analysis.json 并合并:
- `dim_commentary` → 替换脚本占位符
- `panel_insights` → 写入 synthesis
- `great_divide_override` → 替换脚本生成的辩论轮次和金句
- `narrative_override.core_conclusion` → 替换脚本结论
- `narrative_override.risks` → 替换脚本风险
- `narrative_override.buy_zones` → 替换脚本买入区间
- `agent_reviewed: true` → 标记为 agent 已审查
**如果你直接写 synthesis.json,stage2() 会覆盖它。** 必须写 agent_analysis.json,stage2 会合并。
---
### Task 5 · 报告组装 (🤖 脚本 + **🧠 你的金句**)
**脚本部分**:
```bash
python scripts/assemble_report.py {ticker}
python scripts/inline_assets.py {ticker} # 生成自包含 HTML
python scripts/render_share_card.py {ticker} # 朋友圈 PNG
python scripts/render_war_report.py {ticker} # 战报 PNG
```
### 🧠 你的金句审查
在调 assemble_report 之前,**检查一遍** `synthesis.json` 中这 5 个字段:
| 字段 | 检查点 |
|---|---|
| `great_divide.punchline` | 是不是一句能传播的话?有冲突感吗?引用数字了吗? |
| `dashboard.core_conclusion` | 1-2 句结论,必须有定论 |
| `debate.rounds[*].bull_say / bear_say` | 每轮必须引用具体数字 |
| `buy_zones.*.rationale` | 每个价位必须给出计算逻辑(不能只写"基于技术面") |
| `risks[*]` | 风险必须具体到数字 / 事件 |
任何一个字段没达标,**直接重写**后再调脚本。
### 完成验证
生成的 HTML 报告打开必须满足:
- 无 console error
- 22 维深度卡全部出现(包含新增的 dim 20/21/22)
- 65 评委聊天室 + 审判席都渲染
- Great Divide punchline 不为空
- 杀猪盘等级显示
- 文件大小 > 400 KB(低于说明有大段缺失)
---
## 🖥️ Codex / 远程环境适配
**如果你在 Codex / Docker / SSH 等无 GUI 环境中运行**,使用 `run.py` 根入口:
```bash
# 在仓库根目录
python run.py <股票代码> # 自动检测环境,无浏览器时给路径
python run.py <股票代码> --remote # 完成后启动 Cloudflare Tunnel,生成公网链接
python run.py <股票代码> --remote --install-cloudflared # 允许缺失 cloudflared 时自动安装
python run.py <股票代码> --no-browser # 强制不打开浏览器
```
**`--remote` 模式的工作流**:
1. 正常跑完 6 个 Task,生成 HTML 报告
2. 自动启动本地 HTTP 服务器(端口 8976)
3. 调用 `cloudflared tunnel` 映射到 `https://xxx.trycloudflare.com`
4. 输出公网链接 — 用户手机扫码 / 发微信就能看报告
5. Ctrl+C 停止服务
安全默认值:如果本机没有 `cloudflared`,`--remote` 只提示安装方式,不会自动执行 `brew install` / `sudo mv`。只有用户显式传 `--install-cloudflared` 时才允许自动安装。
**Task 0 可选步骤:询问用户环境**
在开始分析之前,你可以先问用户:
> "你现在在电脑前吗?如果不在,我可以生成一个公网链接方便手机查看。"
如果用户说不在电脑前 → 加 `--remote` 参数。
### Codex / 国产模型 自适配(v2.6 论坛 bug 修复)
非 Claude 平台跑 UZI-Skill 时常见问题已被代码层修复,但 agent 也要主动适配:
| 论坛报告问题 | v2.6 代码层做了什么 | agent 还要做什么 |
|---|---|---|
| `KeyError: 'skip'` | preview_with_mock.py 加 'skip' key + .get() 兜底 | 无 |
| 失败卡死整条 pipeline | as_completed/result 加 90s timeout,单 fetcher 超时不影响其他 | 不要绕过 timeout 重试 |
| 中断不能续跑 | stage1 默认 `--resume`,每 3 个 fetcher 增量保存 raw_data.json | 不要手动 `--no-resume` 除非真要重抓 |
| Python 3.9 语法报错 | 所有新文件加 `from __future__ import annotations` | 无 |
| mini_racer V8 thread crash | 给 fetch_industry/capital_flow/valuation 加共享锁 | 无 |
| share/war report 渲染失败 | render_*.py 加 main() alias | 无 |
| 非 Claude agent_analysis 错乱 | stage2 调用 `lib.agent_analysis_validator.validate()` 写 `_agent_analysis_errors.json` | 跑完看 console 是否有 🔴 schema error,按提示修 |
| Top bull/bear 排序错乱 | 排除 score=0 异常,按 score 排(不再先按 signal 分组) | 检查 panel.json 数据合理性 |
| 编造事实 (药明康德↔Apple) | HARD-GATE-FACTCHECK 强制 cite raw_data | **agent 写每条结论都要能在 raw_data 找出处** |
**Codex 启动时检测**:
```bash
echo "${CODEX:-${OPENAI_API_KEY:+codex_via_openai}}"
```
**Codex 推荐设置**:
- `MX_APIKEY=...` 必设(push2 在境外更不稳)
- `--remote` 默认开(生成公网链接,无需 GUI)
- `--no-resume` 别加(断网了能续)
---
## 🎛️ 模式选择
| 触发 | 行为 |
|---|---|
| 默认 | 完整 6 Task |
| `/quick-scan` | 只跑 dim 0/1/2/10/18 + Top 10 投资者,跳过 dim 21/22 |
| `/panel-only` | 跳过 Task 2, 只输出 65 评委 + synthesis |
| `/scan-trap` | 只跑 dim 18 (杀猪盘),不调评审团 |
| `/dcf` | 只跑 DCF 估值单独输出 |
| `/comps` | 只跑同行对标 |
| `/initiate` | 完整 6 Task + 强制生成机构首次覆盖章节 |
| `/ic-memo` | 完整 6 Task + 强制生成 IC Memo 8 章节 |
| `/catalysts` | 完整 Task + 重点展示催化剂日历 |
| `/thesis` | 只跑 thesis_tracker 单独输出 |
| `/screen` | 跑 5 套量化筛选 |
| `/dd` | 跑 DD 清单 |
### 全球同行执行规则
`4_peers` 默认同时保留本地同行与全球同行。全球链路按以下顺序执行:
1. 用目标公司的 Yahoo 细分行业发现全球候选。
2. 按发行人去重,排除目标公司的海外二次上市证券。
3. 只补全相关度最高的 8 家年度财务,单家公司失败不重试整条流程。
4. 原币字段保持不变,金额类比较只读取汇率标准化后的 `*_base` 字段。
5. 有效同行少于 3 家时,不生成全球分位或估值结论。
6. Agent 引用全球同行时必须同时写公司、报告期、币种和来源;不得把缺失值写成 0。
支持 `7203.T`、`005930.KS`、`2330.TW`、`D05.SI`、`RELIANCE.NS`、
`SHOP.TO`、`BHP.AX`、`SHEL.L`、`ASML.AS` 等交易所代码。可用
`UZI_DISABLE_GLOBAL_PEERS=1` 关闭,或用 `UZI_GLOBAL_PEER_LIMIT=3..12` 调整补全数量。
## 📁 数据契约 & 文件路径
| 文件 | 谁写 | 谁读 | 闭环角色 |
|---|---|---|---|
| `.cache/{ticker}/raw_data.json` | Task 1/1.5 脚本 | Task 2-5 + 你 | 数据源 |
| `.cache/{ticker}/dimensions.json` | Task 2 脚本 | Task 4-5 | 评分 |
| `.cache/{ticker}/panel.json` | Task 3 规则引擎 → **你覆盖** | stage2 | 骨架→真实判断 |
| **`.cache/{ticker}/agent_analysis.json`** | **🧠 你写** | **stage2 自动合并** | **闭环关键** |
| `.cache/{ticker}/synthesis.json` | stage2 (合并 agent_analysis) | Task 5 | 最终研判 |
| `reports/{ticker}_{date}/full-report.html` | Task 5 脚本 | 用户 | 报告 |
| `reports/{ticker}_{date}/full-report-standalone.html` | inline_assets.py | 用户分享 | 独立报告 |
| `reports/{ticker}_{date}/share-card.png` | render_share_card | 朋友圈 | 分享卡 |
| `reports/{ticker}_{date}/war-report.png` | render_war_report | 战报 | 战报 |
| `reports/{ticker}_{date}/one-liner.txt` | assemble 副产 | 快速摘要 | 一句话 |
> ⚠️ **agent_analysis.json 是 v2.2 新增的闭环文件。** stage2() 会自动读取并合并到 synthesis 中。如果你不写这个文件,stage2 退化为纯脚本模式(会打印警告)。
详细 schema 见 `assets/data-contracts.md`。
## 🔧 工具箱速查
### 估值建模
- `lib.fin_models.compute_dcf(features, assumptions)` — DCF + WACC + 5×5 敏感性
- `lib.fin_models.build_comps_table(target, peers)` — 同行对标
- `lib.fin_models.project_three_stmt(features, assumptions)` — 5 年 IS/BS/CF
- `lib.fin_models.quick_lbo(features, ...)` — PE 买方视角 IRR 测试
- `lib.fin_models.accretion_dilution(acquirer, target, ...)` — 并购增厚/摊薄
### 研究工作流
- `lib.research_workflow.build_initiating_coverage(...)` — 机构首次覆盖
- `lib.research_workflow.build_earnings_analysis(...)` — beat/miss 解读
- `lib.research_workflow.build_catalyst_calendar(...)` — 催化剂日历
- `lib.research_workflow.build_thesis_tracker(...)` — 投资逻辑追踪
- `lib.research_workflow.build_morning_note(...)` — 晨报
- `lib.research_workflow.run_idea_screen(features, style)` — 5 套量化筛选 (value/growth/quality/gulp/short)
- `lib.research_workflow.build_sector_overview(...)` — 行业综述
### 深度决策
- `lib.deep_analysis_methods.build_ic_memo(...)` — 投委会备忘录 8 章
- `lib.deep_analysis_methods.build_unit_economics(...)` — LTV/CAC 或毛利拆解
- `lib.deep_analysis_methods.build_value_creation_plan(...)` — EBITDA 桥
- `lib.deep_analysis_methods.build_dd_checklist(...)` — 5 工作流 21 项 DD
- `lib.deep_analysis_methods.build_competitive_analysis(...)` — Porter 5 Forces + BCG
- `lib.deep_analysis_methods.build_portfolio_rebalance(...)` — 组合再平衡
### 量化评委 / 规则引擎
- `lib.stock_features.extract_features(raw, dims)` — 108 标准化特征
- `lib.investor_criteria.INVESTOR_RULES` — 65 人 236 条规则
- `lib.investor_evaluator.evaluate(investor_id, features)` — 单人裁决
- `lib.investor_evaluator.evaluate_all(features)` — 65 人批量
- `lib.investor_evaluator.panel_summary(results)` — panel 汇总
### 数据质量
- `lib.data_integrity.validate(raw)` — 100% 覆盖度校验器
## 📚 详细参考文档
- `references/task1-data-collection.md` — 22 维 fetcher 清单 + 并行策略
- `references/task1.5-institutional-modeling.md` — **DCF/Comps/LBO 默认参数与 A 股适配**(重要!)
- `references/task2-dimension-scoring.md` — 打分规则
- `references/task3-investor-panel.md` — 65 评委规则
- `references/task4-synthesis.md` — 叙事合成规范
- `references/task5-report-assembly.md` — 报告组装
- `references/fin-methods/README.md` — 22 种机构方法论索引
- `assets/data-contracts.md` — 所有 JSON schema
- `assets/quality-checklist.md` — 完成前的 checklist
## ✅ 完成定义
- **6 个 JSON 产物全部落地**(raw_data + dimensions + panel + agent_analysis + synthesis + report)
- `raw_data.json` 完整性覆盖 ≥ 90%
- **`agent_analysis.json` 必须存在且 `agent_reviewed: true`**
- `dim_commentary` 至少覆盖 15/22 维度(在 agent_analysis.json 中)
- `synthesis.json` 中 punchline / core_conclusion / debate.rounds / buy_zones / risks 都来自 agent 覆盖(通过 agent_analysis.json 合并)
- HTML 报告打开无 console error
- 金句里包含具体数字
- 杀猪盘等级始终显示
---
**现在开始**:从第 0 步识别股票开始。记住 — **你是分析师,不是脚本运行器。**
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!