fix(HEL-356): complete Shenwan industry signal

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总管
2026-09-09 17:59:58 +08:00
co-authored by multica-agent
parent c3881af708
commit 88411efa1c
7 changed files with 151 additions and 18 deletions
+50 -10
View File
@@ -197,17 +197,22 @@ def fetch_sector_quote(db: HubDB, code: str, expected_date: str = "") -> dict[st
if ts_code.isdigit():
ts_code = f"{ts_code}.SI"
cache_key = f"sector:{ts_code}"
canonical_name = _canonical_sw_name(db, ts_code)
cached = _read_cache(db, cache_key)
if cached is not None:
if cached is not None and _sector_payload_matches(cached, canonical_name):
return cached
errors: list[str] = []
try:
row = EastmoneyAdapter().fetch_shenwan_quote(ts_code)
if not _sector_row_matches(row, canonical_name):
raise AdapterError(
f"industry name mismatch: expected {canonical_name}, got {row.get('name') or '--'}"
)
source = str(row.get("source") or "eastmoney_sw")
except Exception as exc:
errors.append(f"eastmoney:{exc}")
recovered = _load_quotes_lkg(db, cache_key, expected_date)
if recovered is not None:
if recovered is not None and _sector_payload_matches(recovered, canonical_name):
return recovered
raise RealtimeApiError(
"SOURCE_UNAVAILABLE",
@@ -217,7 +222,7 @@ def fetch_sector_quote(db: HubDB, code: str, expected_date: str = "") -> dict[st
quote_date = str(row.get("quote_date") or "")
if want and quote_date and quote_date != want:
recovered = _load_quotes_lkg(db, cache_key, want)
if recovered is not None:
if recovered is not None and _sector_payload_matches(recovered, canonical_name):
return recovered
raise RealtimeApiError("SOURCE_UNAVAILABLE", f"sector quote date {quote_date} != {want}")
payload = _envelope(
@@ -235,6 +240,29 @@ def fetch_sector_quote(db: HubDB, code: str, expected_date: str = "") -> dict[st
return payload
def _canonical_sw_name(db: HubDB, ts_code: str) -> str:
row = db.fetchone(
"SELECT name FROM sector_master WHERE ts_code = ? AND family = 'sw'",
(ts_code,),
)
if not row:
row = db.fetchone(
"SELECT name FROM eod_sector_daily WHERE ts_code = ? AND family = 'sw' "
"ORDER BY trade_date DESC LIMIT 1",
(ts_code,),
)
return str((row or {}).get("name") or "").strip()
def _sector_row_matches(row: dict[str, Any], canonical_name: str) -> bool:
return not canonical_name or str(row.get("name") or "").strip() == canonical_name
def _sector_payload_matches(payload: dict[str, Any], canonical_name: str) -> bool:
data = payload.get("data") if isinstance(payload, dict) else None
return isinstance(data, dict) and _sector_row_matches(data, canonical_name)
def fetch_limit_pool(db: HubDB, trade_date: str = "") -> dict[str, Any]:
day = yyyymmdd(trade_date or now_shanghai())
cache_key = f"limit-pool:{day}"
@@ -489,18 +517,29 @@ def warm_realtime(db: HubDB) -> dict[str, Any]:
try:
masters = db.fetchall(
"""
SELECT ts_code FROM sector_master WHERE family = 'sw'
UNION
SELECT ts_code FROM eod_sector_daily WHERE family = 'sw'
ORDER BY ts_code
SELECT ts_code, name, 0 AS priority FROM sector_master WHERE family = 'sw'
UNION ALL
SELECT ts_code, name, 1 AS priority FROM eod_sector_daily WHERE family = 'sw'
ORDER BY priority, ts_code
"""
)
codes = [str(row.get("ts_code") or "") for row in masters if row.get("ts_code")]
sector_rows = _eastmoney_sector_quotes(codes)
for row in sector_rows:
canonical_names: dict[str, str] = {}
for master in masters:
master_code = str(master.get("ts_code") or "")
master_name = str(master.get("name") or "").strip()
if master_code and master_name:
canonical_names.setdefault(master_code, master_name)
codes = list(canonical_names)
fetched_sector_rows = _eastmoney_sector_quotes(codes)
for row in fetched_sector_rows:
if _row_quote_date(row, today) != today:
continue
code = str(row.get("ts_code") or "").upper()
if not _sector_row_matches(row, canonical_names.get(code, "")):
result["errors"].append(
f"sector:{code}:industry name mismatch"
)
continue
payload = _envelope(
row,
{
@@ -513,6 +552,7 @@ def warm_realtime(db: HubDB) -> dict[str, Any]:
},
)
_write_cache(db, f"sector:{code}", payload, INDEX_TTL, "eastmoney_sw")
sector_rows.append(row)
result["sectors"] = len(sector_rows)
result["rows"] += len(sector_rows)
except Exception as exc: