- daily_collector TOP_THEME_LIMIT 10 → 20 - 同步 routes/collector 注释与 spec/plan 文档 - 实测 2026-08-10 题材前20入库 20 条,themes/history 返回 20 条 Co-Authored-By: Claude <noreply@anthropic.com>
6.4 KiB
6.4 KiB
每日热点核心股 / 题材历史记录 + 活跃核心股滚动表格
日期:2026-08-10
1. 目标
为数据分析和发掘积累历史数据,并提供活跃核心股的滚动展示:
- 每个交易日收盘后,采集核心股前 100(当日全部股票按涨幅降序取前 100)及其所属题材,保存历史。
- 每个交易日收盘后,采集题材(概念)板块涨幅前 20,保存历史。
- 新展示页:活跃核心股 × 最近 10 个 A 股交易日涨幅矩阵表格;新核心股加入,超过 10 个 A 股交易日未出现则踢出。
2. 已确认的决策
| 决策点 | 选择 |
|---|---|
| 核心股口径 | 当日全部股票按涨幅(f3)降序取前 100(不限覆盖题材数) |
| 板块口径 | 题材/概念板块,按涨幅(bf3)降序取前 20 |
| 采集触发 | 方案 A:asyncio 后台任务,每日收盘后自动采集 |
| 表格布局 | 股票 × 最近 10 个 A 股交易日列矩阵 |
| 10 日窗口 | 10 个 A 股交易日(跳过节假/周末) |
| 所属题材完整度 | 折中:以热点穿透采样题材为主,东财压力允许时尽力补全 |
3. 数据模型(新增 3 张表)
CREATE TABLE daily_core_stocks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
trade_date TEXT NOT NULL, -- 交易日 YYYY-MM-DD
stock_code TEXT NOT NULL, -- 股票代码
stock_name TEXT NOT NULL, -- 股票名称
f3 REAL, -- 当日涨幅%
cover_count INTEGER, -- 覆盖题材数(采样)
rank INTEGER, -- 当日涨幅排名 1-100
created_at TEXT DEFAULT (datetime('now','localtime')),
UNIQUE(trade_date, stock_code)
);
CREATE TABLE daily_core_stock_themes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
trade_date TEXT NOT NULL,
stock_code TEXT NOT NULL,
theme_code TEXT NOT NULL,
theme_name TEXT NOT NULL,
created_at TEXT DEFAULT (datetime('now','localtime')),
UNIQUE(trade_date, stock_code, theme_code)
);
CREATE TABLE daily_top_themes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
trade_date TEXT NOT NULL,
theme_code TEXT NOT NULL,
theme_name TEXT NOT NULL,
bf3 REAL, -- 题材涨幅%
hot_rank INTEGER, -- 热度排名
rank INTEGER, -- 当日板块涨幅排名 1-20
created_at TEXT DEFAULT (datetime('now','localtime')),
UNIQUE(trade_date, theme_code)
);
4. 采集服务 backend/services/daily_collector.py
4.1 触发机制(方案 A)
lifespan启动时拉起一个 asyncio 后台任务协程。- 协程循环(如每 5 分钟检查一次):
- 是否交易日(周一至周五,非节假日)。
- 是否收盘后(北京时间 > 15:00)。
- 当日数据是否已采集(按
trade_date查库,幂等去重)。 - 条件满足 → 触发采集。
4.2 采集逻辑
- 核心股前 100:调用
fetch_theme_list(1, False)或fetch_theme_graph得到当日全部股票,按f3降序取前 100。若不足 100 只,存实际数量。 - 所属题材:以热点穿透采样的
themeCodes为主存入daily_core_stock_themes。 - 题材前 20:从
fetch_theme_list(1, False)取bf3降序前 20,连同themeName/hotRank存入daily_top_themes。 - 同一交易日重复触发不重复写入(UNIQUE 去重 + 检查)。
- 采集失败(东财 403/网络)→ 跳过当日,下轮重试;记录日志。
4.3 补全(折中方案)
- 东财压力允许时,对核心股调用个股题材接口尽力补全。
- 优先保证核心股前 100 与题材前 20 的完整性,补全为附加增强,失败不影响主流程。
5. 新接口(backend/routes/)
| 接口 | 说明 |
|---|---|
GET /api/core-stocks/active |
活跃核心股 + 最近 10 日涨幅矩阵 |
GET /api/core-stocks/history?date= |
指定交易日的核心股(含所属题材) |
GET /api/themes/history?date= |
指定交易日的题材前 20 |
active 接口返回结构
{
"dates": ["2026-08-03", "...", "2026-08-10"],
"stocks": [
{
"stockCode": "601606",
"stockName": "长城军工",
"coverCount": 9,
"lastAppear": "2026-08-10",
"daysSinceLastAppear": 0,
"appearCount": 5,
"dailyGains": { "2026-08-03": 10.0, "2026-08-10": 10.0 }
}
]
}
dates:最近 10 个 A 股交易日(升序,最右为最新)。stocks:10 日窗口内出现过的活跃核心股。dailyGains:日期 → 当日涨幅;未上榜日无该键。
6. 新展示页(前端 /core-stocks)
6.1 页面结构
- 顶栏:返回、标题「核心股追踪」、刷新按钮(与
/hot-map一致风格)。 - 表格:股票 × 最近 10 个 A 股交易日列矩阵。
- 行:活跃核心股(10 个 A 股交易日内出现过),按
appearCount降序、lastAppear降序排列。 - 列:最近 10 个 A 股交易日,最右为最新。
- 单元格:当日涨幅(红涨绿跌,A 股惯例);未上榜留空(
·)。
- 行:活跃核心股(10 个 A 股交易日内出现过),按
- 每只股票显示累计出现次数、最近上榜日期、所属题材数。
6.2 数据获取
- 前端
useQuery调GET /api/core-stocks/active。 staleTime与题材页一致(30s 或 60s),盘中可手动刷新。
6.3 路由
- 新建
src/routes/core-stocks.tsx,路由/core-stocks。 - 从题材页
/themes和热点穿透页/hot-map顶部加入口链接。
7. 错误处理与边界
- 东财 403/采集失败:跳过当日采集,下轮重试;不影响已存历史。
- 当日重复采集:UNIQUE 约束 + 入库前检查,幂等。
- 核心股不足 100:存实际数量,不补齐。
- 无历史数据:部署后开始累积;active 接口在无数据时返回空
stocks与空dates。 - 交易日历:以自然周一到周五判定交易日(不处理法定节假日调休的深度历法),与现有
_is_trading_time一致。
8. 测试
- 采集服务:幂等(重复触发不重复写)、去重、失败重试逻辑。
- active 接口:窗口计算、踢出规则(>10 个交易日未出现不返回)、涨幅矩阵正确性。
- 前端页面:空态、有数据态、10 日窗口滚动。
9. 范围外(YAGNI)
- 不做法定的深度交易日历(节假日调休)。
- 不做个股涨幅的增量更新(历史数据一次性采集,之后不补更)。
- 不做板块成分股的每日存储。