@@ -0,0 +1,81 @@
|
||||
"""核心股历史接口:活跃核心股 + 指定日核心股/题材前10"""
|
||||
|
||||
from fastapi import APIRouter, Query
|
||||
from fastapi.responses import JSONResponse
|
||||
from database import get_connection, dict_from_row
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
_NO_CACHE_HEADERS = {"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0"}
|
||||
|
||||
|
||||
def _recent_trade_dates(conn, n: int = 10) -> list[str]:
|
||||
"""最近 n 个有数据的交易日(升序)"""
|
||||
rows = conn.execute(
|
||||
"SELECT DISTINCT trade_date FROM daily_core_stocks ORDER BY trade_date DESC LIMIT ?",
|
||||
(n,),
|
||||
).fetchall()
|
||||
return [r["trade_date"] for r in reversed(rows)]
|
||||
|
||||
|
||||
@router.get("/active", summary="活跃核心股 + 最近10日涨幅矩阵")
|
||||
async def active_core_stocks():
|
||||
conn = get_connection()
|
||||
try:
|
||||
dates = _recent_trade_dates(conn, 10)
|
||||
if not dates:
|
||||
return JSONResponse({"dates": [], "stocks": []}, headers=_NO_CACHE_HEADERS)
|
||||
|
||||
# 窗口内出现过且最近一次出现距今天数 <= 10 个交易日
|
||||
placeholders = ",".join("?" * len(dates))
|
||||
rows = conn.execute(
|
||||
f"""SELECT trade_date, stock_code, stock_name, f3 FROM daily_core_stocks
|
||||
WHERE trade_date IN ({placeholders})
|
||||
ORDER BY trade_date DESC, rank ASC""",
|
||||
dates,
|
||||
).fetchall()
|
||||
|
||||
# 组装 per-stock:每日涨幅 + 出现次数 + 最近上榜
|
||||
stock_days: dict[str, dict] = {}
|
||||
for r in rows:
|
||||
code = r["stock_code"]
|
||||
s = stock_days.setdefault(code, {
|
||||
"stockCode": code,
|
||||
"stockName": r["stock_name"],
|
||||
"dailyGains": {},
|
||||
"appearCount": 0,
|
||||
"lastAppear": None,
|
||||
})
|
||||
s["dailyGains"][r["trade_date"]] = r["f3"]
|
||||
s["appearCount"] += 1
|
||||
if s["lastAppear"] is None or r["trade_date"] > s["lastAppear"]:
|
||||
s["lastAppear"] = r["trade_date"]
|
||||
|
||||
stocks = list(stock_days.values())
|
||||
# 稳定排序:先按最近上榜日降序,再按出现次数降序
|
||||
stocks.sort(key=lambda x: x.get("lastAppear") or "", reverse=True)
|
||||
stocks.sort(key=lambda x: -x["appearCount"])
|
||||
return JSONResponse({"dates": dates, "stocks": stocks}, headers=_NO_CACHE_HEADERS)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/history", summary="指定交易日核心股(含所属题材)")
|
||||
async def core_stock_history(date: str = Query(..., description="交易日 YYYY-MM-DD")):
|
||||
conn = get_connection()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM daily_core_stocks WHERE trade_date = ? ORDER BY rank ASC", (date,)
|
||||
).fetchall()
|
||||
items = []
|
||||
for r in rows:
|
||||
d = dict_from_row(r)
|
||||
themes = conn.execute(
|
||||
"SELECT theme_code, theme_name FROM daily_core_stock_themes WHERE trade_date = ? AND stock_code = ?",
|
||||
(date, d["stock_code"]),
|
||||
).fetchall()
|
||||
d["themes"] = [dict(t) for t in themes]
|
||||
items.append(d)
|
||||
return JSONResponse({"date": date, "items": items}, headers=_NO_CACHE_HEADERS)
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user