# News Sentiment Research

> 新闻情绪研究方法论 — Huntly RSS 42万篇历史新闻 → FinBERT+词典双引擎情绪 → 事件研究/来源预测力/时段特征/信号强度/首日动量/情绪反转/事件标签 七维深度分析 → 融合规律优化策略回测（来源白名单+时段过滤+多篇确认+首日动量+反转出场+连续/标签加成+无止损+动态止盈）→ 研报级 MD+PDF。用户说「新闻情绪」「新闻规律」「新闻策略」「情绪回测」「消息面研究」时使用。触发词：新闻情绪、新闻规律、情绪分析、消息面、新闻回测、情绪策略

- Skill: `qusong0627/news-sentiment-research` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add qusong0627/news-sentiment-research`
- Raw SKILL.md: https://api.skillmd.com/api/skills/qusong0627/news-sentiment-research/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: qusong0627 (https://skillmd.com/u/qusong0627)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/qusong0627/news-sentiment-research

---


> ## ⚙️ 运行环境契约（最高优先级，先于本文其余内容执行）
>
> 本技能可能运行在 **QuantBot（QwenPaw 容器）** 或**宿主机/本地 Claude Code**。执行前先探测环境（`which docker`、API 连通性），并遵守以下映射规则：
>
> 1. **后端 API 地址**：QwenPaw / 容器网络内一律用 `http://quantmind:8000`（`quantmind` 是 docker 网络别名）；仅宿主机调试用 `http://127.0.0.1:8000`。正文中出现的 `127.0.0.1:8000`、`localhost:800x`，在 QwenPaw 环境下自动替换为 `http://quantmind:8000`。
> 2. **取数脚本执行**：凡 import 了 `pandas / duckdb / psycopg2 / numpy / sqlalchemy` 等重依赖或 `backend` 包的脚本，**必须在 quantmind 容器内执行**（QwenPaw 本地 venv 无这些依赖）：
>    ```bash
>    docker cp <脚本路径> quantmind:/tmp/<脚本名> && docker exec -w /app quantmind python3 /tmp/<脚本名> <参数>
>    ```
>    脚本源三选一：宿主机 repo `skills/<name>/scripts/`、QwenPaw 工作区 `/app/working/workspaces/default/skills/<name>/scripts/`、挂载目录 `/quantmind/skills/<name>/scripts/`。纯标准库脚本（无重依赖）可在 QwenPaw 本地直接跑。
> 3. **报告落盘**：股票报告页可见的 MD/PDF 报告，直接写 `/data/reports/trading_agents/{市场或类别}/{股票名}/`（QwenPaw 对 `/app/db` 有写权限，**直接写文件，不要 docker cp**）；过程数据 facts 写 `/data/reports/<类别>/`（`/data` 可写）。
> 4. **MD → PDF 转换（按优先级降级）**：
>    ① `docker exec -w /app quantmind python3 backend/scripts/md_to_pdf_report.py <输入.md> <输出.pdf>`（研报级排版，首选）；
>    ② docker 不可用时，**改用 QwenPaw 内置 `pdf` 技能**把 MD 转成 PDF；
>    ③ 两者都不可用则只交付 MD，并明确告知用户 PDF 未能生成及原因。
> 5. 本文中的 `~/.claude`、`cp -r ... ~/.claude/skills` 等说明仅适用于本地 Claude Code 维护者，**QuantBot 不要执行**。

# news-sentiment-research — 新闻情绪研究方法论

把「RSS 新闻 → 情绪信号 → 交易规律」的完整研究管线沉淀为一套可复现、可升级的流程。核心成果（2026-08-20 实测）：

- **51,741 个有效事件、5,661 只股票、98 个交易日的完整研究**
- **最优策略：+84.34% / Calmar 7.76**（无止损 + 四重过滤 + 动态止盈）
- **动态止盈 100% 胜率是唯一利润引擎；固定止损 100% 亏损**
- **来源预测力跨度 8.66pp（财联社 +5.26% vs 南华早报 -3.40%）**

## 数据链路

```
Huntly SQLite /data/huntly/db.sqlite (423,848 篇)
  └─ page.connected_at = Asia/Shanghai 本地时间字符串（陷阱：无 tzinfo，需手动 replace）
      ▼
PostgreSQL news_article_enrichment 富集
  └─ huntly_page_id, tickers[] (后缀 600036.SH), sentiment_label, sentiment_score,
     event_tags[], industries[]
  └─ 情绪 = FinBERT (0.6) + 金融词典 51,887 词 (0.4) 融合
      ▼
信号生成 |score| ≥ 0.25
  └─ 时间对齐: 盘中(9:30-11:30/13:00-15:00)→当日收盘成交；盘后/盘前/非交易日→下一交易日
      ▼
QuantDB 前复权日K线 data/quantdb/1_kline_data/daily_forward/dt=YYYYMMDD/data.parquet
  └─ compute_limits 涨跌停 / T+1 / ST 剔除 / 停牌顺延
      ▼
回测引擎 → 研报 MD → md_to_pdf_report.py → PDF → 落盘股票报告目录
```

## ⚠️ 核心陷阱（每个都实测踩过）

| 陷阱 | 正确做法 |
|------|---------|
| Huntly `connected_at` 是上海本地时间字符串 | `datetime.strptime(s, "%Y-%m-%d %H:%M:%S.%f").replace(tzinfo=SHANGHAI_TZ)`，不能用 UTC |
| 做空权益计算 | `equity = cash + (cost - close) * shares`，不是 `cash - close * shares`（曾因算错虚增 +516%） |
| 做空现金流 | 开仓 **加** 现金（收钱），平仓 **减** 现金（买回）；与做多相反 |
| 回测循环必须遍历所有交易日 | 只遍历信号日会漏掉持仓的每日止损/止盈检查（持仓 30+ 天无检查的 bug） |
| 消息日期需对齐交易日历 | 用 `bisect` 找下一交易日；盘中消息才当天成交 |
| 同股同日多篇文章 | 取绝对分值最高的一篇作为当日信号 |
| 回测期市场环境 | 2026-03~08 是下行/震荡市，T+15 后大盘 beta 主导，情绪效应 15 天内耗尽 |

## 执行流程

### 第 1 步：事件研究（消息出来后股价怎么走？）

```bash
docker exec quantmind python3 /app/scripts/backtest_news_event_study.py
```

输出：利好/利空 T+0~T+20 平均累计收益曲线、胜率曲线、板块差异、强/弱信号对比、T+5 收益分布（分位数+盈亏比）。

**关键口径**：
- 利空预测力 > 利好（强利空 T+5 -2.39% vs 强利好 -0.17%）
- 利好效应 T+1~T+3 最强，T+15 耗尽
- 利好分布右偏（均值 +0.15% / 中位数 -1.05%），少数大牛股拉高均值 → 动态止盈适配

### 第 2 步：七维深度分析（找规律）

```bash
docker exec quantmind python3 /app/scripts/backtest_news_deep_analysis.py
```

| 维度 | 分析方法 | 实测发现 |
|------|---------|---------|
| 来源预测力 | 利好T+5 − 利空T+5，按来源分组 | 财联社 +5.26% 最强；南华早报 -3.40% 反向 |
| 时段特征 | 按小时分组利好 T+5 | 21点 +1.27% 黄金；凌晨1-5点 -1~-2% 噪声 |
| 多篇集中 | 单篇 vs 2篇+ vs 3篇+ | 3篇+ 利好 +0.80% = 单篇 2.2 倍 |
| 首日动量 | 消息日涨跌 → 后续 T+5/T+10 | 首日涨>3% 后续 +0.58%；首日跌继续跌 |
| 情绪反转 | 利好→利空 / 利空→利好 反转后走势 | 利好→利空反转 T+20 -6.23%，有效出场信号 |
| 事件标签 | 按 event_tags 分组 T+5 | 警示函利好+9.99%（样本小慎用）；监管利空 -2.67% 真实 |
| 连续信号 | 同股连续 1/2/3 天同向 | 连续3天 T+10 +0.63%，唯一全正组合 |

### 第 3 步：优化策略回测（融合规律）

```bash
docker exec quantmind python3 /app/scripts/backtest_news_optimized.py
```

**优化开关**（`scripts/backtest_news_optimized.py` 顶部，可独立控制每个优化项做消融实验）：

```python
ENABLE_SOURCE_FILTER = True      # 来源白/黑名单
ENABLE_TIME_FILTER = True        # 时段过滤
ENABLE_MULTI_CONFIRM = True      # 多篇确认 ≥2 篇同向
ENABLE_MOMENTUM_FILTER = True    # 首日动量（利好+涨/利空+跌才入场）
ENABLE_REVERSAL_EXIT = True      # 情绪反转出场
ENABLE_CONSECUTIVE_BOOST = True  # 连续3天同向 → 仓位 1.5x
ENABLE_TAG_BOOST = True          # 事件标签 → 仓位 1.3-1.5x
```

**参数寻优结论**（5 版本实测）：

| 版本 | 止损 | 过滤 | 收益 | Calmar |
|------|------|------|------|--------|
| v1 严格 | 15% | 全开 | +57.80% | 5.93 |
| v2 放宽 | 20% | 关多篇/动量 | +31.41% | 1.69 |
| **v3 最终** | **禁用** | 全开 | **+84.34%** | **7.76** |
| v4 中档 | 25% | 全开 | +39.72% | 4.17 |
| v5 激进止盈 | 禁用 | 全开 | +75.65% | 6.70 |

**铁律**：
1. **禁用固定止损**——所有版本止损出场 0% 胜率，新闻行情「先洗盘再拉升」
2. **动态止盈是唯一引擎**——盈利>15% 激活、回撤 5% 出场，100% 胜率
3. **多篇确认+首日动量贡献 53pp 收益**——关掉后 84%→31%
4. **止盈不能太敏感**——激活 10%/回撤 3% 反而不如 15%/5%（+75.7% vs +84.3%）
5. **到期浮盈续持，浮亏照离场**（P0 结论）——到期时赚钱的仓位继续持有到动态止盈兑现，亏钱的照常 20 天离场；数据上是 +105.35% vs 基线的 +54.70%，Calmar 12.76 vs 6.15（同数据快照）

### 第 4 步：研报生成与落盘

```bash
# 1) 手工撰写或脚本生成 MD（模板见 docs/news_sentiment_deep_report.md）
# 2) 容器内转 PDF（研报排版：深蓝封面+金色双线+斑马纹+红涨绿跌）
docker exec quantmind python3 /app/backend/scripts/md_to_pdf_report.py /tmp/report.md /tmp/report.pdf
# 3) 落盘前端可见目录（必做，只发 /tmp = 未交付）
docker cp report.md  quantmind:/data/reports/trading_agents/每日复盘/新闻情绪研究报告_$(date +%F).md
docker cp report.pdf quantmind:/data/reports/trading_agents/每日复盘/新闻情绪研究报告_$(date +%F).pdf
```

报告标准结构（13 章）：数据基础 → 事件研究 → 来源特征 → 时间特征 → 信号强度 → 价格行为 → 事件标签 → 策略回测（含 P0 升级 v6/hw40）→ 极端案例 → 规律清单 → 风险局限 → 结论 → **单股深度分析应用手册**。模板：`docs/news_sentiment_deep_report.md`（2026-08-21 升华版）。

### 第 5 步：单股新闻面三步纵深（stock-market-analysis 的 L7 层）

> 用户对**单只股票**做深度分析时，把本技能 21 条规律退化为「三步纵深」（详见 `docs/news_sentiment_deep_report.md` §13）。这不是本技能的完整回测流程，而是统计规律在单股的落地。

**① 直接消息判定** —— 窗口 `[T-2, T]` 内 Huntly 库标题 + 正文搜 `{股票名}/{code}`：
- 命中 → 来源（白名单财政联/同花顺？黑名单南华/彭博？）、时段（19-22 黄金？凌晨噪声）、多篇（≥2 同向→×2.2）、当天涨跌（首日动量双确认）
- **零命中 → 明确写「个股近期无直接催化」，禁止用行业新闻冒充个股消息**

**② 相关行业归类** —— 标题含行业词（超级电容/薄膜电容/电力设备等）的新闻按板块定性：
- 利好共振源（同行量产/业绩预增）vs 利空分化源（同行亏损/行业竞争叙事），写清"间接、板块级"

**③ 21 条规律对照打分** —— 按来源/时段/多篇/首日动量/反转/标签/板块逐条对位，输出**明确新闻面结论**（不许含混）。再与 L2 微观结构截面交叉（见 [[quantdb-full-analysis-design]] L4b）：

| 新闻 × L2 组合 | 含义 | 操作含义 |
|------|------|---------|
| 直接利空新闻 + L2 负IC族高位 | 事件驱动+盘面确认 | 强利空，回避/做空候选 |
| 无消息 + L2 缩量阴跌（大单流出收敛、买盘弱） | 资金惯性下行、无催化剂 | 左侧末段，勿接飞刀 |
| 直接利好 + L2 正IC族扩散（vpin_vol_ratio↑/informed↑） | 消息+知情资金共振 | 高置信做多候选 |
| 有利好但 L2 正IC族低位（无资金跟进） | 假利好 | 一日游，不追 |
| 无消息 + L2 vpin_vol_ratio 率先恢复 | 反转前兆 | 观察确认，等第二信号 |

（阈值：L2 负IC因子≥70% 分位 + 正IC因子≤40% = 负面组合；反之为正面组合。）

## 已验证的 21 条规律清单

| # | 规律 | 强度 | 落地方式 |
|---|------|------|---------|
| 1 | 财联社电报利空 → T+5 -6.57% | ★5 | 做空信号金矿 |
| 2 | 同花顺实时利好 → T+5 +5.19% | ★5 | 做多信号金矿 |
| 3 | 动态止盈（>15%激活/回撤5%）100% 胜率 | ★5 | 核心出场机制 |
| 4 | 固定止损 100% 亏损 | ★5 | 禁用固定止损 |
| 5 | 多篇（≥2）同向报道 → 信号强度 2.2x | ★4 | 入场过滤器 |
| 6 | 首日动量双确认 | ★4 | 入场过滤器 |
| 7 | 21点晚间消息利好 T+5 +1.27% | ★4 | 时段加权 |
| 8 | 凌晨 1-5 点消息为噪声 | ★4 | 时段过滤 |
| 9 | 强利空（≤-0.6）T+5 -2.39% | ★4 | 做空分值加权 |
| 10 | 连续 3 天同向信号 T+10 +0.63% | ★4 | 仓位加成 1.5x |
| 11 | 利好→利空反转 T+20 -6.23% | ★4 | 反转出场 |
| 12 | 沪主板利好 T+5 +0.49%（板块最优） | ★3 | 板块加权 |
| 13 | 深主板利空 T+5 -3.56%（做空首选） | ★3 | 做空选股 |
| 14 | 监管/立案调查利空真实有效 | ★3 | 事件标签加权 |
| 15 | 业绩预告/净利润增长利好有效 | ★3 | 事件标签加权 |
| 16 | 利好效应 T+3 内最强、T+15 耗尽 | ★3 | 持仓周期设计 |
| 17 | 南华早报/创业邦/彭博为反向指标 | ★3 | 黑名单 |
| 18 | 创业板利空无效（T+5 +0.67%） | ★3 | 禁止做空创业板 |

## 升级路线图（按优先级）

### P0：消除到期亏损 ✅ 已完成（2026-08-20）

25 笔 max_hold 出场贡献全部净亏损。实验了三条路线（9 个变体）：

| 路线 | 变体 | 结果 | 结论 |
|------|------|------|------|
| 缩短持仓 | mh15 / mh10 | +56.6% / -4.6% | ❌ 证伪：到期亏损是信号弱，不是持仓长 |
| MA5 提前离场 | ma5h10 / ma5h5 | +24.2% / +3.0% | ❌ 证伪：洗盘期全被踢出，ma5_exit 76 笔 -18.2 万 |
| **浮盈续持** | hw20 / hw40 / hw60 | +78.5% / +54.7% / **+105.4%** | ✅ **hw60 最优** |

**最终采纳 hw40**：到期（20 天）时浮盈仓位不卖，继续持有到动态止盈/情绪反转/绝对上限 60 天；浮亏仓位照常到期离场。同数据快照对比：**+105.35% / Calmar 12.76 vs 基线 +84.34% / 7.76**。

**续持上限单调性实验**（2026-08-20 同快照）：
```
续持上限:  0天(v3)  20天    40天    60天    80天
收益:     +84.3%  +78.5%  +105.3% +54.7%  +54.7%
回撤:     49.2%   47.7%   42.0%   26.6%   26.6%
Calmar:   7.76    7.20    12.76   7.79    7.79
```
- **曲线非单调**：hw40 是甜点，hw20 反而不如 v3（续持太短，多数赢家到期二次离场而非跑到止盈）
- **hw60/hw80 完全一致**（8 位小数）：60 天续持上限已是事实上的「无限期」，无仓位能活过 60 天
- **回撤随续持上限递减**：更长的续持减少「到期一刀切」的集中亏损，但收益在 hw40 后急剧塌方
- **续持 20 天不够**：hw20 的 7 笔续持中仅 2 笔跑到止盈；hw40 的 9 笔中 5 笔跑到止盈——赢家需要 30-50 天才能激活 +15% 止盈线

配套开关（`scripts/backtest_news_optimized.py`，默认已开启）：
```python
HOLD_WINNERS = True     # QM_HOLD_WINNERS 环境变量可关
MAX_EXTEND_DAYS = 60    # 续持上限（自入场日算总持仓 80 天）
```

**实验注意**：PG 富集表是活数据（情绪富集持续更新），不同时间跑回测输入会变（信号数曾差 16 个），对比变体必须在同一数据快照下完成。

### P1：动态来源权重

来源预测力会随时间漂移（媒体风格/受众结构变化）。改为：
- 每月滚动复测各来源预测力（用最近 60 个交易日事件）
- 白名单从静态集合改为 Top-N 动态入选
- 信号分值 = 情绪分 × 来源权重

### P2：做空现实化

当前假设无障碍做空。实盘化：
- 引入两融标的过滤（PG 查询 `margin_trading` 标记）
- 融券成本（年化 ~8%）计入做空持仓成本
- 北交所/科创板做空已剔除，继续剔除流动性不足标的

### P3：日内时间对齐精度

当前盘中消息统一按收盘价成交。升级：
- 盘中消息按「消息时刻 + 15 分钟」的分钟线价格成交（QuantDB 若有分钟线）
- 盘后消息按次日开盘价成交（当前已如此）
- 涨停板排队：开盘一字板挂单等开板的 pending 机制（参考 backtest_l2_year.py）

### P4：情绪模型升级

- FinBERT 中文金融微调数据增强（当前利空识别 58.7% > 利好 43.2%，可能含模型偏差）
- 加入标题/正文分离评分（标题情绪权重更高）
- 事件类型分类器（业绩/监管/合作/增减持）替代 event_tags 关键词

### P5：多市场扩展

- 港股/美股新闻源接入 Huntly（SKILL.md 已有架构，数据管线复用）
- 美股情绪模型需英文 FinBERT（当前是中文模型）
- 加密货币新闻源已有 QuantBC 数据平台，可先行试点

## 脚本清单

| 脚本 | 用途 | 输入 | 输出 |
|------|------|------|------|
| `scripts/backtest_news_event_study.py` | 事件研究 | Huntly+PG+QuantDB | T+0~T+20 收益曲线/胜率/板块/分布 |
| `scripts/backtest_news_deep_analysis.py` | 七维深度分析 | 同上+来源/标签/市值 | 8 个分析章节 |
| `scripts/backtest_news_sentiment.py` | 基线三模式回测 | 同上 | follow/fade/long_only 对比 |
| `scripts/backtest_news_optimized.py` | 优化策略回测 | 同上+优化开关 | 消融实验+最终策略 |
| `scripts/backtest_news_compare.py` | 三模式对比运行器 | 基线脚本 | 对比表 JSON |

所有脚本在容器内运行（本地 Python 缺 asyncpg）：
```bash
docker exec quantmind python3 /app/scripts/<script>.py
```
宿主机副本在 `scripts/`，容器内 `/app/scripts/`（挂载同步）。

## 报告模板

完整研报模板：`docs/news_sentiment_deep_report.md`（12 章结构，2026-08-20 版 13 页 PDF）。
复用时替换数据即可，章节结构不动。

## 关联技能

- [[news-sentiment-finbert]] — 情绪识别管线（FinBERT+词典融合的源头）
- [[quantdb-fields]] — QuantDB 字段单位速查（volume 股/amount 万元等陷阱）
- [[daily-review]] — 报告落盘「每日复盘」目录的路径规范
- [[model-train-infer-backtest-report]] — md_to_pdf_report.py 研报排版细节
- [[stock-market-analysis]] — 单股深分主技能（本技能是它的 L7 新闻层底座；L4b 订单微结构截面层底座 = `scripts/L2_微观结构因子系统化分析报告.md`）
- [[quantdb-full-analysis-design]] — 9 层个股深分框架（L7 三步纵深在此落地，含新闻×L2 交叉印证矩阵）

