"""Sector and theme research agent.""" from __future__ import annotations from typing import Any from app.research.industry_chain_agent import ( load_theme_chain_library, map_sector_to_chain, map_sector_to_chain_from_library, ) def build_theme_views(sectors: list[Any]) -> list[dict]: return _build_theme_views_with_mapper(sectors, map_sector_to_chain) async def build_theme_views_async(sectors: list[Any]) -> list[dict]: library = await load_theme_chain_library() def mapper(sector_name: str, leading_stocks: list[dict[str, Any]] | None = None) -> dict[str, Any]: return map_sector_to_chain_from_library(sector_name, leading_stocks, library) return _build_theme_views_with_mapper(sectors, mapper) def _build_theme_views_with_mapper(sectors: list[Any], mapper) -> list[dict]: views: list[dict] = [] for sector in sectors[:10]: pct = getattr(sector, "realtime_pct_change", None) if pct is None: pct = getattr(sector, "pct_change", 0) or 0 leading = getattr(sector, "leading_stocks_realtime", None) or getattr(sector, "leading_stocks", None) or [] chain = mapper(getattr(sector, "sector_name", ""), leading) stage = getattr(sector, "stage", "") or chain.get("stage") or "mid" heat = float(getattr(sector, "heat_score", 0) or 0) theme = chain["theme"] logic = chain["logic"] views.append({ "theme": theme, "raw_sector": getattr(sector, "sector_name", ""), "stage": stage, "heat_score": round(heat, 1), "pct_change": round(float(pct or 0), 2), "limit_up_count": int(getattr(sector, "limit_up_count", 0) or 0), "logic": logic, "chain_nodes": chain["chain_nodes"], "chain_items": chain.get("chain_items", []), "leader_stocks": leading[:5], "lifecycle_status": chain.get("lifecycle_status") or _lifecycle_label(stage), }) return views def _lifecycle_label(stage: str) -> str: return { "early": "启动期", "mid": "扩散期", "late": "后段", "end": "退潮", }.get(stage, "观察期")