1
This commit is contained in:
parent
294bf07841
commit
bcd478f701
Binary file not shown.
@ -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)
|
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_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", "")))
|
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(
|
logger.info(
|
||||||
"东方财富实时市场温度: 上涨=%s 下跌=%s 涨停=%s 跌停=%s (共%s只)",
|
"%s实时市场温度: 上涨=%s 下跌=%s 涨停=%s 跌停=%s (共%s只)",
|
||||||
|
"腾讯兜底" if source == "tencent_fallback" else "东方财富",
|
||||||
up_count,
|
up_count,
|
||||||
down_count,
|
down_count,
|
||||||
limit_up_count,
|
limit_up_count,
|
||||||
|
|||||||
@ -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:
|
def _ts_code_to_eastmoney(ts_code: str) -> str:
|
||||||
"""600519.SH -> 1.600519 (上海=1, 深圳=0)"""
|
"""600519.SH -> 1.600519 (上海=1, 深圳=0)"""
|
||||||
code, market = ts_code.split(".")
|
code, market = ts_code.split(".")
|
||||||
@ -209,6 +216,7 @@ async def get_a_share_realtime_ranking(
|
|||||||
"total_mv": _safe_float(item.get("f20")),
|
"total_mv": _safe_float(item.get("f20")),
|
||||||
"circ_mv": _safe_float(item.get("f21")),
|
"circ_mv": _safe_float(item.get("f21")),
|
||||||
"main_net_inflow": _safe_float(item.get("f62")) or 0,
|
"main_net_inflow": _safe_float(item.get("f62")) or 0,
|
||||||
|
"source": "eastmoney",
|
||||||
})
|
})
|
||||||
if len(result) == before_count or len(items) < page_size_per_request:
|
if len(result) == before_count or len(items) < page_size_per_request:
|
||||||
break
|
break
|
||||||
@ -225,12 +233,79 @@ async def get_a_share_realtime_ranking(
|
|||||||
logger.info("东方财富A股实时行情: 获取 %s 只", len(result))
|
logger.info("东方财富A股实时行情: 获取 %s 只", len(result))
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"东方财富A股实时行情获取失败: {e}")
|
reason = _describe_exception(e)
|
||||||
await log_error(
|
logger.warning("东方财富A股实时行情获取失败,尝试腾讯兜底: %s", reason)
|
||||||
"eastmoney",
|
fallback = await _get_a_share_realtime_ranking_from_tencent(
|
||||||
f"东方财富A股实时行情获取失败: {e}",
|
sort_by=sort_by,
|
||||||
detail=f"sort_by={sort_by}, page_size={page_size}",
|
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 []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user