记录 llm_stock_report 的实际使用方式,以及为什么在股票预测场景里不能只靠大模型,而要引入 Qlib 风格特征和树模型。
这个项目是我最近做的一个个人开源项目,目标不是做一个“只会聊天的股票助手”,而是做一个真正能每天看盘、给出结构化结论、还能自动推送到 Telegram 的看盘机器人。
它的核心思路很明确:
如果只用大模型来分析股票,通常会遇到几个问题:
如果只用传统量化模型,也有另外一组问题:
所以这个项目最后选的方向,不是“LLM 替代量化”,也不是“量化完全不需要 LLM”,而是做一个双引擎系统。
从当前仓库结构来看,这个项目已经是一个完整分层的 Python 工程,不是单文件脚本。
大致可以拆成几层:
app/data/:按市场抓取行情数据,A 股走 AKShare,美股和港股走 yfinanceapp/features/:构建技术指标等特征app/model/:做 Qlib 风格数据整理、训练和预测app/news/:聚合新闻搜索,主路径是 Tavily,Brave 做 fallbackapp/llm/:适配 OpenAI / Gemini / Ollama,并生成解释文本app/report/:把预测结果和分析结论渲染成 Markdown 和 Telegram 消息app/jobs/:训练和日报的统一入口README 里也给出了很清晰的处理链路:
flowchart LR
A["行情数据获取"] --> B["特征工程 / 缓存"]
B --> C["LightGBM预测"]
C --> D["新闻抓取"]
D --> E["大模型生成解释"]
E --> F["Telegram推送"]这部分按项目当前 README 的方式来,用起来是比较直接的。
项目要求 Python 3.11+。
先安装基础依赖:
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'如果你还需要完整的 pyqlib 环境,可以继续安装:
python -m pip install -e '.[qlib]'从 pyproject.toml 看,核心依赖包括:
aksharelightgbmnumpypandasPyYAMLrequestsyfinance股票池配置在:
config/universe.yaml可以按市场分别维护 A 股、美股和港股的股票列表。
把:
.env.example复制成:
.env然后把需要的 key 填进去。
根据 README,目前至少需要:
TAVILY_API_KEYBRAVE_API_KEYTELEGRAM_BOT_TOKENTELEGRAM_CHAT_ID模型侧至少配置一条可用路径:
LLM_PROVIDER=openai + OPENAI_API_KEYLLM_PROVIDER=gemini + GEMINI_API_KEYLLM_PROVIDER=ollama + OLLAMA_BASE_URL + OLLAMA_MODELpython -m pytest这个步骤很值得保留,因为项目里已经有比较完整的测试目录。先把环境和基础链路验证掉,后面排查问题会省很多时间。
日报依赖训练好的模型,所以可以先按市场手动训练。
python -m app.jobs.run_retrain --market cn --date 2026-03-04
python -m app.jobs.run_retrain --market us --date 2026-03-04
python -m app.jobs.run_retrain --market hk --date 2026-03-04从实现上看,训练入口会做几件事:
LightGBM 训练回归模型;这里有一个我比较喜欢的设计:项目不是假设“树模型一定训练成功”,而是明确实现了 fallback 路径。这对自动化日报项目很重要,因为它强调的是每天都能稳定跑,而不是只在理想环境下跑。
训练完成之后,就可以手动跑日报。
python -m app.jobs.run_report --market cn --date 2026-03-04
python -m app.jobs.run_report --market us --date 2026-03-04
python -m app.jobs.run_report --market hk --date 2026-03-04日报任务会完成下面这些动作:
项目默认会把运行结果写到:
outputs/{market}/{date}/README 里列出的主要输出文件有:
summary.mddetails.mdpredictions.csvrun_meta.json这组输出设计是比较实用的,因为它同时兼顾了:
这是这个项目最核心的开发思考。
如果把问题简化成一句话,那就是:
大模型擅长的部分是:
但大模型不擅长直接代替一个严格的时序预测器。尤其是涉及:
这些内容如果完全交给 LLM,输出通常会变得很主观,也不够稳定。
这个项目采用的方式,本质上是先把“预测”这部分交给更传统的量化路径,再让大模型去做解释和报告。
从实现上看:
app/model/qlib_data_builder.py 负责构造 Qlib 风格的数据框架;app/features/technical.py 负责技术指标;app/model/trainer.py 默认用 LightGBM 来训练 next_day_return 的回归模型;app/model/predictor.py 负责根据预测值做标准化、排序和 side bucket 划分。这里选择树模型而不是把所有判断都交给 LLM,原因很直接:
换句话说,大模型在这个项目里不是“预测器本身”,而是:
这也是我觉得这个项目更合理的地方。
如果只是做一个模型实验,其实到 predictions.csv 就可以停了。
但这个项目最后多做了一步,就是把整个链路封成一个可以日常使用的机器人:
这一步非常关键,因为它把项目从“一个研究脚本”推进成了“一个真实可用的系统”。
对个人用户来说,这类看盘机器人最大的价值不是替你自动交易,而是每天帮你完成:
这会大幅减少每天看盘时的信息整理成本。
从现在这个仓库看,有几个设计我觉得是对的:
不是只做单一市场,而是同时覆盖:
这让系统的扩展性更强,也更贴近真实使用需求。
项目没有每次都全量重拉,而是做了本地历史缓存和增量更新。这对行情类系统很重要,不然跑久了之后成本和稳定性都会变差。
Tavily 主搜索、Brave 兜底,这种 fallback 思路跟模型层的 fallback 一样,体现的是系统稳定性优先。
这点是我最认同的:LLM 在这个项目里是最后一层表达,而不是最底层预测内核。
如果继续往下做,我觉得还可以继续增强几个方向: