"""AI 分析定时任务 收盘后自动触发 AI 分析: - 15:01 collector_loop 采集核心股+题材数据 - 15:10 ai_analysis_loop 触发 AI 分析(等数据采集完成) """ import asyncio import traceback from datetime import datetime, time as dtime, timezone, timedelta from typing import Optional from database import get_connection _CST = timezone(timedelta(hours=8)) CHECK_INTERVAL_SECONDS = 300 # 每5分钟检查 AI_ANALYSIS_TIME = dtime(15, 10) # 15:10 后触发 def _is_trading_day(d: datetime) -> bool: """仅按工作日判断""" return d.weekday() < 5 def _has_ai_report(trade_date: str) -> bool: """检查某日是否已有 AI 分析报告""" conn = get_connection() try: row = conn.execute( "SELECT 1 FROM ai_reports WHERE trade_date = ? AND report_type = 'daily' LIMIT 1", (trade_date,) ).fetchone() return row is not None finally: conn.close() async def ai_analysis_loop(stop: Optional[asyncio.Event] = None) -> None: """后台循环:每个交易日 15:10 后自动触发 AI 分析(幂等)""" while True: try: now = datetime.now(_CST) if _is_trading_day(now) and now.time() >= AI_ANALYSIS_TIME: trade_date = now.strftime("%Y-%m-%d") if not _has_ai_report(trade_date): print(f"[ai-collector] 开始 AI 分析 {trade_date}") from services.ai_service import collect_ai_analysis result = await collect_ai_analysis(trade_date) print(f"[ai-collector] AI 分析完成 {trade_date},token 消耗: {result.get('tokens_used', 0)}") except Exception: print("[ai-collector] AI 分析异常:") traceback.print_exc() if stop is not None and stop.is_set(): break await asyncio.sleep(CHECK_INTERVAL_SECONDS)