青玉案 d0e66a1dc3 feat: 新闻检索为空时在报告中如实标注 (#2229)
* feat: 新闻检索为空时在报告中如实标注

消息面章节此前是「有内容才渲染」,检索一条没拿到时整段直接消失,
读报告的人无从判断是确实没新闻,还是检索静默失败了(搜索源限流、
未配置可用渠道等)。这把「抓取失败」呈现成了「确实没有新闻」。

- src/analyzer.py: AnalysisResult 新增 news_result_count,默认 None
- src/core/pipeline.py: 把 Step 4 已算好的计数交给结果对象
  (此前只进了 diagnostic context snapshot,报告层拿不到)
- src/notification.py: news_lines 为空且计数为 0 时,渲染明确提示,
  并说明结论未纳入新闻维度证据
- tests: 新增 5 条用例,含两条负例——计数为 None 时不得报警
  (那是未配置搜索渠道,不是失败)、拿到新闻时行为与改动前一致

不触碰任何检索路径,纯展示层增量。

* fix: 把新闻缺失提示放进真实渲染路径,并独立于模型输出判定

按 review 三条意见修正:

P1-1 提示只存在于 generate_daily_report,而正常流程从不调用它——
_send_single_stock_notification 与聚合报告走的是 dashboard / brief /
single_stock。原实现对所有标准 REPORT_TYPE 都不生效。
改为抽出共享判定 _empty_news_disclosure,四个渲染器统一接入。

P2 检索零命中但模型按 schema 写出了 market_sentiment / hot_topics 时,
原 elif 分支被跳过,报告会展示模型生成的情绪判断却隐瞒无新闻证据。
改为独立判定 news_result_count == 0,与模型是否产出文字无关。

P1-2 补 docs/CHANGELOG.md [Unreleased] 条目,并在
docs/data-source-stability.md 的「用户可见提示建议」一节记录该行为,
含 None / 0 / >0 三态语义表。

测试从 5 条增至 10 条,新增覆盖 dashboard、brief、single_stock 三个真实
渲染器,以及「模型有输出但检索为空」这一最糟组合。39 passed

* fix: 把新闻零命中披露覆盖到模板链路与企业微信入口

按 review 指出的 blocker 修正。此前只接了字符串拼接分支,遗漏两类活路径:

1. REPORT_RENDERER_ENABLED=true 时,generate_dashboard_report /
   generate_brief_report / generate_wechat_dashboard 会先 return render(...),
   模板链路一路不渲染披露;
2. generate_wechat_dashboard 的非模板 fallback 从未接入,而 pipeline 在
   企业微信非 brief 场景会直接调用它。

后果是同一份分析结果在部分渠道披露、在另一些渠道沉默。

改法不再逐点打补丁,而是抽出单一事实来源:

- 新增 src/services/empty_news.py 持有判定与中英文案
- src/notification.py 的 _empty_news_disclosure 改为委托该模块
- src/services/report_renderer.py 为每条结果预计算 empty_news_disclosure,
  三个平台模板共用
- templates/report_markdown.j2 / report_brief.j2 / report_wechat.j2 各加渲染分支
- generate_wechat_dashboard 的 fallback 正文接入披露

新增 6 条回归测试:模板链路三个平台各一条、企业微信入口一条,
外加两条负例(未执行检索时模板与企业微信均不得提示)。

本文件测试 10 → 16 全过;全量 5824 passed,9 个既有失败与本 PR 无关
(干净 main 上同样失败,属测试顺序依赖)。

* fix: 修正计数源头的两处缺口(自查发现)

按 review 的 merge-base..HEAD 方法自查全链路,发现此前几轮都只盯着渲染出口,
从未核对计数源头,而源头本身在两条路径上是错的:

1. src/core/pipeline.py: news_result_count 只在 intel_results 非空时赋值,
   搜索服务整体失败(正是所有搜索源限流全挂的场景)时停留在 None,
   语义为「未执行检索」,于是本 PR 想解决的头号场景反而不提示。
   改为检索一发起即置 0。

2. _analyze_with_agent: Agent 模式自行调用 search_stock_news 完成检索,
   却从不回写计数,该路径下零命中永远静默。改为按检索结果回写 0 或实际条数。

渲染层再周全,源头数据不对则全部落空。

新增 2 条测试锁住这两处语义(18 passed,此前 16)。
全量 5826 passed,9 个既有失败与本 PR 无关。

* fix: disclose missing news search configuration

* chore: remove unrelated agent guidance

* test: run all empty news tests directly

* fix: preserve empty news disclosure across reports

* fix: 让 Agent 模式的新闻披露跟随实际消费的证据

原问题:agent_arch=multi 等受支持的 Agent 配置下,报告可能声称「未纳入新闻
面证据」而分析其实用了新闻,或反过来该提示而不提示。

根因:news_result_count 取自 executor.run() 结束后为持久化情报补打的一次
search_stock_news()。真实情报由 IntelAgent 通过 search_comprehensive_intel
取得,两者不等价,因此披露与真实证据链可能相反。

修复点:新增 src/agent/news_evidence.py,以运行期证据作用域收集 Agent 搜索
工具的真实返回条数;搜索渠道不可用为 None(未执行检索),可用则从 0 起步、
拿到多少算多少。pipeline 在 executor.run() 前后开启并读取该作用域,事后的
持久化补查不再回写计数。

回归风险:工具在 ThreadPoolExecutor 中执行,runner.py 以
contextvars.copy_context() 提交,故作用域中必须是可变累加器对象,换成不可变
值会让父线程读不到;已加回归测试锁住该机制。原 test_agent_path_records_count
断言的正是被修复的错误行为,已替换为反向断言。

Refs #2225

* fix: 让新闻披露以实际证据为准而非搜索命中数

原问题:本地已落库的资讯池或社交情绪进入 news_context 参与分析后,报告仍可能
声称「未配置搜索渠道,本次分析未纳入新闻面证据」或「零命中」。

根因:news_context 由三路来源拼成——实时检索、社交情绪(美股)、本地资讯池,
但只有实时检索会更新 news_result_count。披露断言的是「结论有没有用到新闻面
证据」,而计数只是「搜索命中了几条」,两者是不同命题,后两路参与时必然失真。

修复点:AnalysisResult 新增 news_evidence_present,由 news_context 是否非空
得出,pipeline 两条路径共用 src/services/empty_news.news_evidence_present()
这一个判定函数。披露改为先看有无证据;确无证据时才用计数解释原因
(None=未配置渠道,0=检索零命中)。历史重建同步恢复该字段。

回归风险:旧记录没有该字段,按计数回退推断,与该记录当时的报告表现一致,不会
追溯改变旧报告;已有用例锁住。review 只点名了本地资讯池,社交情绪属同一缺陷类,
本次一并修复并加测试。另加源码断言:任一 pipeline 路径改回只传计数即失败。

Refs #2225

* fix: 按来源登记新闻证据,不让零命中占位文本冒充证据

原问题:普通分析链路在「搜索已执行但一条证据都没拿到」时,报告不再显示零命中
披露——正是本 PR 要修的核心场景,反而比改动前更差。

根因:src/search_service.py 的 format_intel_report() 即使所有维度失败或为空,
也会输出「【XX 情报搜索结果】」标题和每个维度的「未找到相关信息」占位文本,
整段永远非空。上一版把拼好的 news_context 整段交给 news_evidence_present()
判定,于是 news_result_count == 0 时 evidence 被翻成 true,披露被吞掉,错误
状态还会经 to_dict() 持久化,继续影响历史、详情 API 与 Web。

修复点:判定改为按来源逐个登记——实时检索的真实命中数、社交情绪内容、本地
资讯池内容,任一为真才算有证据;两条 pipeline 路径都不再传拼好的整段。
news_evidence_present() 的契约随之改为接收各来源,并在文档串里写明为什么不能
传整段。

回归风险:新增反例用真实的 format_intel_report() 产出占位文本(不用 mock),
断言其不得被判成证据、且报告必须出现零命中披露。另有源码断言:谁把整段
news_context 交回判定函数即失败。上一版两条测试实际在保护该缺陷(一条名为
「任何非空 context 都算证据」,一条要求必须传入 news_context),已一并纠正。

Refs #2225

---------

Co-authored-by: Mach-Chan <zz-b240@zz-b240deMacBook-Air.local>
2026-08-22 21:27:04 +08:00
2026-01-10 15:38:56 +08:00

📈 股票智能分析系统

GitHub stars CI License: MIT Python 3.10+ GitHub Actions Docker

#1 Python Repository Of The Day | Trendshift Featured|HelloGitHub

🤖 基于 AI 大模型的 A股/港股/美股/日股/韩股/台股自选股智能分析系统,每日自动分析并推送「决策仪表盘」到企业微信/飞书/Telegram/Discord/Slack/邮箱

产品预览 · 功能特性 · 快速开始 · 推送效果 · 文档中心 · 完整指南

简体中文 | English | 繁體中文

💖 赞助商 (Sponsors)

Anspire Open 一站式模型和搜索服务 轻松抓取搜索引擎上的实时金融新闻数据 - SerpApi

🖥️ 产品预览

DSA Web 工作台演示

功能特性

能力 覆盖内容
AI 决策报告 核心结论、评分、趋势、买卖点位、风险警报、催化因素、操作检查清单
多市场数据聚合 覆盖 A股、港股、美股、日股、韩股、台股和 ETF支持行情、K 线、技术指标、新闻、公告、基本面与报告辅助数据;不同市场的数据源和能力边界见 市场支持边界
Web / 桌面工作台 手动分析、任务进度、历史报告、完整 Markdown、回测、持仓、配置管理、浅色 / 深色主题
Agent 策略问股 多轮追问,支持均线、缠论、波浪、趋势、热点、事件、成长、预期等 15 种内置策略,覆盖 Web/Bot/API
智能导入与补全 图片、CSV/Excel、剪贴板导入股票代码/名称/拼音/别名补全
自动化与推送 GitHub Actions、Docker、本地定时任务、FastAPI 服务和企业微信/飞书/Telegram/Discord/Slack/邮件推送

功能细节、字段契约、基本面 P0 超时语义、交易纪律、数据源优先级、Web/API 行为请看 完整配置与部署指南

技术栈与数据来源

类型 支持
AI 模型 AnspireAIHubMix、Gemini、OpenAI 兼容、DeepSeek、通义千问、Claude、Ollama 本地模型等
行情数据 TickFlow、AkShare、Tushare、Pytdx、Baostock、YFinance、Longbridge
新闻搜索 AnspireSerpAPITavilyBochaBraveMiniMax、SearXNG
社交舆情 Stock Sentiment APIReddit / X / Polymarket仅美股可选

项目默认内置 AkShare、Baostock、YFinance 等免费行情源,可零配置运行;免费源受上游限流、接口变动和网络波动影响,稳定性不保证。长期定时、批量分析或更稳定行情建议配置 TickFlow、Tushare、Longbridge 等 token 型数据源适用市场、Actions 映射和 fallback 规则见 数据源配置

🚀 快速开始

方式一:GitHub Actions推荐

5 分钟完成部署,零成本,无需服务器。

1. Fork 本仓库

点击右上角 Fork 按钮(顺便点个 Star 支持一下)

2. 配置 Secrets

SettingsSecrets and variablesActionsNew repository secret

AI 模型配置(至少配置一个)

默认先选一个模型服务商并填写 API Key需要多模型、图片识别、本地模型或高级路由时再参考 LLM 配置指南

Secret 名称 说明 必填
ANSPIRE_API_KEYS Anspire API Key一Key同时启用全球热门大模型和联网搜索本项目新用户提供30元等额的免费额度GLM5.2、GPT等模型特惠中 推荐
AIHUBMIX_KEY AIHubMix API Key一Key切换使用全系模型无需科学上网本项目可享 10% 优惠 推荐
GEMINI_API_KEY Google Gemini API Key 可选
ANTHROPIC_API_KEY Anthropic Claude API Key 可选
OPENAI_API_KEY OpenAI 兼容 API Key支持 DeepSeek、通义千问等 可选
OPENAI_BASE_URL / OPENAI_MODEL 使用 OpenAI 兼容服务时填写 可选

Ollama 更适合本地 / Docker 部署GitHub Actions 推荐使用云端 API。

通知渠道配置(至少配置一个)

Secret 名称 说明
WECHAT_WEBHOOK_URL 企业微信机器人
FEISHU_WEBHOOK_URL 飞书机器人
TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID Telegram
DISCORD_WEBHOOK_URL Discord Webhook
SLACK_BOT_TOKEN + SLACK_CHANNEL_ID Slack Bot
EMAIL_SENDER + EMAIL_PASSWORD 邮件推送

更多渠道、签名校验、分组邮件、Markdown 转图片等配置见 通知渠道详细配置

自选股配置(必填)

Secret 名称 说明 必填
STOCK_LIST 自选股代码,如 600519,hk00700,AAPL,7203.T,005930.KS,2330.TW

新闻源配置(推荐)

新闻源会显著影响舆情、公告、事件和催化因素质量,建议至少配置一个搜索服务。

Secret 名称 说明 必填
ANSPIRE_API_KEYS Anspire AI Search汇聚全球舆情信息适配A股、美股、港股等新闻和舆情检索同一Key可复用大模型服务本项目新用户提供免费30元等额的免费点数 推荐
SERPAPI_API_KEYS SerpAPI:搜索引擎结果补强,适合实时金融新闻 推荐
TAVILY_API_KEYS Tavily:通用新闻搜索 API 可选
BOCHA_API_KEYS 博查搜索:中文搜索优化,支持 AI 摘要 可选
BRAVE_API_KEYS Brave Search:隐私优先,美股资讯补强 可选
MINIMAX_API_KEYS MiniMax:结构化搜索结果 可选
SEARXNG_BASE_URLS SearXNG 自建实例:无配额兜底,适合私有部署 可选

更多搜索源、社交舆情和降级规则见 搜索服务配置

行情数据源配置(可选)

默认使用 AkShare、Baostock、YFinance 等免费数据源,日志中"未配置"的提示不影响运行。 如需更稳定的行情,可按市场配置以下 Secret

Secret 名称 适用市场 说明
TUSHARE_TOKEN A 股 提升历史行情稳定性
LONGBRIDGE_OAUTH_CLIENT_ID + LONGBRIDGE_OAUTH_TOKEN_CACHE_B64 港股/美股 补齐量比、换手率、PE 等字段

详见 数据源配置

3. 启用 Actions

Actions 标签 → I understand my workflows, go ahead and enable them

4. 手动测试

Actions每日股票分析Run workflowRun workflow

完成

默认每个**工作日 18:00北京时间**自动执行,也可手动触发。默认非交易日(含 A/H/US 节假日)不执行;强制运行、交易日检查、断点续传等规则见 完整指南

方式二:客户端配置教程 / 本地运行 / Docker 部署

# 克隆项目
git clone https://github.com/ZhuLinsen/daily_stock_analysis.git && cd daily_stock_analysis

# 安装依赖
pip install -r requirements.txt

# 配置环境变量
cp .env.example .env && vim .env

# 运行分析
python main.py

常用命令:

python main.py --debug
python main.py --dry-run
python main.py --stocks 600519,hk00700,AAPL,2330.TW
python main.py --market-review
python main.py --schedule
python main.py --serve-only

Docker 部署、定时任务、云服务器访问请参考 完整指南;桌面客户端打包请参考 桌面端打包说明

📱 推送效果

决策仪表盘

🎯 2026-02-08 决策仪表盘
共分析3只股票 | 🟢买入:0 🟡观望:2 🔴卖出:1

📊 分析结果摘要
⚪ 中钨高新(000657): 观望 | 评分 65 | 看多
⚪ 永鼎股份(600105): 观望 | 评分 48 | 震荡
🟡 新莱应材(300260): 卖出 | 评分 35 | 看空

⚪ 中钨高新 (000657)
📰 重要信息速览
💭 舆情情绪: 市场关注其AI属性与业绩高增长情绪偏积极但需消化短期获利盘和主力流出压力。
📊 业绩预期: 基于舆情信息公司2025年前三季度业绩同比大幅增长基本面强劲为股价提供支撑。

🚨 风险警报:

风险点12月5日主力资金大幅净卖出3.63亿元,需警惕短期抛压。
风险点2筹码集中度高达35.15%,表明筹码分散,拉升阻力可能较大。
风险点3舆情中提及公司历史违规记录及重组相关风险提示需保持关注。
✨ 利好催化:

利好1公司被市场定位为AI服务器HDI核心供应商受益于AI产业发展。
利好22025年前三季度扣非净利润同比暴涨407.52%,业绩表现强劲。
📢 最新动态: 【最新消息】舆情显示公司是AI PCB微钻领域龙头深度绑定全球头部PCB/载板厂。2月5日主力资金净卖出3.63亿元,需关注后续资金流向。

---
生成时间: 18:00

大盘复盘

🎯 2026-01-10 大盘复盘

📊 主要指数
- 上证指数: 3250.12 (🟢+0.85%)
- 深证成指: 10521.36 (🟢+1.02%)
- 创业板指: 2156.78 (🟢+1.35%)

📈 市场概况
上涨: 3920 | 下跌: 1349 | 涨停: 155 | 跌停: 3

🔥 板块表现
领涨: 互联网服务、文化传媒、小金属
领跌: 保险、航空机场、光伏设备

⚙️ 配置说明

完整环境变量、模型渠道、通知渠道、数据源优先级、交易纪律、基本面 P0 语义和部署说明请参考 完整配置指南

🖥️ Web 界面

Web 工作台提供配置管理、任务监控、手动分析、历史报告、完整 Markdown 报告、Agent 问股、回测、持仓管理、智能导入和浅色 / 深色主题。启动方式:

python main.py --webui
python main.py --webui-only

访问 http://127.0.0.1:8000 即可使用。认证、智能导入、搜索补全、历史报告复制、云服务器访问等细节见 本地 WebUI 管理界面

🤖 Agent 策略问股

配置任意可用 AI API Key 后Web /chat 页面即可使用策略问股;如需显式关闭可设置 AGENT_MODE=false

  • 支持均线金叉、缠论、波浪理论、多头趋势、热点题材、事件驱动、成长质量、预期重估等内置策略
  • 支持实时行情、K 线、技术指标、新闻和风险信息调用
  • 支持多轮追问、会话导出、发送到通知渠道和后台执行
  • 支持自定义策略文件与多 Agent 编排(实验性)

Agent 具体参数、skill 命名兼容、多 Agent 模式和预算护栏见 完整指南LLM 配置指南

DSA 聚焦日常分析报告;选股实现参考 AlphaSiftAlphaEvo 用于策略验证与进化。

项目 定位
AlphaSift DSA 选股实现的参考项目
AlphaEvo 策略回测与自我进化,用于验证策略规则,并通过迭代探索策略参数与组合

📬 联系与合作

合作邮箱 zhuls345@gmail.com
项目咨询、部署支持与功能扩展
小红书二维码
扫码关注小红书
小红书 欢迎关注小红书
问题反馈 提交 Issue

📄 License

MIT License © 2026 ZhuLinsen

欢迎在二次开发或引用时注明本仓库来源,感谢支持项目持续维护。

⚠️ 免责声明

本项目仅供学习和研究使用,不构成任何投资建议。股市有风险,投资需谨慎。作者不对使用本项目产生的任何损失负责。


Description
No description provided
Readme MIT 197 MiB
Languages
Python 78.8%
TypeScript 19.4%
JavaScript 0.8%
CSS 0.5%
Shell 0.2%
Other 0.2%