""" 종목코드 → 표시용 종목명 (Mattermost·로그·DB 공통). 키움 조건검색 실시간 응답에는 종목명이 없어 code=이름 임시값이 들어오는 경우가 많다. 우선순위: 유효 fallback → 메모리 캐시 → stock_meta → target_candidates_history → 잔고 prdt_name """ from __future__ import annotations import logging from typing import Dict, Optional logger = logging.getLogger(__name__) # 프로세스 내 재조회 방지 (매수체크 루프·체결 알림 공용) _NAME_CACHE: Dict[str, str] = {} def resolve_stock_display_name( db, code: str, fallback: str = "", *, holdings_map: Optional[Dict[str, Dict]] = None, cache_to_meta: bool = True, ) -> str: """ 종목코드에 대응하는 한글 종목명을 반환한다. Args: db: TradeDB / TradeDBExt 인스턴스 code: 6자리 종목코드 fallback: 전략·후보에서 넘어온 이름 (코드와 같으면 무시) holdings_map: {code: {name, qty, ...}} — OrderManager 잔고 캐시 등 cache_to_meta: history/잔고에서 찾은 이름을 stock_meta 에 저장 """ code = str(code or "").strip() if not code: return str(fallback or "").strip() fb = str(fallback or "").strip() if fb and fb != code: _NAME_CACHE[code] = fb return fb cached = _NAME_CACHE.get(code) if cached and cached != code: return cached # 1) stock_meta try: if hasattr(db, "get_stock_meta"): meta = db.get_stock_meta(code) if meta: n = str(meta.get("name") or "").strip() if n and n != code: _NAME_CACHE[code] = n return n except Exception as exc: logger.debug("get_stock_meta 실패(%s): %s", code, exc) # 2) target_candidates_history (조건검색 스냅샷 — 실매 후보 적재) try: conn = getattr(db, "conn", None) if conn is not None: row = conn.execute( "SELECT name FROM target_candidates_history " "WHERE code = %s AND name IS NOT NULL AND name != '' AND name != code " "ORDER BY COALESCE(event_time, scan_time) DESC, id DESC LIMIT 1", (code,), ).fetchone() if row: n = str(row.get("name") or "").strip() if n and n != code: _NAME_CACHE[code] = n if cache_to_meta and hasattr(db, "upsert_stock_meta"): try: db.upsert_stock_meta(code, name=n) except Exception: pass return n except Exception as exc: logger.debug("target_candidates_history 이름 조회 실패(%s): %s", code, exc) # 3) 실계좌 잔고 (보유 종목 prdt_name) if holdings_map: h = holdings_map.get(code) or {} n = str(h.get("name") or "").strip() if n and n != code: _NAME_CACHE[code] = n if cache_to_meta and hasattr(db, "upsert_stock_meta"): try: db.upsert_stock_meta(code, name=n) except Exception: pass return n return fb if fb else code