ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI投研Skill实战:从取数到研报生成的全流程自动化

AI投研Skill实战:从取数到研报生成的全流程自动化 最近在复盘自己用 AI 辅助投研的工作流时有个很深的感受真正让效率翻倍的并不是某个大模型的提示词而是一套被固化成“Skill”的标准化流程。所谓 AI 投研 Skill就是把数据采集、财务指标计算、估值分析和研报草稿生成这些环节封装成一个 AI 编程助手能自动调用的工作包。你只需要输入一个股票代码它会按预设步骤取数、算指标、生成一份结构完整的投研纪要。这篇文章会完整分享这套 Skill 的设计思路、目录结构、核心代码以及实操中踩过的坑适合自己做基本面研究、但不想把时间耗在复制粘贴上的个人投资者也适合想给团队沉淀研究流程的初级研究员。如果你正在用 Claude Code、Codex 或 Cursor 这类 AI 编程工具这套方法基本开箱即用。1. 为什么需要把投研流程装进 Skill1.1 传统投研的信息处理痛点做个股基本面研究大致要经历这样几个步骤先找到公司近几年的年报和季报整理出营收、净利润、毛利率、经营现金流等关键数据再算 ROE、估值分位、自由现金流做横向纵向对比最后把结论写成一份可读的研究纪要。听起来不复杂但实际做一遍非常耗时。以我自己的经验一只票从零开始整理数据到出草稿至少需要两到三个小时其中一半时间花在“打开年报定位科目复制数据核对单位”这种机械劳动上。更大的问题是标准不统一。今天分析 A 公司用归母净利润增速明天分析 B 公司又用营业总收入增速不同时候做出来的底稿格式五花八门复盘的时候根本没法横向比较。我早先试过用对话式 AI 来解决但每次都要把“请帮我分析 XX 公司基本面重点关注盈利质量和现金流”这段背景重新输入一遍而且它给出的指标经常对不上财报口径数据来源也不明不白。用过几次之后我就意识到缺的不是生成能力而是一套能让 AI 重复执行、不偏题的流程外壳。Skill 正好补上这个缺口。1.2 Skill 和 Agent 的分工关系很多人会把 Skill 和 Agent 混在一起其实两者是不同层的东西。Agent 是一个能自主规划、调用工具的智能体它负责拆解任务、决定下一步做什么而 Skill 是给它的一套标准化能力包里面写清楚特定场景下应该执行什么步骤、调用哪些脚本、按什么模板输出。用一个生活化的类比Agent 是厨师Skill 是菜谱和预处理好的配菜包。厨师可以临场发挥但如果想稳定出品就必须有一份标准化配菜。目前主流 AI 编程工具都在逐步支持这类机制。比如 Claude Code 会读取用户目录下.claude/skills中的 Skill 定义Codex 也能通过项目说明文件加载自定义技能Cursor 的规则目录同样可以达到类似效果。因为核心都是“描述文件 可执行脚本 模板”所以这套投研 Skill 可以在不同工具间复用只需要调整目录位置和描述格式。这也是我选择把它做成 Skill 而不是一段固定 prompt 的原因可复用、可分发、还能用 Git 做版本管理。另一个关键点是Skill 能强制 AI 去调用本地脚本而不是靠自己的语言模型“脑补”财务数字这直接解决了 AI 在数据准确性上的最大短板。1.3 为什么选择自定义 Skill 而不是固定提示词有一段时间我在各种收藏夹里攒了大量“AI 投研提示词”比如“你是一名资深分析师请从盈利能力、成长性、估值水平三方面分析 XXX 公司”。说实话这类提示词有一定效果但问题也很明显第一每次使用都要复制粘贴不同成员之间版本还会漂移第二prompt 里没法内置可执行的取数逻辑AI 只能基于训练数据里的旧信息回答无法拿到最新财报第三输出格式完全看模型心情上一份报告是表格下一份就可能变成小作文。自定义 Skill 把这些问题都解决了。你可以把 Python 脚本放在 Skill 目录里让 AI 按步骤执行可以把模板文件放在同一个目录下规定输出结构还可以把整个目录提交到 Git团队里所有人拉下来就是同一套研究标准。而且 Skill 本身可以迭代今天发现某个指标算错了改一次脚本以后所有分析都自动修正。这种“一次建设、长期复用”的体验是用普通提示词无法获得的。2. Skill 的整体设计与目录结构2.1 功能模块划分我把整个投研流程拆成三个模块取数模块、计算模块、输出模块。取数模块负责拿到股票代码后拉取最新的财务数据和行情数据计算模块负责算出核心指标比如 ROE、毛利率、净利率、资产负债率、PE、PB、自由现金流输出模块则把指标和模板结合生成一份带数据来源和风险提示的研报草稿。这样拆是有原因的。三个模块可以独立测试和替换比如换一个数据源时不需要动计算逻辑计算脚本用 Python 写死公式能避免模型在对话里“心算”出错模板独立出来之后想调整研报格式只需要改 markdown 文件不用重新解释需求。模块之间的数据流也很清晰取数脚本落地 CSV计算脚本读 CSV 产出 JSON最后模板渲染成 Markdown。任何一个环节出问题都能快速定位。模块主要职责对应文件数据获取拉取行情、财务报表、基础信息scripts/fetch_data.py指标计算计算盈利质量、成长、估值、现金流指标scripts/calc_metrics.py报告生成根据模板生成结构化研报scripts/generate_report.py流程编排让 AI 按步骤执行并调用脚本SKILL.md2.2 目录结构与配置说明实际目录长这样equity_research_skill/ ├── SKILL.md ├── scripts/ │ ├── fetch_data.py │ ├── calc_metrics.py │ └── generate_report.py ├── templates/ │ ├── report_template.md │ └── checklist.md └── data/ ├── balance.csv ├── income.csv ├── cashflow.csv └── price.csvSKILL.md 是这个 Skill 的核心描述文件建议用 YAML front matter 写清楚技能名称和触发描述。它相当于“使用说明书”AI 会先读这个文件才知道该按什么顺序执行任务。下面是我在项目里实际使用的 SKILL.md 简化版--- name: equity_research description: 用于个股基本面投研分析。输入股票代码或公司名称自动获取财务数据、计算核心指标并生成结构化研报草稿。 --- # Equity Research Skill ## 执行步骤 1. 用户输入股票代码如 600519.SH后先运行 python scripts/fetch_data.py 代码 获取数据。 2. 数据拉取成功后运行 python scripts/calc_metrics.py 代码 计算指标。 3. 结合计算结果和 templates/report_template.md 生成研报。 4. 生成内容必须在末尾注明“本内容仅供研究参考不构成投资建议”和取数时间。放在哪个目录取决于工具。Claude Code 通常读取~/.claude/skills/和项目内.claude/skills/Codex 可以通过AGENTS.md或对应技能目录加载Cursor 的规则目录也能放自定义 skill。我自己的习惯是放在项目.claude/skills/下这样不同机器、不同项目拉下来就能用。写完目录后记得重启会话或者在工具里执行列出 skills 的命令确认已经加载。2.3 环境准备与安装在使用这套 Skill 之前需要保证本机有可用的 Python 环境。我的建议是用虚拟环境隔离依赖避免污染系统 Python。命令很简单mkdir -p equity_research_skill/{scripts,templates,data} cd equity_research_skill python -m venv .venv source .venv/bin/activate # Windows 下是 .venv\Scripts\activate pip install akshare pandasakshare 是取数用的开源库pandas 用于数据清洗。如果你还想让报告生成脚本更优雅一点可以再加一个 jinja2不过我在示例里用的是纯字符串替换不依赖额外库。装好依赖后先手动跑一遍 fetch 脚本能正常打印“done”再交给 AI 使用。否则 AI 调脚本时报错排查起来会多一层噪音。3. 核心能力实现与实操要点3.1 数据获取与清洗取数我选了 akshare。原因很简单免费、覆盖 A 股主要行情和财务报表、接口调用门槛低。缺点也有接口字段偶尔会变后面常见问题部分会专门讲。以下是我在 fetch_data.py 里用的一个简化版本足以跑通全流程import sys import akshare as ak import pandas as pd code sys.argv[1] # 取资产负债表、利润表、现金流量表最近几期 for table, name in [ (资产负债表, balance), (利润表, income), (现金流量表, cashflow), ]: df ak.stock_financial_report_sina(stockcode, symboltable) df.to_csv(fdata/{name}.csv, indexFalse) # 取日线行情用于计算 PE/PB 的实时值 price ak.stock_zh_a_hist(symbolcode.split(.)[0], perioddaily, start_date20240101, adjustqfq) price.to_csv(data/price.csv, indexFalse) print(done)注意几点财务报表的单位一般是“元”但有的接口返回的是“万元”写计算脚本之前先打印几行看看stock_financial_report_sina返回的是按报告期排列的明细表里面包含公告日期和报告期后续计算要用最新报告期数据股票代码格式在不同接口里不统一有的要600519有的要600519.SH建议在 SKILL.md 里约定统一格式再由脚本内部转换。清洗数据这一步往往决定成败。原始财务表里会有不少空列和重复列名例如“净利润”可能出现“归属于母公司所有者的净利润”和“净利润”两个字段。我一般会根据字段名关键词优先选择更严格的口径例如要算归母净利润时匹配“归属于母公司所有者的净利润”实在找不到再用“净利润”。如果关键字段缺失宁可让脚本报错也不要让后续计算带着 NaN 继续跑。3.2 财务指标与估值计算拿到原始数据后重点不是把所有财务指标都算一遍而是围绕“盈利质量、成长性、财务健康、估值”四个维度选最核心的指标。我这里固定算这几个指标公式用途ROE净利润 / 净资产衡量股东回报效率毛利率毛利 / 营收衡量商业模式与护城河净利率净利润 / 营收衡量整体盈利效率资产负债率总负债 / 总资产衡量财务风险经营现金流/净利润经营现金流绝对值 / 净利润检验利润含金量PE总市值 / 净利润TTM估值水平PB总市值 / 净资产估值水平自由现金流经营现金流 - 购建固定资产支出企业可自由支配的现金calc_metrics.py 里比较关键的是数据处理部分。因为原始表里包含多个报告期必须按报告期排序后取最新一行同时注意字段名在不同年份可能有差异建议用“包含某个关键词”的方式去做字段匹配。具体片段def get_field(df, keywords): for col in df.columns: if any(k in col for k in keywords): return col return None latest df.sort_values(报告期).iloc[-1] net_income_col get_field(df, [归属于母公司所有者的净利润, 净利润]) equity_col get_field(df, [归属于母公司股东权益合计, 股东权益合计]) roe latest[net_income_col] / latest[equity_col]从实际使用的角度这些口径问题比指标本身更容易把人绊倒。ROE 建议用归母净利润除以归母净资产而不是用含少数股东权益的合并净资产否则不同公司之间差异很大PE 建议用最近 12 个月净利润的 TTM 口径避免只拿单季净利润导致估值失真PB 用最新报告期的净资产不能用上一年年报的净资产因为年中分红和增发都会直接影响净资产。还有一个细节是自由现金流很多人直接用“经营现金流净额 - 投资现金流净额”但投资现金流里包含理财产品的买卖会把计算口径搞混。更实用的口径是用“经营现金流净额 - 购建固定资产、无形资产和其他长期资产支付的现金”这样更接近企业真实的扩张消耗。所有计算结果最终可以汇总成一个 JSON 文件供后续报告生成使用。格式类似{ code: 600519.SH, report_date: 2024-09-30, roe: 0.286, gross_margin: 0.917, net_margin: 0.523, debt_ratio: 0.214, ocf_to_net_profit: 1.17, pe_ttm: 26.5, pb: 8.4, fcff: 52300000000 }3.3 研报生成与输出计算脚本只负责产出结构化数据真正的投研观点仍由 AI 生成。为了让输出稳定模板必须足够细。report_template.md 我是这样组织的# {公司简称} ({股票代码}) 投研简报 ## 业务概况 - 主营产品/服务 - 主要客户与行业地位如有已知信息 ## 财务表现数据截至 {取数日期} - 最新报告期 - 营业收入及增速 - 归母净利润及增速 - 毛利率、净利率 - ROE ## 估值与现金流 - PE/PB - 自由现金流 - 经营现金流/净利润 ## 核心看点 基于以上数据总结 2-3 个关键点 ## 风险提示 列出财报数据中值得警惕的信号 免责声明本内容仅供研究参考不构成投资建议。generate_report.py 可以写成一个简单的模板渲染器从 JSON 中读取指标替换模板里的占位符。核心逻辑如下import json, pathlib, sys metrics json.loads(pathlib.Path(output/metrics.json).read_text()) template pathlib.Path(templates/report_template.md).read_text() for k, v in metrics.items(): template template.replace({ k }, str(v)) pathlib.Path(output/report.md).write_text(template) print(report generated)不过生成报告这个环节我更推荐让 AI 来做最终润色而不是完全依赖脚本。脚本填充的是一份信息准确的初稿AI 负责把“核心看点”和“风险提示”写成通顺的自然语言。SKILL.md 的执行步骤里要特别强调两点一是所有数据必须来自/data目录下的 CSV 或 JSONAI 不能自己“编”一个数出来二是模板里的每一项都要写不允许漏项。实测下来只要把这两点写进 Skill 描述生成质量会稳定很多。3.4 让 Skill 适配不同 AI 编程工具这套 Skill 不是某个工具独有的但不同工具的加载方式略有差异。Claude Code 中放在~/.claude/skills/下的技能全局可用放在项目.claude/skills/下的技能只对当前项目生效配置好之后可以在会话里用命令查看已加载技能确认描述是否被识别。Codex 的做法通常是依赖项目说明文件例如在AGENTS.md中写明“当前项目包含 equity_research_skill使用时请先阅读 SKILL.md”也有的团队会直接用官方支持的自定义技能目录以最新文档为准。Cursor 用户则可以把 SKILL.md 的核心指令复制进.cursor/rules或.cursorrules让对话模型知道遇到个股分析任务时该调用哪些脚本。不管用哪种工具核心逻辑是一样的让 AI 知道有一个可调用的技能并且明确脚本路径和执行顺序。如果不想维护多份配置一个偷懒的办法是在项目根目录写一个简短的AI_AGENTS.md把“投研分析请参考.claude/skills/equity_research_skill/SKILL.md”这句说明写清楚大部分工具都能读懂这种约定式指引。4. 常见问题与排查技巧4.1 Skill 没有生效新手最容易遇到的就是技能放好了但 AI 不调用。先检查目录位置有的工具只读取项目内.claude/skills有的读~/.claude/skills放错位置当然不会生效。其次检查 SKILL.md 开头的 YAML front mattername和description缺一不可description 要写清楚“输入股票代码”这个触发条件。最后改完文件后必须重启会话之前我因为没重启反复怀疑脚本写错浪费了不少时间。还有一类情况是 AI 虽然读了 SKILL.md但执行顺序不对。比如它直接开始写报告跳过了取数和计算。这时候要在执行步骤里加更明确的指令例如“必须运行脚本禁止在没有脚本输出的情况下生成财务数据”。如果工具支持调试模式可以先让 AI 输出它认为应该执行的命令再手动干预纠正。4.2 数据源不稳定akshare 的接口属于“免费但会变”最典型的问题是某个财务表字段名变了导致脚本取值取到 NaN。我的处理方式是把数据抓取和指标计算解耦抓到 CSV 后脚本先做一次空值检查如果发现关键字段缺失就中止流程并输出提示而不是带着错误继续往下算。日常使用还可以在 fetch 脚本里加一个--cache参数当天数据缓存下来重复分析同一只票就不必重复拉接口也能减少被数据源限流的情况。当接口失效时不要硬等修复可以直接准备本地 CSV 作为降级方案。从行情软件或公司公告里手动导出最近几期财务报表放到data/目录下再让脚本带一个--local参数读取本地文件。这样即使数据源接口临时挂了投研流程也能继续跑。数据合规上也要注意只使用公开披露的财报和行情数据不要抓取非公开信息也不要大规模高频请求接口个人研究频率下基本不会踩线。4.3 结果不准 / 幻觉AI 生成研报时最容易出现的问题是“一本正经地编指标”。比如我遇到过它把上年同期净利润当成最新值还写进了摘要。解决办法主要靠两点第一把计算全部交给脚本计算结果以 JSON 形式给到 AI并且要求它只能引用这份 JSON 里的数字第二在生成结果末尾强制带上取数时间这样复盘时能判断是不是数据过期导致的偏差。另外所有涉及个股的结论我都让模型在“风险提示”里加上一句“数据可能存在口径差异请以公司公告为准”这个习惯帮我避免了好几次“数据被误读”的尴尬。还有一种比较隐蔽的错误是“字段匹配错误”。比如有些数据接口会同时返回“净利润”和“归属于母公司所有者的净利润”如果脚本用模糊匹配匹配到了前者算出来的 ROE 就会偏高。我的经验是在 get_field 里把更精确的字段放在关键词列表最前面优先匹配长字段名。同时建议每个指标在 JSON 里附带一个unit字段标明单位是元、万元还是亿元上游单位错了后面所有结论都会跟着错。4.4 离线场景下怎么办如果你是出差途中或者网络不稳定A 股实时接口可能拉不到数据。我的解决办法是提前把重点关注池的财报数据导出成 CSV存到data/history/目录下然后修改 fetch 脚本支持--local模式。本地模式不再调用任何网络接口而是从 CSV 里读取最近报告期数据同样可以完成指标计算和报告生成。虽然拿不到最新的行情但基本面分析本来就更依赖季报年报一两天内的离线不会让你的研究结论失效。最后再分享一个小技巧把你在实战中反复踩过的检查项沉淀成模板里的 checklist比如商誉占比超过净资产 30% 要单独提示、应收账款增速远高于营收增速要警惕、经营现金流连续为负必须重点说明。Skill 最大的价值不在省几分钟而在于它会逼着 AI 每次都用同一套标准帮你扫描这些信号。我实际跑了大半年之后这个投研 Skill 已经从最早的取数和计算慢慢长成了包含检查清单、风险提示模板、多数据源降级方案的研究框架。对我来说它带来的不是某一次分析有多惊艳而是每一次分析都不会再漏掉那些本来应该被看见的细节。
返回列表