From be3dae3845b0bf46da451a179954cbf1a49e78c9 Mon Sep 17 00:00:00 2001 From: dsa343 Date: Sun, 8 Mar 2026 12:34:45 +0800 Subject: [PATCH] =?UTF-8?q?feat0308=20=E6=96=B0=E5=A2=9Ecompyny-deep?= =?UTF-8?q?=E6=8A=80=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- company-deep/SKILL.md | 93 ++++++++ company-deep/requirements.txt | 1 + .../__pycache__/db_config.cpython-310.pyc | Bin 0 -> 623 bytes company-deep/scripts/db_config.py | 12 ++ company-deep/scripts/query_company.py | 204 ++++++++++++++++++ 5 files changed, 310 insertions(+) create mode 100644 company-deep/SKILL.md create mode 100644 company-deep/requirements.txt create mode 100644 company-deep/scripts/__pycache__/db_config.cpython-310.pyc create mode 100644 company-deep/scripts/db_config.py create mode 100644 company-deep/scripts/query_company.py diff --git a/company-deep/SKILL.md b/company-deep/SKILL.md new file mode 100644 index 0000000..68fce28 --- /dev/null +++ b/company-deep/SKILL.md @@ -0,0 +1,93 @@ +--- +name: company-deep +description: 查询公司个股深度研报数据。当用户询问特定上市公司的画像、股权、管理层、赛道、业务线、财务、Alpha指标、竞争对标、估值、投资论点、主营拆解、业绩预测时使用。支持按股票代码或公司名称查询原始Markdown(Part)。关键词:公司分析、个股研报、股票分析、估值、company analysis。 +--- + +# 公司个股深度研报查询 (Company Deep Analysis) + +连接 MySQL 数据库,查询公司个股深度研报数据。 +每份报告包含 12 个 Part 深度分析原文 + 3 个附录,总计约 17-20 万字/公司。 + +## 数据架构 + +### 核心数据源:Part 原文(`report_raw_parts` 表) + +每个公司包含最多 16 个段落(0=meta, 1-12=Part, 13-15=附录): + +| Part | 主题 | 核心内容 | 典型字数 | +|------|------|---------|---------| +| 0 (meta) | 目录 + Executive Summary | YAML 元数据、目录索引、报告概览表、Part 生成明细 | ~2K | +| 1 | 公司画像与定位 | 基本面速览、业务结构全景、行业定位图谱、发展历程、可比公司对照 | ~3-11K | +| 2 | 股权架构与公司治理 | 股权结构、股东分析、治理评估、机构持仓、激励计划 | ~10K | +| 3 | 管理层与核心团队 | 高管画像、稳定性、持股激励、技术团队、能力评估 | ~12K | +| 4 | 赛道分析与演变 | 赛道定义与规模、增速驱动、竞争格局、卡位分析、迁移路径 | ~14K | +| 5 | 业务线深度拆解 | 业务全景、各线详解、BCG矩阵、优劣势、组合评估 | ~19K | +| 6 | 财务深度分析 | 五年趋势、杜邦分析、现金流、资产质量、盈利能力、风险预警 | ~15-49K | +| 7 | 公司Alpha指标 | Alpha定义、核心指标体系、详解、排名、趋势、可持续性评估 | ~15-29K | +| 8 | 竞争对标分析 | 可比公司选取、财务对标、估值对标、业务结构对比、竞争优劣 | ~15K | +| 9 | 估值与目标价 | 历史估值、DCF模型、可比公司法、PEG法、分部估值、投资评级 | ~13-31K | +| 10 | 投资论点与风险 | Bull/Bear Case、情景分析、风险清单、催化剂、时机判断 | ~6K | +| 11 | 主营业务深度分析 | 10年营收穿透式拆解、销量x单价、驱动因素分解、Survival Metrics关联 | ~13-21K | +| 12 | 5年业绩预测 | 预测假设、财务预测(利润表/BS/CF)、经营数据、敏感性、情景分析 | ~21-31K | +| 13 | 附录A: 生成摘要 | 生成耗时、各Part字符数统计 | ~1K | +| 14 | 附录B: V3行业报告关联 | V3行业报告与V4公司报告的互补关系 | ~1K | +| 15 | 附录C: 数据来源索引 | 数据来源机构、获取方式、置信度 | ~1K | + +## 命令接口 + +脚本路径: `~/.claude/skills/company-deep/scripts/query_company.py` + +### 1. 查找公司 +```bash +python ~/.claude/skills/company-deep/scripts/query_company.py lookup "歌尔" +python ~/.claude/skills/company-deep/scripts/query_company.py lookup "002241" +``` + +### 2. 列出所有公司 +```bash +python ~/.claude/skills/company-deep/scripts/query_company.py list +``` + +### 3. Part 目录(先看有哪些 Part) +```bash +python ~/.claude/skills/company-deep/scripts/query_company.py parts 002241 +``` + +### 4. Part 原文(深度分析,首选) +```bash +python ~/.claude/skills/company-deep/scripts/query_company.py part 002241 1 # Part 1 公司画像 +python ~/.claude/skills/company-deep/scripts/query_company.py part 002241 6,9 # 多个 Part +python ~/.claude/skills/company-deep/scripts/query_company.py part 002241 all # 全部(慎用,~20万字) +``` + +## 回答策略 + +1. **先 lookup 确认股票代码**(除非用户已给出代码) +2. **先 parts 看目录**:了解该公司有哪些 Part 可查 +3. **按需查 part**:根据问题类型精准选择 1-2 个 Part +4. **不要一次查 all**:除非用户明确要求全量 + +### 场景速查表 + +| 用户问题类型 | 推荐 Part | 关键内容 | +|-------------|----------|---------| +| "XXX 是什么公司" | part 1 | 基本面、业务结构、行业定位 | +| "XXX 股权/大股东" | part 2 | 股权结构、实控人、机构持仓 | +| "XXX 管理层怎么样" | part 3 | 高管画像、稳定性、能力评估 | +| "XXX 所在赛道/行业" | part 4 | 赛道规模、增速、竞争格局 | +| "XXX 有哪些业务" | part 5 | 业务线拆解、BCG矩阵 | +| "XXX 财务怎么样" | part 6 | 五年趋势、杜邦分析、现金流 | +| "XXX 核心竞争力" | part 7 | Alpha指标体系、可持续性 | +| "XXX 和同行对比" | part 8 | 可比公司、财务/估值对标 | +| "XXX 值多少钱" | part 9 | DCF、可比公司法、目标价 | +| "XXX 值不值得买" | part 10 | Bull/Bear Case、风险、催化剂 | +| "XXX 主营收入结构" | part 11 | 10年营收拆解、量价分析 | +| "XXX 未来业绩预测" | part 12 | 5年财务预测、敏感性分析 | +| 综合分析 | part 0 + 相关 | 先看 Executive Summary | + +## 约束 + +- 数据库: MySQL @ 222.128.1.157:33060(需可达该地址) +- 连接信息可通过环境变量 `COMPANY_DEEP_DB_*` 覆盖(见 `scripts/db_config.py`) +- 数据来源为 V4 公司深度研报(Claude/Gemini 生成),约 17-20 万字/公司 +- Part 原文为 LLM 生成的 Markdown,框架跨公司高度一致(95%+),内容按公司定制化 diff --git a/company-deep/requirements.txt b/company-deep/requirements.txt new file mode 100644 index 0000000..9e9f6b1 --- /dev/null +++ b/company-deep/requirements.txt @@ -0,0 +1 @@ +pymysql>=1.0.0 diff --git a/company-deep/scripts/__pycache__/db_config.cpython-310.pyc b/company-deep/scripts/__pycache__/db_config.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..913e9d9a6717446090903f72e0f3811fe9578276 GIT binary patch literal 623 zcmd1j<>g`k0$;^7nI9P$7#@Q-$bbXLaRB1t2q2Nd5XF$fn8K997{!>%n8mb!IfXfe zWg$~43zWy2!nTm9879Y`!U2?nsN+oGg0s0(cos6H@TTz1VT)o-VG3r@KYL5;uP=U9~@G}Yh+}k zXJ}-hXQ*drYL2NWz&|J?iq+WIz{~(sGBnsVD2lVVG%qVNwLCQwQ$c`ZaBvk5T!BMb z8m1aQM_<<{9;j#HL7s_XFD*&4$W1cQWQ$_S$S*F5VkyWkD!Ii{TAW%G#Zi!0TwI=C zloG{}l30?Mlvtd4i#<6bv8Xt;M3e0ndwhIKesX;LEvEe9TkNTMWtm0!dAFF;Q%i0! zXXcgM;spBK+27C2(|sjF5h$j?#8-bH%h@U>6lg [args...] + +子命令: + lookup 按关键词或股票代码查找公司 + list 列出所有公司 + parts 列出该公司所有 Part 目录(编号+标题+字数) + part 获取 Part 原始 Markdown +""" +from __future__ import annotations + +import json +import sys +import os + +sys.stdout.reconfigure(encoding="utf-8") +sys.stderr.reconfigure(encoding="utf-8") + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from db_config import DB_CONFIG + +try: + import pymysql +except ImportError: + import subprocess + print("pymysql 未安装,正在自动安装...", file=sys.stderr) + subprocess.check_call([sys.executable, "-m", "pip", "install", "pymysql", "-q"]) + import pymysql + + +def _get_conn(): + return pymysql.connect(**DB_CONFIG, cursorclass=pymysql.cursors.DictCursor) + + +def cmd_lookup(keyword: str): + """按关键词查找公司,模糊匹配 company_name 和 stock_code。""" + conn = _get_conn() + try: + with conn.cursor() as cur: + like = f"%{keyword}%" + cur.execute( + """SELECT stock_code, company_name, report_version, + total_parts, success_parts, total_characters, + generated_at + FROM company_reports + WHERE company_name LIKE %s OR stock_code LIKE %s + ORDER BY stock_code""", + (like, like), + ) + rows = cur.fetchall() + finally: + conn.close() + + if not rows: + print(f"未找到匹配「{keyword}」的公司") + return + + print(f"找到 {len(rows)} 家公司:\n") + for r in rows: + parts_info = f"{r['success_parts']}/{r['total_parts']} Part" + chars = f"{r['total_characters']:,}字" if r["total_characters"] else "" + print(f" {r['stock_code']} {r['company_name']} {r['report_version']} {parts_info} {chars}") + + +def cmd_list(): + """列出所有公司。""" + conn = _get_conn() + try: + with conn.cursor() as cur: + cur.execute( + """SELECT stock_code, company_name, total_parts, success_parts, + total_characters, generated_at + FROM company_reports ORDER BY stock_code""" + ) + rows = cur.fetchall() + finally: + conn.close() + + if not rows: + print("暂无公司数据") + return + + print(f"共 {len(rows)} 家公司:\n") + for r in rows: + parts_info = f"{r['success_parts']}/{r['total_parts']}" + chars = f"{r['total_characters']:,}字" if r["total_characters"] else "" + print(f" {r['stock_code']} {r['company_name']} Parts={parts_info} {chars}") + + +def cmd_parts(stock_code: str): + """列出某公司所有 Part 的编号、标题、字数。""" + conn = _get_conn() + try: + with conn.cursor() as cur: + cur.execute( + """SELECT rrp.part_num, rrp.title, rrp.char_count + FROM report_raw_parts rrp + JOIN company_reports cr ON cr.id = rrp.report_id + WHERE cr.stock_code = %s + ORDER BY rrp.part_num""", + (stock_code,), + ) + rows = cur.fetchall() + finally: + conn.close() + + if not rows: + print(f"未找到公司: {stock_code}") + return + + print(f"公司 {stock_code} 的 Part 列表:\n") + print(f" {'Part':>6s} {'标题':<30s} {'字数':>8s}") + print(f" {'-'*6} {'-'*30} {'-'*8}") + for r in rows: + pn = r["part_num"] + label = f"Part {pn}" if pn > 0 else "meta" + title = r["title"] or "" + print(f" {label:>6s} {title:<30s} {r['char_count']:>8,d}") + + +def cmd_part(stock_code: str, part_nums: str): + """获取 Part 原始 Markdown 文本。""" + conn = _get_conn() + try: + with conn.cursor() as cur: + if part_nums == "all": + cur.execute( + """SELECT rrp.part_num, rrp.title, rrp.content, rrp.char_count + FROM report_raw_parts rrp + JOIN company_reports cr ON cr.id = rrp.report_id + WHERE cr.stock_code = %s + ORDER BY rrp.part_num""", + (stock_code,), + ) + else: + nums = [int(x.strip()) for x in part_nums.split(",")] + placeholders = ",".join(["%s"] * len(nums)) + cur.execute( + f"""SELECT rrp.part_num, rrp.title, rrp.content, rrp.char_count + FROM report_raw_parts rrp + JOIN company_reports cr ON cr.id = rrp.report_id + WHERE cr.stock_code = %s AND rrp.part_num IN ({placeholders}) + ORDER BY rrp.part_num""", + [stock_code] + nums, + ) + rows = cur.fetchall() + finally: + conn.close() + + if not rows: + print(f"未找到公司 {stock_code} 的 Part 数据") + return + + for r in rows: + pn = r["part_num"] + label = f"Part {pn}: {r['title']}" if r["title"] else f"Part {pn}" + if pn == 0: + label = "meta (目录+Executive Summary)" + print(f"{'=' * 60}") + print(f" {label} ({r['char_count']:,} 字)") + print(f"{'=' * 60}") + print(r["content"]) + print() + + +def main(): + if len(sys.argv) < 2: + print(__doc__) + sys.exit(0) + + cmd = sys.argv[1] + + if cmd == "lookup": + if len(sys.argv) < 3: + print("用法: query_company.py lookup ") + sys.exit(1) + cmd_lookup(sys.argv[2]) + + elif cmd == "list": + cmd_list() + + elif cmd == "parts": + if len(sys.argv) < 3: + print("用法: query_company.py parts ") + sys.exit(1) + cmd_parts(sys.argv[2]) + + elif cmd == "part": + if len(sys.argv) < 4: + print("用法: query_company.py part <0-15|all>") + sys.exit(1) + cmd_part(sys.argv[2], sys.argv[3]) + + else: + print(f"未知命令: {cmd}") + print(__doc__) + sys.exit(1) + + +if __name__ == "__main__": + main()