feat(HEL-490): 剩余行情改由数据中枢主线路提供

正式页面以 8766 为主线路,旧接口只作故障备用;compose 钉死全部 DATAHUB_READ_*,避免现网残留 0 造成假完成。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总工
2026-09-08 12:03:30 +08:00
co-authored by Cursor multica-agent
parent 5d3465987d
commit 1c2f2ac057
24 changed files with 979 additions and 67 deletions
+54 -2
View File
@@ -186,7 +186,12 @@ class DashboardMixin:
previous_sectors = _build_sectors(previous_limits)
now = self._now()
market_status = _realtime_market_status(now.time().replace(tzinfo=None))
if quote_source == "eastmoney_clist":
if quote_source == "datahub":
notice = (
"盘中行情由数据中枢统一提供;涨停原因、封板时间和开板次数以盘后榜单校正为准。"
)
source_name = "datahub"
elif quote_source == "eastmoney_clist":
notice = (
"盘中行情由东财免费实时快照计算;涨停原因、封板时间和开板次数以盘后榜单校正为准。"
)
@@ -241,10 +246,16 @@ class DashboardMixin:
codes: str,
trade_date: str,
) -> tuple[list[dict[str, Any]], str]:
hub = getattr(self, "try_market_quotes", None)
if callable(hub):
quotes = hub(trade_date)
if quotes:
return list(quotes), "datahub"
rt_error = ""
try:
quotes = self.query("rt_k", {"ts_code": codes})
if quotes:
self._mark_quote_legacy("tushare_rt_k", rt_error)
return list(quotes), "tushare_rt_k"
rt_error = f"No realtime data returned for {trade_date}"
except TushareError as exc:
@@ -259,8 +270,14 @@ class DashboardMixin:
raise TushareError(
f"当天盘中实时行情不可用:rt_k={rt_error};免费源=empty"
)
self._mark_quote_legacy(quote_source, rt_error)
return quotes, quote_source
def _mark_quote_legacy(self, source: str, error: str = "") -> None:
marker = getattr(self, "record_datahub_legacy", None)
if callable(marker):
marker("quotes", source, error)
def _free_realtime_quotes(
self,
trade_date: str,
@@ -286,8 +303,18 @@ class DashboardMixin:
return quotes, "tencent_qt"
def _free_realtime_indices(self) -> list[dict[str, Any]]:
hub = getattr(self, "try_index_quotes", None)
if callable(hub):
rows = hub()
converted = [item for item in (_hub_index_quote(row) for row in rows or []) if item]
if converted:
return converted
try:
return self._realtime_aggregator().eastmoney_indices()
rows = self._realtime_aggregator().eastmoney_indices()
marker = getattr(self, "record_datahub_legacy", None)
if callable(marker):
marker("index_quotes", "eastmoney_push2")
return rows
except Exception:
return []
@@ -692,6 +719,31 @@ def _build_yesterday_performance(
return result
def _hub_index_quote(row: dict[str, Any]) -> dict[str, Any] | None:
ts_code = str(row.get("ts_code") or "")
code = str(row.get("code") or ts_code.split(".")[0])
close = _number(row.get("price") if row.get("price") not in (None, "") else row.get("close"))
previous = _number(
row.get("previous_close") if row.get("previous_close") not in (None, "") else row.get("pre_close")
)
if close <= 0 or previous <= 0:
return None
amount = _number(row.get("amount"))
amount_billion = _number(row.get("amount_billion"))
if not amount_billion and amount:
amount_billion = round(amount / 100_000_000, 2)
return {
"code": code,
"name": str(row.get("name") or code),
"price": close,
"change": _number(row.get("pct_chg") if row.get("pct_chg") not in (None, "") else row.get("change")),
"previous_close": previous,
"amount_billion": amount_billion,
"quote_time": str(row.get("quote_time") or ""),
"source": "datahub",
}
def _build_limit_performance(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
result = []
for level in sorted({int(row.get("prior_streak") or 1) for row in rows}, reverse=True):