Files
MoFin/docs/market-screening-pipeline.md
T

12 KiB
Raw Blame History

全市场潜力股筛选 - LLM调用流程与提示词文档

概述

本流程在收盘后(16:00)通过一个 LLM cron(市场精选推荐-每日)一次性完成。全程只有一个 LLM 入口:我(知微,deepseek-v4-flash 根据 cron prompt 的指令逐步执行。

数据采集层(market_watch.py)为 no_agent 脚本,不调 LLM,只拉 API 写数据库。


一、数据源准备(15:30no_agent,不调LLM

market_watch.py

对 A 股 90 个行业板块逐个拉取同花顺(akshare)数据,写入 mofin.db 两张表:

market_snapshots(每次采集一条):

  • timestamp(采集时间)
  • sourceths/eastmoney
  • up_ratio(上涨板块占比%
  • moodbullish/neutral/bearish

sector_snapshots(每条记录一个板块):

  • snapshot_id ← 关联 market_snapshots.id
  • name(板块名,如"半导体"
  • change_pct(涨跌幅%
  • up_count / down_count(涨跌家数)
  • net_inflow(资金净流入亿)
  • lead_stock / lead_stock_change(领涨股)

兼容说明source=eastmoney 时原始 change 是万分比(如 596 = 5.96%),需 ÷100source=ths 时已是百分比。


二、LLM 入口

2.1 定时触发

cron 任务: 市场精选推荐-每日
job_id: 759064f56c03
时间: 0 16 * * 1-5(交易日16:00
模型: deepseek-v4-flash
Tools: terminal, file, web, search

2.2 完整 Prompt

以下为 cron prompt 的完整内容(2026-06-20 更新,SQLite 版):

## 任务:每日全市场潜力股精选 + 星级推荐

收盘后执行。全部通过 mofin.db SQLite 读数据。

### 第1步:读数据

运行以下SQL获取数据:

sqlite3 /home/hmo/MoFin/data/mofin.db "SELECT ms.timestamp, ms.up_ratio, ms.mood, ss.name, ss.change_pct, ss.up_count, ss.down_count, ss.net_inflow, ss.lead_stock, ss.lead_stock_change FROM market_snapshots ms JOIN sector_snapshots ss ON ms.id=ss.snapshot_id WHERE ms.id=(SELECT MAX(id) FROM market_snapshots) ORDER BY ABS(ss.change_pct) DESC"

sqlite3 /home/hmo/MoFin/data/mofin.db "SELECT c.code, c.name, c.sector, c.reason, c.entry_range, c.stop_loss, c.target, c.zhiwei_star, c.promoted, c.dropped, (SELECT score FROM candidate_score_history WHERE code=c.code ORDER BY created_at DESC LIMIT 1) as latest_score FROM candidates c ORDER BY c.zhiwei_star DESC NULLS LAST"


### 第2步:全市场分析

用板块数据分析:
- 市场情绪(涨跌比、mood字段)
- 领涨行业(涨幅前5,看涨跌家数比、资金流入)
- 领跌行业(跌幅前3)
- 判断哪些板块是真趋势、哪些是一日游

### 第3步:筛选潜力股

从领涨行业中基于你对A股的了解,选出2-3只候选股。
用腾讯API查实时价:`curl -s --noproxy '*' "http://qt.gtimg.cn/q=sh{code}"` 或 `sz{code}`

每只给:评分1-10、推荐理由、入场区间、止损价、目标价

### 第4步:更新候选池

将本次结果与candidates表合并:
- 新候选 → INSERT(最新评分写入candidate_score_history
- 已有候选 → INSERT新的评分记录到candidate_score_history
- 连续3次评分下降 → candidates.trend_warning=true
- 平均分<5或7天未更新 → candidates.dropped=true

### 第5步:出推荐

从candidates中选最佳(未淘汰、未推荐过、最新评分>=7):
- 给星级写入candidates.zhiwei_star
- candidates.promoted=true

### 输出格式

最终回复三段式推送给老爸:
【📊 今日市场】判断/热门行业/风险行业
【⚡ 潜力股推荐】股票名(代码) ★星级 | 入场X~X | 止损X | 目标X | 理由
【📋 候选池状态】活跃X只,今日新增X只,已推荐X只

禁止:可关注、可考虑、建议观察、试试、谨慎关注、择机

三、执行细节

3.1 LLM 工具调用序列

顺序 工具 用途
1 terminal sqlite3 查 mofin.db 获取板块快照
2 terminal sqlite3 查 mofin.db 获取候选池
3 terminal curl 腾讯API 验证候选股实时价格
4 terminal sqlite3 INSERT INTO candidate_score_history
5 terminal sqlite3 UPDATE candidates SET zhiwei_star/promoted
6 最终回复 输出三段式报告

3.2 腾讯API调用示例

# 沪市股票
curl -s --noproxy '*' "http://qt.gtimg.cn/q=sh688981"
# 返回: v_sh688981="1~中芯国际~688981~140.50~..."
# 字段[3]=当前价, 字段[32]=涨跌幅

# 深市股票  
curl -s --noproxy '*' "http://qt.gtimg.cn/q=sz002371"

3.3 候选池治理规则

由 LLM 执行时自行判断:

  • 候选评分连续 3 次下降 → candidates.trend_warning=true
  • 近 3 次平均分 < 5 → candidates.dropped=true
  • 距上次更新超过 7 天 → candidates.dropped=true
  • dropped 的候选保留在池中供追溯,不再参与推荐

四、实时信号检测与小果情报处理(新增)

4.1 概述

在每30分的 market_watch 数据采集之外,增加一条实时信号处理链路:

market_watch(每30分)→ mofin.db
    │
    ▼
trend_detectorno_agent,每30分)
    │ SQL扫最新 snapshots → 发现异常信号
    │ 定位领涨股/成分股/持仓股/自选股
    │ 写入 sector_signals
    │
    ▼
小果情报处理(no_agent,每30分)
    │ 读未处理 signals
    │ curl 搜新闻(板块+个股+持仓+自选)
    │ 调本地 LLM 逐篇分析情感
    │ 写入 signal_news
    │
    ▼
知微(盘中即时 + 收盘汇总)
    │ 读 signal_news → 判断真伪
    │ 紧急利空 → 盘中推老爸
    │ 确认利好 → 更新 candidates
    │ 16:00 → 整合到每日推荐

4.2 trend_detector — 信号检测规则

# 每次运行检测以下6类信号:
# 1. 资金异动:单次净流入 > 近20次均值 + 3σ
# 2. 涨跌比反转:上涨占比从 <30% 跳到 >70%
# 3. 领涨股更替:领涨股与前2次采集不同
# 4. 趋势拐点:连续N次净流入 → 突然转流出
# 5. 量价背离:板块涨但资金流出 / 跌但资金流入
# 6. 普涨背离:板块大涨但上涨家数 <50%

检测到信号后,收集以下信息写入 sector_signals

  • signal_type, sector, severity (high/medium/low)
  • related_stocks — 该板块的领涨股+成分股(从 stock_sectors 表查)
  • holdings_in_sector — signal 板块中属于持仓的股票(查 holdings 表)
  • watchlist_in_sector — signal 板块中属于自选的股票(查 watchlist_stocks 表)
  • trigger_reason — 一句话触发原因

4.3 小果情报处理流程

trend_detector 完成后的下一步,由小果处理每一条未处理的 signal。

第1步:搜新闻 对小果来说,一条 signal 需要搜索的范围:

  • 板块层面:搜"板块名 + 行业/政策/走势"
  • 领涨股:本次 signal 的领涨股
  • related_stocks 中的每一只
  • holdings_in_sector 中的每一只(如有持仓股)
  • watchlist_in_sector 中的每一只(如有自选股)

搜索方式:curl 调百度/新浪公开新闻源,取标题(不要求全文)。

第2步:调小果本地 LLM 逐篇分析

对每篇新闻标题,小果本地 LLM 做:

  • 内容摘要(一段话,不限字数)
  • 情感分类:利好 / 利空 / 中性
  • 判断依据一句话

第3步:汇总(所有文章处理完后)

  • 总体情感判断
  • 一段简短的总结

写入 signal_news 表。

第4步:交知微盘中判断

signal_news 写入后,知微立即读取:

  • severity=high + sentiment=利空 → 盘中即时推送给老爸
  • 确认利好信号 → 更新 candidates(加候选或升星级)
  • 不确定的 → 标记待观察,累积到16:00汇总

4.4 小果 LLM 调用设计

模型: Qwen3.6-27B-OptiQ-4bit192.168.1.122:18003

每次调用内容:

输入:同一 signal 的 3-5 条新闻标题
任务:逐条分析(摘要 + 情感) + 总体判断

注意: 该模型会先输出思考过程再输出 JSON。JSON 在回复末尾,需从 response 中提取最后的完整 JSON 对象(跳过 thinking process 部分)。

节流规则:

  • 同一板块同一 signal 类型24小时内已有 signal_news 记录 → 跳过
  • 每次只处理未 processed 的 signals
  • 无未处理 signals → 本轮跳过

4.5 新增表结构

-- 信号表
CREATE TABLE IF NOT EXISTS sector_signals (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    signal_type TEXT NOT NULL,
    sector TEXT NOT NULL,
    severity TEXT DEFAULT 'medium',
    related_stocks TEXT,       -- JSON [{code, name, change_pct}]
    holdings_in_sector TEXT,   -- JSON,持仓股
    watchlist_in_sector TEXT,  -- JSON,自选股
    trigger_reason TEXT,
    snapshot_id INTEGER,       -- 触发的 snapshot
    processed INTEGER DEFAULT 0,
    detected_at TEXT DEFAULT (datetime('now','localtime'))
);

-- 小果情报表
CREATE TABLE IF NOT EXISTS signal_news (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    signal_id INTEGER REFERENCES sector_signals(id),
    sector TEXT NOT NULL,
    overall_sentiment TEXT,
    summary TEXT,
    key_articles TEXT,         -- JSON [{title, sentiment, summary, reason}]
    searched_stocks TEXT,      -- JSON,本次搜了哪些股
    created_at TEXT DEFAULT (datetime('now','localtime'))
);

五、完整数据流

┌────────────────────────────────────────────────────────┐
│ 15:30  数据采集层(no_agent                           │
│                                                       │
│ market_watch.py                                       │
│   → akshare 拉取同花顺90个行业板块                    │
│   → INSERT INTO market_snapshots + sector_snapshots   │
└──────────────────────┬─────────────────────────────────┘
                       │
                       ▼
┌────────────────────────────────────────────────────────┐
│ 16:00  LLM层(deepseek-v4-flash,单次cron调用)         │
│                                                       │
│ SELECT mofin.db 板块数据                                │
│   → 分析涨跌比 → 市场判断                               │
│   → 选热门行业 → 选危险行业                              │
│   → 腾讯API查实时价                                     │
│   → 筛选候选股                                          │
│   → INSERT评分历史 + UPDATE候选状态                      │
│   → 给最终星级 → 输出报告                               │
└──────────────────────┬─────────────────────────────────┘
                       │
                       ▼
                老爸收到三段式报告

六、数据库表结构

核心表

用途 关键字段
market_snapshots 每次采集元信息 id, timestamp, up_ratio, mood
sector_snapshots 板块快照 snapshot_id, name, change_pct, net_inflow
candidates 候选池 code, zhiwei_star, promoted, dropped
candidate_score_history 评分变更历史 code, score, source, created_at

关联查询示例

-- 最新板块排行
SELECT ss.name, ss.change_pct, ss.net_inflow, ss.up_count, ss.down_count, ss.lead_stock
FROM sector_snapshots ss
JOIN market_snapshots ms ON ss.snapshot_id = ms.id
WHERE ms.id = (SELECT MAX(id) FROM market_snapshots)
ORDER BY ABS(ss.change_pct) DESC;

-- 候选池最新评分
SELECT c.code, c.name, c.sector, c.zhiwei_star, c.promoted,
  (SELECT score FROM candidate_score_history
   WHERE code = c.code ORDER BY created_at DESC LIMIT 1) as latest_score
FROM candidates c
WHERE c.dropped = 0
ORDER BY c.zhiwei_star DESC NULLS LAST;

七、与其他管道的关系

管道 时间 关系
市场数据采集 (market_watch) 每30分 本管道的唯一数据源
市场精选推荐 (本管道) 16:00 依赖 market_watch 的最新一次写入
小果情感分析 16:00 独立管道,本管道可选参考
策略评估-每日 21:00 无关,独立评估持仓策略
知识萃取 16:30 本管道的输出可作为输入