Skip to content

Latest commit

 

History

History
401 lines (301 loc) · 19.4 KB

File metadata and controls

401 lines (301 loc) · 19.4 KB

UZI-Skill · Agent 指令

本文件供 Codex / Claude Code / Cursor / Devin / OpenCode / Gemini 等 AI agent 自动读取。


🗺️ Repository Layout & Entrypoints (v3.2.0)

绝对路径约定 —— 不要自己瞎猜 · 避免 "scripts/run.py 缺失" 这类误解:

UZI-Skill/                                  # ← 你 cwd 应该是这里
├── run.py                                  # ✅ 用户入口 · CLI 直跑 (python run.py <ticker>)
├── AGENTS.md / CLAUDE.md / GEMINI.md       # agent 指令
├── .claude-plugin/plugin.json              # Claude Code manifest
├── .cursor-plugin/plugin.json              # Cursor manifest
├── gemini-extension.json                   # Gemini manifest
├── package.json                            # OpenClaw / npm
└── skills/deep-analysis/
    ├── SKILL.md                            # skill 描述
    ├── assets/                             # HTML 模板 / avatars / icons
    └── scripts/                            # ← 所有 Python 业务代码在这里
        ├── run_real_test.py                # legacy stage1/stage2 入口 (v3.1 瘦身后 735 行)
        ├── assemble_report.py              # HTML shell 组装 (v3.2 瘦身后 587 行)
        ├── fetch_*.py (22 个)              # 数据采集 · 也是独立 CLI (python fetch_basic.py <ticker>)
        ├── compute_*.py                    # 机构建模 (DCF / BCG / Porter)
        ├── tests/                          # 332 pytest
        ├── .cache/<ticker>/                # 跑过的股票缓存
        ├── reports/<ticker>_<date>/        # 生成的 HTML 报告
        └── lib/
            ├── pipeline/                   # 🆕 v3.0 管道式架构(默认路径)
            │   ├── run.py                  # run_pipeline 编排入口
            │   ├── collect.py              # 并发 collector (22 fetcher adapter)
            │   ├── score.py                # scoring 段 (调 rrt 纯函数)
            │   ├── synthesize.py           # stage2 薄 wrapper
            │   ├── score_fns.py            # 🆕 v3.1 · 1228 行纯函数
            │   ├── preflight_helpers.py    # 🆕 v3.1 · 网络/ticker preflight
            │   ├── fetchers/registry.py    # 22 adapter 工厂
            │   └── renderer/               # 21 个 renderer stub (未完全使用)
            ├── report/                     # 🆕 v3.2 · assemble_report 拆分
            │   ├── svg_primitives.py       # 19 个 svg_* + COLOR_*
            │   ├── dim_viz.py              # 19 个 _viz_xxx + DIM_VIZ_RENDERERS
            │   ├── institutional.py        # DCF/LBO/IC memo/catalyst/competitive
            │   ├── panel_cards.py          # 66 评委 panel 渲染
            │   └── special_cards.py        # fund/insights/school_scores/debate
            └── ...(其他 lib 模块 · investor_db / network_preflight / ...)

入口 Cheat Sheet

操作 命令
用户一句话分析 python run.py <ticker> (repo root · 走 v3.0 pipeline)
强制老路径 (保险) UZI_LEGACY=1 python run.py <ticker>
只跑单个 fetcher cd skills/deep-analysis/scripts && python fetch_basic.py <ticker>
跑全量 pytest cd skills/deep-analysis/scripts && pytest tests/ -q
Python 环境 任意装了 akshare/pytest 的 Python 3.10+(macOS 系统 /usr/bin/python3 通常缺这些 · 用 pip install -r requirements.txt 装;conda / venv / pyenv 都行)

内部模块调用约定

  • Python 模块路径起点 = skills/deep-analysis/scripts/ · run_real_test.py 顶部 sys.path.insert(0, str(HERE)) 注入
  • from lib.pipeline.score import score_from_cache · 不是 from skills.deep_analysis.scripts.lib...
  • run_real_test 对外简称 rrt · pipeline 调它的纯函数 (rrt.score_dimensions → 实际来自 lib.pipeline.score_fns)

版本分水岭

版本 变化 影响 agent 的部分
v3.0.0 pipeline 默认启用 · UZI_LEGACY=1 回老路径 python run.py 默认进 pipeline
v3.1.0 rrt 瘦身 65% · 纯函数搬到 score_fns 所有 rrt.XXX 仍向后兼容 (re-export)
v3.2.0 assemble_report 瘦身 80% · 拆 5 个 lib/report/* 所有 assemble_report.XXX 仍向后兼容

黄金规则:外部 test / lib 仍可以 import run_real_test; rrt.score_dimensions(...) · 不用改。拆分对上层透明.


你是谁

你是一个股票深度分析 agent。用户给你一只股票,你要采集数据 → 亲自分析每个投资者的判断 → 生成报告

核心原则

你不是脚本运行器——你是首席分析师。 脚本只是你的工具。

66 个投资大佬的评审必须由你 role-play,不是纯跑规则引擎:

  • 巴菲特看 ROE 和护城河,但他实际持有苹果 → 这比规则更重要
  • 游资只做 A 股 → 分析美股时直接跳过
  • 木头姐看颠覆创新 → 给她白酒股她会说"不在平台里"

深浅两套路径 · 按用户意图选一条(v3.2.0)

用户一句话只说"分析 XXX"不一定等于要跑全量 agent 流程。先做判断:

用户信号 推荐路径 耗时 为什么
"快速看看"、"先扫一眼"、/quick-scan/thesis CLI 直跑 lite 30-60s 7 维核心数据 + 10 投资者,脚本直接出报告
--depth deep / 明确要求"深度分析"、"估值"、"DCF"、"首次覆盖"、/ic-memo/initiate 全量 agent 流程 5-10min 22 维 + 66 评委 role-play + agent_analysis.json
未明确 默认 medium + CLI 直跑(仍出完整报告) 2-4min v2.10.5 起 CLI 直跑 medium 也能完整出 HTML

关键(v3.9.4 起强化)--depth deep 必须是全量 agent 流程——你要介入 role-play 66 评委并写 agent_analysis.json,不能只跑 run.py --depth deep 就交差。判断规则:

  1. 用户明确要"深度 / 全面 / DCF / 首次覆盖 / IC memo" → 走路径 B
  2. 你看到 --depth deep(无论谁加的)→ 走路径 B
  3. lite / medium / 未指定 → 走路径 A(CLI 直跑,agent 不介入)

从 v2.10.4 起,run.py 直跑模式下 agent_analysis.json 缺失会降级为 warning 不阻塞 HTML。但这只适用于 lite/medium。deep 档缺 agent_analysis 意味着你没尽到 agent 职责——报告会缺 role-play 判断。

路径 A · CLI 直跑(快速 · 仅 lite/medium)

python3 run.py <ticker> --depth lite --no-browser    # 最快
python3 run.py <ticker> --depth medium --no-browser  # 默认完整度
python3 run.py <ticker> --school F --no-browser      # v3.5.0 · 只看 F 派(游资)视角

注意:路径 A 只适用于 lite/medium。--depth deep 不在此列——deep 必须走路径 B(agent 介入 role-play)。看到 deep 档时不要直接 run.py --no-browser 一把梭,先跑 stage1 采集,然后介入 role-play。

v3.5.0 --school 参数:用户可锁定单一流派 (A价值/B成长/C宏观/D技术/E中国价投/F游资/G量化/H科技领袖派/I Serenity 卡位猎手), 其他派评委自动 skip · 报告顶部渲染 SCHOOL LOCK banner · 你 role-play 时只 role-play 该派 5-8 人 · panel_insights / debate_rounds 都限于该派内部分歧。详见 SKILL.md HARD-GATE-SCHOOL-LOCK

脚本会:

  1. 跑 stage1 采集数据
  2. 自检 self-review(CLI 模式下 agent_analysis 缺失是 warning)
  3. 调 stage2 组装 HTML 报告

你只需:读最终 HTML / synthesis.json,向用户汇报核心结论。不需要 role-play 66 评委。(这是 lite/medium 档的行为。deep 档除外——见下方路径 B。)

路径 B · 全量 agent 流程(深度)

用户明确要深度分析(estimation/DCF/IC memo),按下面 Step 1-5 走:

Step 1 · 安装依赖(首次)

克隆仓库并安装依赖。仓库在 skills/deep-analysis/scripts/ 下有所有脚本。

Step 2 · 数据采集(脚本完成)

进入 skills/deep-analysis/scripts/ 目录,调用 stage1() 采集 22 维数据 + 机构建模 + 规则引擎骨架分:

cd <repo_root>/skills/deep-analysis/scripts
python -c "from run_real_test import stage1; stage1('<ticker>')"

💡 deep 档不要python run.py <ticker> --depth deep 一把跑完(那是纯规则输出)。正确的做法是先 stage1() 采集 → 你介入 role-play → 再 stage2() 出报告。

Step 3 · 你来分析(全量路径必走,不能跳过)

Do NOT proceed to report generation until you have: 1. READ the panel.json skeleton scores 2. ANALYZED each investor group from their perspective 3. UPDATED panel.json with your judgments 4. WRITTEN agent_analysis.json with dim_commentary + panel_insights + overrides 5. SET agent_reviewed: true in agent_analysis.json

⛔ Step 3.0 · Playwright 兜底前置检查(v2.13.5 必走)

Stage 1 跑完后 · 开始 role-play 之前

import json, os
from pathlib import Path

# 1. 读网络 profile · 了解能抓哪些源
net_path = Path(".cache/_global/network_profile.json")
if net_path.exists():
    net = json.loads(net_path.read_text(encoding="utf-8"))
    print(f"网络: {net['recommendation']}")  # 比如"国内通 · 境外受限"

# 2. 读自查 issues 找数据不足的维度
issues_path = Path(f".cache/{ticker}/_review_issues.json")
if issues_path.exists():
    issues = json.loads(issues_path.read_text(encoding="utf-8"))
    low_q = [
        i["dim"] for i in issues.get("issues", [])
        if i.get("category") == "data" and i.get("severity") in ("critical", "warning")
    ]

# 3. 如果 low_q 非空 · 主动强制跑一次 Playwright 兜底
if low_q:
    os.environ["UZI_PLAYWRIGHT_FORCE"] = "1"
    from lib.playwright_fallback import autofill_via_playwright
    summary = autofill_via_playwright(raw, ticker)
    # summary.succeeded > 0 → 某些维度已被 Playwright 补齐 · 继续 role-play 时这些维度有真实数据了

为什么这个 HARD-GATE:v2.13.5 之前 agent 经常看到 data.growth = "—" 就在 commentary 里写 "增速待补充",但脚本其实可以用 Playwright 从百度/东财 F10/雪球 抓到数据 · agent 没主动调就浪费了。

Playwright 也抓不到的维度 · 再用 WebSearch / mx_api / 常识补(并标注"基于公开信息推断")。

Step 3.1 你来做评委 role-play

3a. 读取 .cache/{ticker}/panel.json

看 66 人各自打了多少分,特别关注 Top 5 Bull 和 Top 5 Bear。

3b. 逐组分析 66 评委

对每组投资者,站在他们的角度思考这只票:

关注点
价值派(巴菲特/格雷厄姆/芒格) ROE 够不够?护城河深不深?有安全边际吗?
成长派(林奇/木头姐/欧奈尔) 增速够不够?赛道有颠覆性吗?PEG 合理吗?
宏观派(索罗斯/达里奥) 利率环境?行业在周期什么位置?
技术派(利弗莫尔/米内尔维尼) Stage 几?均线排列?成交量?
中国价投(段永平/张坤/冯柳) 好生意吗?管理层本分吗?有认知差吗?
游资(赵老哥/章盟主) 龙虎榜?板块热度?适合短线吗?
量化(西蒙斯) 动量/价值/质量因子打分

每个人给出:signal(bullish/bearish/neutral/skip)、score(0-100)、headline(引用具体数字)、reasoning(2-3 句话)

你可以覆盖规则引擎的机械得分——你是在模拟这个人的判断。

3c. 把分析结果更新到 panel.json

3d. 写 agent_analysis.json(闭环关键!)

写入 .cache/{ticker}/agent_analysis.json,包含:

{
  "agent_reviewed": true,
  "dim_commentary": { "0_basic": "你的定性评语", ... },
  "panel_insights": "整体评委观察",
  "great_divide_override": {
    "punchline": "一句能传播的冲突金句",
    "bull_say_rounds": ["第1轮多方说", "第2轮", "第3轮"],
    "bear_say_rounds": ["第1轮空方说", "第2轮", "第3轮"]
  },
  "narrative_override": {
    "core_conclusion": "综合结论",
    "risks": ["风险1", "风险2", ...],
    "buy_zones": { "value": {...}, "growth": {...}, "technical": {...}, "youzi": {...} }
  }
}

stage2() 会自动读取并合并。 你写的字段优先级高于脚本生成的 stub。

Step 4 · 生成报告(脚本完成)

调用 stage2() 读取你更新后的 panel.json + agent_analysis.json,生成综合研判 + HTML 报告。

Step 5 · 向用户汇报

告诉用户:

  1. 综合评分 + 定调(值得重仓 / 可以蹲 / 观望 / 谨慎 / 回避)
  2. 66 评委投票分布
  3. 你自己分析的 Top 3 看多理由 + Top 3 看空理由
  4. DCF 内在价值 vs 当前价
  5. 杀猪盘等级
  6. 报告路径(或 --remote 公网链接)

快速模式

用户说"快速分析"或"不用详细"→ 直接用 run.py 一把跑完,不做 agent 分析。快但粗糙。

远程模式

用户不在电脑前 → 用 --remote 参数,自动生成 Cloudflare 公网链接。

平台专属安装指南

平台 文档
Codex .codex/INSTALL.md
OpenCode .opencode/INSTALL.md
Cursor .cursor-plugin/plugin.json
Gemini GEMINI.md
Claude Code .claude-plugin/plugin.json

🌐 网络受限环境(重要 · v2.4 新增)

UZI-Skill 既可能在中国大陆运行,也可能在 Codex / 海外云容器里运行, 两类环境的网络瓶颈不同,agent 遇到错误时要按情况切换。

场景 A · 大陆网络 / 校园 / 公司代理

症状pip install 超时、SSL handshake 失败、pypi.org 连不上。

处理:按顺序尝试国内 pip 镜像(run.pysetup.sh 已经会自动 fallback, 但在 agent 环境你可能要手动指定):

# 清华(推荐)
pip install -r requirements.txt \
    -i https://pypi.tuna.tsinghua.edu.cn/simple \
    --trusted-host pypi.tuna.tsinghua.edu.cn

# 阿里云(兜底)
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

# 中科大
pip install -r requirements.txt -i https://pypi.mirrors.ustc.edu.cn/simple/

数据源通常都通(akshare / xueqiu / eastmoney),个别被反爬的子域(如 push2.eastmoney.com)可能 Empty reply — 设置 MX_APIKEY 启用东财 妙想官方 API 作为主数据源,见 .env.example

场景 B · Codex / 海外 agent 容器

症状pip install 很快,但跑分析时 akshare 报 timeout、 push2.eastmoney.com 不通、cninfo.com.cn DNS 失败。

处理:国内数据源从海外访问有时反被 GFW 限制。按以下顺序尝试:

  1. 启用 MX_APIKEY(最稳)— 妙想 API 走境内外都可达的 mkapi2.dfcfs.com
  2. yfinance 兜底美股/港股
  3. WebSearch + Chrome/Playwright MCP 打开以下备用入口抓 HTML:
    • 雪球:https://xueqiu.com/S/{code}(走 CDN,境外可访问)
    • 腾讯财经:https://stockapp.finance.qq.com/mstats/
    • 同花顺(F10 页):https://stockpage.10jqka.com.cn/{code}/

场景 C · pip 和数据源都不通(双失败)

agent 应该:

  1. 明确告诉用户:"当前网络环境无法访问 pypi 和东财,建议切换到中国大陆 IP 或配置 MX_APIKEY"
  2. 不要尝试用未验证的 VPN / 代理,不要绕过用户网络策略
  3. 保留 _data_gaps.json + _resolve_error.json,下次网络恢复后可以直接 stage2() 生成报告

环境侦测快速命令

agent 在不确定环境时,可先跑这几条探测:

# pypi 连通性
curl -sS --max-time 5 -o /dev/null -w "pypi: %{http_code}\n" https://pypi.org/simple/
# 国内镜像连通性
curl -sS --max-time 5 -o /dev/null -w "tuna: %{http_code}\n" https://pypi.tuna.tsinghua.edu.cn/simple/
# 东财 push2(最常被挡)
curl -sS --max-time 5 -o /dev/null -w "push2: %{http_code}\n" https://push2.eastmoney.com/api/qt/stock/get
# 东财其他域
curl -sS --max-time 5 -o /dev/null -w "quote-em: %{http_code}\n" https://quote.eastmoney.com/
curl -sS --max-time 5 -o /dev/null -w "xueqiu: %{http_code}\n" https://xueqiu.com/
# 妙想 API
curl -sS --max-time 5 -o /dev/null -w "mx: %{http_code}\n" https://mkapi2.dfcfs.com/

根据哪些通/哪些不通,决定走哪个数据链。

📚 数据源速查表(v2.5 新增)

完整源清单在 lib/data_source_registry.py(40+ 源 · 3 tier)。常见 dim 推荐路径如下, agent 选择源时按"主源 → 备源 → 浏览器源"顺序,failed 自动 fallthrough:

Dim A 股 主源 A 股 备源 A 股 浏览器源 H 股主源
0_basic xq_api (akshare) mx_api / em_quote xueqiu_f10 hk_data_sources combined (XQ + EM profile + EM valuation)
2_kline em_data + akshare baostock / tencent_qt akshare hk_hist
4_peers akshare board_industry em_data iwencai / ths_f10 hk_valuation_comparison_em (rank-only) + AASTOCKS (Playwright)
6_research em_data + cninfo hexun / stockstar xueqiu_f10 (HK 限) yicai / cls
12_capital_flow em_data 北向 + akshare yuncaijing hk_security_profile (港股通标记) + AASTOCKS Playwright
13_policy gov_cn + cninfo csrc / miit / ndrc (同 A) + cls 7x24 + wallstreetcn
15_events cninfo + em_data xq_api / cls / yicai xueqiu_f10 hkexnews + AASTOCKS Playwright
16_lhb akshare lhb + em_data yuncaijing (HK 无 LHB 概念,看南北向替代)
17_sentiment xq_api / ddgs wallstreetcn xueqiu_f10 futu (Playwright) / xq_api

用法(在 sub-agent prompt 里)

from lib.data_source_registry import http_sources_for, playwright_sources_for, by_dim

# Tier-1 HTTP 源,按 health 排序
sources = http_sources_for("4_peers", "A")
for s in sources:
    print(s.id, s.base_url, s.health, s.notes)

# 当 HTTP 全失败时,agent 启动 Playwright 用 tier-2 源:
browser_sources = playwright_sources_for("4_peers", "A")

港股增强(v2.5 新加)

  • lib/hk_data_sources.py 包装了之前未用到的 50+ akshare HK 函数
  • _fetch_basic_hk 现在能拿到 industry / PE / PB / 市值 / 排名 / 公司介绍
  • fetch_peers.py HK 分支返回 rank-in-HK-universe(具体同行 list 走 AASTOCKS Playwright)
  • fetch_capital_flow.py HK 分支返回港股通资格 + 30 日市值变化
  • fetch_events.py HK 分支抓 HKEXNews + 中文 web search 兜底

⚙️ v2.6 论坛 bug 修复速查(重要 · 影响 agent 行为)

论坛 bug 修了什么 agent 仍要做什么
失败卡死 per-fetcher 90s timeout 不要重试 timeout 维度,让 _data_gaps.json 触发恢复
中断不能续 --resume 默认开 第二次跑同股 agent 应直接调 stage2 (raw_data 已有)
非 Claude 评委对齐错位 schema validator 写 _agent_analysis_errors.json 跑完 stage2 看 console 是否有 🔴 错误,按 _agent_analysis_errors.json suggestion 改
编造事实(药明康德↔Apple) HARD-GATE-FACTCHECK 每条 commentary cite raw_data 出处,不确定的不要肯定语气
Codex 兼容差 run.py 自动 Codex 检测 + mini_racer 锁 Codex 环境必设 MX_APIKEY,不要 --no-resume
Claude plugin 不能执行 hooks.json 直调 session-start 装完跑 chmod +x hooks/session-start

注意

  • A 股:600519.SH / 002273.SZ / 贵州茅台
  • 港股:00700.HK
  • 美股:AAPL
  • 不需要 API key(但建议设置 MX_APIKEY 提高稳定性,特别是 Codex/海外环境)
  • v2.6 默认 --resume · 强制重抓加 --no-resume