astock-agent/backend/app/research/sector_agent.py
2026-06-10 08:36:25 +08:00

62 lines
2.2 KiB
Python

"""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, "观察期")