feat: 题材热点历史页展示最近10个交易日题材涨幅矩阵

This commit is contained in:
Sakurasan
2026-08-27 20:18:51 +08:00
parent 57548c791d
commit 86d0dded3a
5 changed files with 218 additions and 1 deletions
+50 -1
View File
@@ -1,4 +1,4 @@
"""题材数据路由:题材列表、题材详情、题材相关股票"""
"""题材数据路由:题材列表、题材详情、题材相关股票、题材历史"""
from fastapi import APIRouter, Query, HTTPException
from fastapi.responses import JSONResponse
@@ -52,6 +52,55 @@ async def theme_history(date: str = Query(..., description="交易日 YYYY-MM-DD
conn.close()
@router.get("/active", summary="活跃题材 + 最近10日涨幅矩阵")
async def active_themes():
conn = get_connection()
try:
# 最近 10 个有数据的交易日(升序)
rows = conn.execute(
"SELECT DISTINCT trade_date FROM daily_top_themes ORDER BY trade_date DESC LIMIT 10"
).fetchall()
dates = [r["trade_date"] for r in reversed(rows)]
if not dates:
return JSONResponse({"dates": [], "themes": []}, headers=_NO_CACHE_HEADERS)
# 窗口内全部题材上榜记录,按天分组排列(当日 rank 即排名)
placeholders = ",".join("?" * len(dates))
rows = conn.execute(
f"""SELECT trade_date, theme_code, theme_name, bf3, rank FROM daily_top_themes
WHERE trade_date IN ({placeholders})
ORDER BY trade_date DESC, rank ASC""",
dates,
).fetchall()
# 按题材聚合:每日涨幅矩阵 + 上榜次数 + 最近上榜日 + 最佳排名
theme_map: dict[str, dict] = {}
for r in rows:
code = r["theme_code"]
t = theme_map.setdefault(code, {
"themeCode": code,
"themeName": r["theme_name"],
"dailyGains": {},
"appearCount": 0,
"lastAppear": None,
"bestRank": None,
})
t["dailyGains"][r["trade_date"]] = r["bf3"]
t["appearCount"] += 1
if t["lastAppear"] is None or r["trade_date"] > t["lastAppear"]:
t["lastAppear"] = r["trade_date"]
if t["bestRank"] is None or (r["rank"] or 0) < t["bestRank"]:
t["bestRank"] = r["rank"] or 0
themes_list = list(theme_map.values())
# 稳定排序:先按上榜次数降序,再按最佳排名升序
themes_list.sort(key=lambda x: x["bestRank"] if x["bestRank"] is not None else 10**9)
themes_list.sort(key=lambda x: -x["appearCount"])
return JSONResponse({"dates": dates, "themes": themes_list}, headers=_NO_CACHE_HEADERS)
finally:
conn.close()
@router.get("/{theme_code}/news", summary="题材相关新闻(分页)")
async def theme_news(
theme_code: str,