From 75c7ff3670625eec1d145c9b52dd4d3730e0adeb Mon Sep 17 00:00:00 2001 From: Sakurasan <26715255+Sakurasan@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:20:11 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=AF=8F=E6=97=A5=E7=83=AD=E7=82=B9?= =?UTF-8?q?=E6=A0=B8=E5=BF=83=E8=82=A1/=E9=A2=98=E6=9D=90=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=AE=B0=E5=BD=95=20+=20=E6=B4=BB=E8=B7=83=E6=A0=B8?= =?UTF-8?q?=E5=BF=83=E8=82=A1=E6=BB=9A=E5=8A=A8=E8=A1=A8=E6=A0=BC=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 每日采集核心股前100(按涨幅)+所属题材,题材涨幅前10,存历史 - asyncio 后台定时采集,幂等去重 - 新页面:股票×最近10个A股交易日涨幅矩阵,超10日未出现踢出 Co-Authored-By: Claude --- ...6-08-10-daily-core-stock-history-design.md | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-10-daily-core-stock-history-design.md diff --git a/docs/superpowers/specs/2026-08-10-daily-core-stock-history-design.md b/docs/superpowers/specs/2026-08-10-daily-core-stock-history-design.md new file mode 100644 index 0000000..8f8dac4 --- /dev/null +++ b/docs/superpowers/specs/2026-08-10-daily-core-stock-history-design.md @@ -0,0 +1,156 @@ +# 每日热点核心股 / 题材历史记录 + 活跃核心股滚动表格 + +日期:2026-08-10 + +## 1. 目标 + +为数据分析和发掘积累历史数据,并提供活跃核心股的滚动展示: + +1. 每个交易日收盘后,采集**核心股前 100**(当日全部股票按涨幅降序取前 100)及其**所属题材**,保存历史。 +2. 每个交易日收盘后,采集**题材(概念)板块涨幅前 10**,保存历史。 +3. 新展示页:**活跃核心股 × 最近 10 个 A 股交易日**涨幅矩阵表格;新核心股加入,**超过 10 个 A 股交易日未出现则踢出**。 + +## 2. 已确认的决策 + +| 决策点 | 选择 | +|---|---| +| 核心股口径 | 当日全部股票按涨幅(f3)降序取前 100(不限覆盖题材数) | +| 板块口径 | 题材/概念板块,按涨幅(bf3)降序取前 10 | +| 采集触发 | 方案 A:asyncio 后台任务,每日收盘后自动采集 | +| 表格布局 | 股票 × 最近 10 个 A 股交易日列矩阵 | +| 10 日窗口 | 10 个 A 股交易日(跳过节假/周末) | +| 所属题材完整度 | 折中:以热点穿透采样题材为主,东财压力允许时尽力补全 | + +## 3. 数据模型(新增 3 张表) + +```sql +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-10 + 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 采集逻辑 + +1. **核心股前 100**:调用 `fetch_theme_list(1, False)` 或 `fetch_theme_graph` 得到当日全部股票,按 `f3` 降序取前 100。若不足 100 只,存实际数量。 +2. **所属题材**:以热点穿透采样的 `themeCodes` 为主存入 `daily_core_stock_themes`。 +3. **题材前 10**:从 `fetch_theme_list(1, False)` 取 `bf3` 降序前 10,连同 `themeName`/`hotRank` 存入 `daily_top_themes`。 +4. 同一交易日重复触发不重复写入(UNIQUE 去重 + 检查)。 +5. 采集失败(东财 403/网络)→ 跳过当日,下轮重试;记录日志。 + +### 4.3 补全(折中方案) + +- 东财压力允许时,对核心股调用个股题材接口尽力补全。 +- 优先保证核心股前 100 与题材前 10 的完整性,补全为附加增强,失败不影响主流程。 + +## 5. 新接口(`backend/routes/`) + +| 接口 | 说明 | +|---|---| +| `GET /api/core-stocks/active` | 活跃核心股 + 最近 10 日涨幅矩阵 | +| `GET /api/core-stocks/history?date=` | 指定交易日的核心股(含所属题材) | +| `GET /api/themes/history?date=` | 指定交易日的题材前 10 | + +### active 接口返回结构 + +```json +{ + "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 股惯例);未上榜留空(`·`)。 +- 每只股票显示累计出现次数、最近上榜日期、所属题材数。 + +### 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) + +- 不做法定的深度交易日历(节假日调休)。 +- 不做个股涨幅的增量更新(历史数据一次性采集,之后不补更)。 +- 不做板块成分股的每日存储。