This commit is contained in:
aaron 2026-04-28 11:37:21 +08:00
parent 294bf07841
commit bcd478f701
4 changed files with 83 additions and 6 deletions

View File

@ -56,8 +56,10 @@ async def intraday_market_temperature(prev_temp: MarketTemperature) -> MarketTem
down_count = sum(1 for q in eastmoney_quotes if q.get("pct_chg", 0) < 0)
limit_up_count = sum(1 for q in eastmoney_quotes if q.get("pct_chg", 0) >= _limit_threshold(q.get("ts_code", "")))
limit_down_count = sum(1 for q in eastmoney_quotes if q.get("pct_chg", 0) <= -_limit_threshold(q.get("ts_code", "")))
source = eastmoney_quotes[0].get("source", "eastmoney") if eastmoney_quotes else "eastmoney"
logger.info(
"东方财富实时市场温度: 上涨=%s 下跌=%s 涨停=%s 跌停=%s (共%s只)",
"%s实时市场温度: 上涨=%s 下跌=%s 涨停=%s 跌停=%s (共%s只)",
"腾讯兜底" if source == "tencent_fallback" else "东方财富",
up_count,
down_count,
limit_up_count,

View File

@ -31,6 +31,13 @@ SECTOR_HEADERS = {
}
def _describe_exception(exc: Exception) -> str:
text = str(exc).strip()
if text:
return f"{exc.__class__.__name__}: {text}"
return exc.__class__.__name__
def _ts_code_to_eastmoney(ts_code: str) -> str:
"""600519.SH -> 1.600519 (上海=1, 深圳=0)"""
code, market = ts_code.split(".")
@ -209,6 +216,7 @@ async def get_a_share_realtime_ranking(
"total_mv": _safe_float(item.get("f20")),
"circ_mv": _safe_float(item.get("f21")),
"main_net_inflow": _safe_float(item.get("f62")) or 0,
"source": "eastmoney",
})
if len(result) == before_count or len(items) < page_size_per_request:
break
@ -225,12 +233,79 @@ async def get_a_share_realtime_ranking(
logger.info("东方财富A股实时行情: 获取 %s", len(result))
return result
except Exception as e:
logger.error(f"东方财富A股实时行情获取失败: {e}")
await log_error(
"eastmoney",
f"东方财富A股实时行情获取失败: {e}",
detail=f"sort_by={sort_by}, page_size={page_size}",
reason = _describe_exception(e)
logger.warning("东方财富A股实时行情获取失败尝试腾讯兜底: %s", reason)
fallback = await _get_a_share_realtime_ranking_from_tencent(
sort_by=sort_by,
descending=descending,
page_size=page_size,
)
if fallback:
ttl = 60 if _is_trading_hours() else 300
cache.set(cache_key, fallback, ttl)
logger.warning("东方财富A股实时行情获取失败已切换腾讯兜底: %s", reason)
return fallback
logger.error("A股实时行情双源获取失败: %s", reason)
await log_error(
"market_data",
f"A股实时行情双源获取失败: {reason}",
detail=f"primary=eastmoney, fallback=tencent, sort_by={sort_by}, page_size={page_size}",
)
return []
async def _get_a_share_realtime_ranking_from_tencent(
sort_by: str,
descending: bool,
page_size: int,
) -> list[dict]:
"""东方财富失败时,用腾讯批量行情兜底全市场快照。"""
try:
from app.data.tushare_client import tushare_client
from app.data.tencent_client import get_realtime_quotes_batch
stock_basic = tushare_client.get_stock_basic()
if stock_basic.empty:
return []
ts_codes = stock_basic["ts_code"].dropna().astype(str).tolist()
quotes = await get_realtime_quotes_batch(ts_codes)
if not quotes:
return []
rows = []
for ts_code, quote in quotes.items():
if quote.price <= 0:
continue
rows.append({
"ts_code": ts_code,
"name": quote.name,
"price": quote.price,
"pct_chg": quote.pct_chg,
"amount": quote.amount,
"turnover_rate": quote.turnover_rate,
"pe": quote.pe,
"pb": quote.pb,
"total_mv": quote.total_mv,
"circ_mv": quote.circ_mv,
"main_net_inflow": 0,
"source": "tencent_fallback",
})
sort_key_map = {
"f3": "pct_chg",
"f6": "amount",
"f8": "turnover_rate",
"f20": "total_mv",
"f21": "circ_mv",
}
sort_key = sort_key_map.get(sort_by, "pct_chg")
rows.sort(key=lambda item: float(item.get(sort_key, 0) or 0), reverse=descending)
logger.info("腾讯兜底A股实时行情: 获取 %s", len(rows))
return rows[:page_size]
except Exception as e:
logger.warning("腾讯兜底A股实时行情失败: %s", _describe_exception(e))
return []

Binary file not shown.