feat0308 新增compyny-deep技能
This commit is contained in:
93
company-deep/SKILL.md
Normal file
93
company-deep/SKILL.md
Normal file
@@ -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%+),内容按公司定制化
|
||||
1
company-deep/requirements.txt
Normal file
1
company-deep/requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
pymysql>=1.0.0
|
||||
BIN
company-deep/scripts/__pycache__/db_config.cpython-310.pyc
Normal file
BIN
company-deep/scripts/__pycache__/db_config.cpython-310.pyc
Normal file
Binary file not shown.
12
company-deep/scripts/db_config.py
Normal file
12
company-deep/scripts/db_config.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""数据库连接配置 -- 供 company-deep Skill 查询脚本使用。"""
|
||||
import os
|
||||
|
||||
DB_CONFIG = {
|
||||
"host": os.environ.get("COMPANY_DEEP_DB_HOST", "222.128.1.157"),
|
||||
"port": int(os.environ.get("COMPANY_DEEP_DB_PORT", "33060")),
|
||||
"user": os.environ.get("COMPANY_DEEP_DB_USER", "sunjiewei"),
|
||||
"password": os.environ.get("COMPANY_DEEP_DB_PASS", "sunjiewei@vf"),
|
||||
"database": os.environ.get("COMPANY_DEEP_DB_NAME", "company_deep"),
|
||||
"charset": "utf8mb4",
|
||||
}
|
||||
204
company-deep/scripts/query_company.py
Normal file
204
company-deep/scripts/query_company.py
Normal file
@@ -0,0 +1,204 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""公司深度研报查询脚本 -- 供 Claude Skill 使用。
|
||||
|
||||
用法:
|
||||
python query_company.py <command> [args...]
|
||||
|
||||
子命令:
|
||||
lookup <keyword> 按关键词或股票代码查找公司
|
||||
list 列出所有公司
|
||||
parts <stock_code> 列出该公司所有 Part 目录(编号+标题+字数)
|
||||
part <stock_code> <nums|all> 获取 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 <keyword>")
|
||||
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 <stock_code>")
|
||||
sys.exit(1)
|
||||
cmd_parts(sys.argv[2])
|
||||
|
||||
elif cmd == "part":
|
||||
if len(sys.argv) < 4:
|
||||
print("用法: query_company.py part <stock_code> <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()
|
||||
Reference in New Issue
Block a user