feat: AI市场分析功能

- 后端:AI分析服务、工具调用、定时任务
- 前端:报告列表、详情页、Mermaid图表支持
- 支持OpenAI API兼容模型
- 收盘后自动分析生成报告
This commit is contained in:
Sakurasan
2026-09-01 04:21:29 +08:00
parent d7d019c2c4
commit 912a224b6b
17 changed files with 2525 additions and 4 deletions
+56
View File
@@ -0,0 +1,56 @@
"""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)