tradingSystem/app/services/industry.py

89 lines
2.9 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""
行业划分接口 (设计 §5 的可插拔适配器)
======================================
IndustryClassifier.get(ts_code) -> 行业名 | None
数据源经参数 PMS_SECTOR_SOURCE 切换:
custom_table 自定义映射表 pms_industry_map (默认建议; 用户后续灌何种划分都只是灌数)
gp_stock_category 决策系统生态已有的行业表 (映射表就绪前的临时数据源)
""() 未配置 行业约束自动停用, 页面显著提示 (不静默放行也不误拦)
"""
from __future__ import annotations
import logging
import threading
import time
from app.repo import downstream_repo, pms_repo
from app.services import param_store
logger = logging.getLogger("pms.industry")
_cache = {"at": 0.0, "map": {}, "source": None}
_lock = threading.Lock()
CACHE_TTL = 300.0
def source() -> str:
return (param_store.get("PMS_SECTOR_SOURCE", "") or "").strip()
def ready() -> bool:
"""行业约束是否生效 (数据源已配置)。"""
return source() in ("custom_table", "gp_stock_category")
def status() -> dict:
src = source()
st = {"source": src, "ready": ready(), "count": 0,
"hint": "行业划分数据源未配置 —— 行业集中度硬拦截已自动停用, "
"行业类命令置灰 (设计 §5/§13)"}
if src == "custom_table":
try:
st["count"] = len(_load_custom())
st["hint"] = f"自定义映射表 pms_industry_map 已加载 {st['count']}"
except Exception as e:
st["ready"] = False
st["hint"] = f"映射表读取失败: {type(e).__name__}: {e}"
elif src == "gp_stock_category":
st["hint"] = "临时数据源 gp_stock_category (逐票查询, 建议尽快切 custom_table)"
return st
def _load_custom() -> dict:
now = time.time()
if _cache["source"] == "custom_table" and now - _cache["at"] < CACHE_TTL:
return _cache["map"]
with _lock:
rows = pms_repo.list_industry()
m = {r["ts_code"]: r["industry"] for r in rows}
_cache.update({"at": now, "map": m, "source": "custom_table"})
return m
def get(ts_code: str):
"""返回行业名; 未配置数据源或查不到 → None (调用方据此跳过行业约束)。"""
src = source()
if not ts_code or src not in ("custom_table", "gp_stock_category"):
return None
try:
if src == "custom_table":
return _load_custom().get(ts_code)
return downstream_repo.fetch_sector_from_category(ts_code)
except Exception as e:
logger.warning("行业查询失败 [%s]: %s", ts_code, e)
return None
def get_many(codes) -> dict:
src = source()
if src != "custom_table":
return {c: get(c) for c in (codes or [])}
m = _load_custom()
return {c: m.get(c) for c in (codes or [])}
def invalidate():
_cache["at"] = 0.0