feat: 每日题材采集改为涨幅/强度/热度/成交额4榜各前50合并去重

原逻辑只取题材涨幅前20入库。现改为从 4 个榜单
(sortField 1=涨幅/3=强度/4=热度排名/5=成交额) 各取前50,
按 themeCode 合并去重后写入 daily_top_themes,
覆盖更全面的当日活跃题材。
This commit is contained in:
Sakurasan
2026-08-28 00:42:09 +08:00
parent 86d0dded3a
commit 82006f7cf9
+17 -5
View File
@@ -18,11 +18,15 @@ _CST = timezone(timedelta(hours=8))
CHECK_INTERVAL_SECONDS = 300
COLLECT_AFTER_TIME = dtime(15, 1) # 收盘后 15:01 开始允许采集(留 1 分钟等收盘数据稳定)
CORE_STOCK_LIMIT = 100 # 题材领涨股涨幅前100
TOP_THEME_LIMIT = 20 # 题材涨幅前20
RANK_TOP_LIMIT = 50 # 每个榜单(涨幅/强度/热度/成交额)取前50
HOTMAP_TOP_N = 100 # 热点穿透采样题材数:涨幅榜+热度榜各取前100,合并(与热点穿透页一致)
HOTMAP_CORE_LIMIT = 100 # 热点穿透核心股前100(按覆盖题材数降序)
CORE_COVER_THRESHOLD = 2 # 热点穿透核心股门槛:覆盖题材数 ≥2
# 题材榜单:sortField 1=涨幅(bf3) 3=强度(strengthValue) 4=热度排名(hotRank) 5=成交额(fex5)
# 每个榜单取前 RANK_TOP_LIMIT 个,按 themeCode 合并去重后入库
THEME_RANK_LISTS = ((1, "bf3"), (3, "strengthValue"), (4, "hotRank"), (5, "fex5"))
# 每日缓存清理:交易日 9:31 清空全部缓存,保证开盘后数据全新
CLEANUP_TIME = dtime(9, 31)
@@ -49,6 +53,7 @@ async def collect_daily(trade_date: str, dry_run: bool = False) -> dict:
"""采集指定交易日数据并入库。
核心股 = 题材领涨股涨幅前100 ∪ 热点穿透核心股(覆盖题材数≥2、按覆盖数降序前100),按股票代码去重。
题材 = 涨幅/强度/热度/成交额 4 榜各前50,按 themeCode 合并去重。
热点穿透构建失败时降级为仅领涨股前100,不影响当日采集。
Args:
@@ -107,8 +112,15 @@ async def collect_daily(trade_date: str, dry_run: bool = False) -> dict:
}
f3_core = sorted(stock_map.values(), key=lambda x: -(x["f3"] or 0))[:CORE_STOCK_LIMIT]
# 4. 题材涨幅前20:bf3 降序
top_themes = sorted(themes, key=lambda x: -(x.get("bf3") or 0))[:TOP_THEME_LIMIT]
# 4. 题材 4 榜(涨幅/强度/热度/成交额)各前50,按 themeCode 合并去重。
# 涨幅榜列表与开头用于构建领涨股映射的 fetch_theme_list(1, False) 同缓存,直接复用。
merged: dict[str, dict] = {}
rank_list = await fetch_theme_list(1, False)
for sort_field, _ in THEME_RANK_LISTS:
lst = rank_list if sort_field == 1 else await fetch_theme_list(sort_field, False)
for t in lst[:RANK_TOP_LIMIT]:
merged.setdefault(t["themeCode"], t)
top_themes = list(merged.values())
# 5. 合并去重:热点穿透核心股在前(覆盖数降序,rank 优先),随后补领涨股涨幅前100
core_stocks: list[dict] = []
@@ -145,7 +157,7 @@ async def collect_daily(trade_date: str, dry_run: bool = False) -> dict:
theme_pairs.add((code, tc, tn))
if dry_run:
print(f"[collector] {trade_date} 核心股 {len(core_stocks)} 只(热点穿透 {len(hotmap_core)} + 领涨股 {len(f3_core)}),题材前20 {len(top_themes)} 只")
print(f"[collector] {trade_date} 核心股 {len(core_stocks)} 只(热点穿透 {len(hotmap_core)} + 领涨股 {len(f3_core)}),题材 {len(top_themes)} 只(4 榜前 {RANK_TOP_LIMIT} 合并)")
return {"core_count": len(core_stocks), "theme_count": len(top_themes), "skipped": False}
# 6. 入库(事务,UNIQUE 幂等)
@@ -170,7 +182,7 @@ async def collect_daily(trade_date: str, dry_run: bool = False) -> dict:
finally:
conn.close()
print(f"[collector] {trade_date} 已采集:核心股 {len(core_stocks)} 只,题材前20 {len(top_themes)} 只")
print(f"[collector] {trade_date} 已采集:核心股 {len(core_stocks)} 只,题材 {len(top_themes)} 只(4 榜前 {RANK_TOP_LIMIT} 合并)")
return {"core_count": len(core_stocks), "theme_count": len(top_themes), "skipped": False}