diff --git a/Dockerfile b/Dockerfile
index 9768d7f..0ec1a64 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# 使用官方Python镜像作为基础镜像
-FROM python:3.12-slim
+FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/python:3.12-slim
# 设置工作目录
WORKDIR /app
diff --git a/app.py b/app.py
index 8d960ea..e560555 100644
--- a/app.py
+++ b/app.py
@@ -17,6 +17,7 @@ from monitor_service import monitor_service
from notification_service import notification_service
from config_manager import config_manager
from main_force_ui import display_main_force_selector
+from sector_strategy_ui import display_sector_strategy
# 页面配置
st.set_page_config(
@@ -308,6 +309,19 @@ def main():
del st.session_state.show_monitor
if 'show_config' in st.session_state:
del st.session_state.show_config
+ if 'show_sector_strategy' in st.session_state:
+ del st.session_state.show_sector_strategy
+
+ if st.button("🎯 智策板块", use_container_width=True, key="nav_sector_strategy"):
+ st.session_state.show_sector_strategy = True
+ if 'show_history' in st.session_state:
+ del st.session_state.show_history
+ if 'show_monitor' in st.session_state:
+ del st.session_state.show_monitor
+ if 'show_config' in st.session_state:
+ del st.session_state.show_config
+ if 'show_main_force' in st.session_state:
+ del st.session_state.show_main_force
if st.button("🏠 返回首页", use_container_width=True, key="nav_home"):
if 'show_history' in st.session_state:
@@ -318,6 +332,8 @@ def main():
del st.session_state.show_config
if 'show_main_force' in st.session_state:
del st.session_state.show_main_force
+ if 'show_sector_strategy' in st.session_state:
+ del st.session_state.show_sector_strategy
if st.button("⚙️ 环境配置", use_container_width=True, key="nav_config"):
st.session_state.show_config = True
@@ -389,6 +405,7 @@ def main():
**功能说明**
- **智能分析**:AI团队深度分析
- **主力选股**:主力资金精选标的
+ - **智策板块**:AI板块策略分析
- **实时监测**:价格监控与提醒
- **历史记录**:查看分析历史
@@ -414,6 +431,11 @@ def main():
display_main_force_selector()
return
+ # 检查是否显示智策板块
+ if 'show_sector_strategy' in st.session_state and st.session_state.show_sector_strategy:
+ display_sector_strategy()
+ return
+
# 检查是否显示环境配置
if 'show_config' in st.session_state and st.session_state.show_config:
display_config_manager()
diff --git a/sector_strategy_agents.py b/sector_strategy_agents.py
new file mode 100644
index 0000000..6383ba9
--- /dev/null
+++ b/sector_strategy_agents.py
@@ -0,0 +1,547 @@
+"""
+智策AI智能体分析集群
+包含四个专业分析师智能体
+"""
+
+from deepseek_client import DeepSeekClient
+from typing import Dict, Any
+import time
+
+
+class SectorStrategyAgents:
+ """板块策略AI智能体集合"""
+
+ def __init__(self, model="deepseek-chat"):
+ self.model = model
+ self.deepseek_client = DeepSeekClient(model=model)
+ print(f"[智策] AI智能体系统初始化 (模型: {model})")
+
+ def macro_strategist_agent(self, market_data: Dict, news_data: list) -> Dict[str, Any]:
+ """
+ 宏观策略师 - 分析宏观经济和新闻对板块的影响
+
+ 职责:
+ - 分析国际国内新闻和宏观经济数据
+ - 判断对整体市场和不同板块的潜在影响
+ - 识别政策导向和宏观趋势
+ """
+ print("🌐 宏观策略师正在分析...")
+ time.sleep(1)
+
+ # 构建新闻摘要
+ news_summary = ""
+ if news_data:
+ news_summary = "\n【重要财经新闻】\n"
+ for idx, news in enumerate(news_data[:30], 1):
+ news_summary += f"{idx}. [{news.get('publish_time', '')}] {news.get('title', '')}\n"
+ if news.get('content'):
+ news_summary += f" 摘要: {news['content'][:200]}...\n"
+
+ # 构建市场概况
+ market_summary = ""
+ if market_data:
+ market_summary = f"""
+【市场概况】
+大盘指数:
+"""
+ if market_data.get("sh_index"):
+ sh = market_data["sh_index"]
+ market_summary += f" 上证指数: {sh['close']} ({sh['change_pct']:+.2f}%)\n"
+ if market_data.get("sz_index"):
+ sz = market_data["sz_index"]
+ market_summary += f" 深证成指: {sz['close']} ({sz['change_pct']:+.2f}%)\n"
+ if market_data.get("cyb_index"):
+ cyb = market_data["cyb_index"]
+ market_summary += f" 创业板指: {cyb['close']} ({cyb['change_pct']:+.2f}%)\n"
+
+ if market_data.get("total_stocks"):
+ market_summary += f"""
+市场涨跌统计:
+ 上涨: {market_data['up_count']} ({market_data['up_ratio']:.1f}%)
+ 下跌: {market_data['down_count']}
+ 涨停: {market_data['limit_up']} | 跌停: {market_data['limit_down']}
+"""
+
+ prompt = f"""
+你是一名资深的宏观策略分析师,拥有10年以上的市场研究经验,擅长从宏观经济和政策新闻中洞察市场趋势。
+
+{market_summary}
+{news_summary}
+
+请基于以上信息,从宏观角度进行深度分析:
+
+1. **宏观环境评估**
+ - 当前宏观经济形势判断(经济周期位置)
+ - 政策环境分析(货币政策、财政政策倾向)
+ - 国际环境影响(地缘政治、全球经济)
+ - 市场整体风险偏好评估
+
+2. **新闻事件影响分析**
+ - 识别对市场影响最大的3-5条重要新闻
+ - 分析新闻的性质(利好/利空/中性)和影响范围
+ - 判断新闻对不同板块的差异化影响
+ - 识别政策导向和行业扶持重点
+
+3. **行业板块影响预判**
+ - 分析哪些板块受宏观环境影响最积极(看多)
+ - 分析哪些板块面临宏观压力(看空)
+ - 识别政策支持的重点行业
+ - 预判资金可能流向的板块
+
+4. **市场情绪和节奏**
+ - 当前市场情绪状态(恐慌/谨慎/乐观/亢奋)
+ - 大盘趋势判断(上涨/震荡/下跌)
+ - 市场参与热情(活跃度、成交量)
+ - 风险偏好变化趋势
+
+5. **投资策略建议**
+ - 当前宏观环境下的配置思路
+ - 建议重点关注的板块(3-5个)
+ - 建议规避的板块(2-3个)
+ - 仓位管理建议
+
+请给出专业、深入的宏观策略分析报告。
+"""
+
+ messages = [
+ {"role": "system", "content": "你是一名资深的宏观策略分析师,擅长从宏观经济、政策和新闻事件中把握市场脉搏。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ analysis = self.deepseek_client.call_api(messages, max_tokens=4000)
+
+ print(" ✓ 宏观策略师分析完成")
+
+ return {
+ "agent_name": "宏观策略师",
+ "agent_role": "分析宏观经济、政策导向、新闻事件对市场和板块的影响",
+ "analysis": analysis,
+ "focus_areas": ["宏观经济", "政策解读", "新闻事件", "市场情绪", "行业轮动"],
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
+ }
+
+ def sector_diagnostician_agent(self, sectors_data: Dict, concepts_data: Dict, market_data: Dict) -> Dict[str, Any]:
+ """
+ 板块诊断师 - 分析板块的走势、估值和基本面
+
+ 职责:
+ - 深入分析特定板块的历史走势
+ - 评估板块的估值水平
+ - 分析板块的成长性和基本面因素
+ """
+ print("📊 板块诊断师正在分析...")
+ time.sleep(1)
+
+ # 构建行业板块数据
+ sector_summary = ""
+ if sectors_data:
+ sorted_sectors = sorted(sectors_data.items(), key=lambda x: x[1]["change_pct"], reverse=True)
+
+ sector_summary = f"""
+【行业板块表现】(共 {len(sectors_data)} 个板块)
+
+涨幅榜 TOP15:
+"""
+ for idx, (name, info) in enumerate(sorted_sectors[:15], 1):
+ sector_summary += f"{idx}. {name}: {info['change_pct']:+.2f}% | 换手率: {info['turnover']:.2f}% | 领涨股: {info['top_stock']} ({info['top_stock_change']:+.2f}%) | 涨跌家数: {info['up_count']}/{info['down_count']}\n"
+
+ sector_summary += f"""
+跌幅榜 TOP10:
+"""
+ for idx, (name, info) in enumerate(sorted_sectors[-10:], 1):
+ sector_summary += f"{idx}. {name}: {info['change_pct']:+.2f}% | 换手率: {info['turnover']:.2f}% | 领跌股: {info['top_stock']} ({info['top_stock_change']:+.2f}%) | 涨跌家数: {info['up_count']}/{info['down_count']}\n"
+
+ # 构建概念板块数据
+ concept_summary = ""
+ if concepts_data:
+ sorted_concepts = sorted(concepts_data.items(), key=lambda x: x[1]["change_pct"], reverse=True)
+
+ concept_summary = f"""
+【概念板块表现】(共 {len(concepts_data)} 个板块)
+
+热门概念 TOP15:
+"""
+ for idx, (name, info) in enumerate(sorted_concepts[:15], 1):
+ concept_summary += f"{idx}. {name}: {info['change_pct']:+.2f}% | 换手率: {info['turnover']:.2f}% | 领涨股: {info['top_stock']} ({info['top_stock_change']:+.2f}%)\n"
+
+ prompt = f"""
+你是一名资深的板块分析师,具有CFA资格和深厚的行业研究背景,擅长板块诊断和趋势判断。
+
+【市场环境】
+{self._format_market_overview(market_data)}
+
+{sector_summary}
+
+{concept_summary}
+
+请基于以上数据,进行专业的板块诊断分析:
+
+1. **板块强弱分析**
+ - 识别当前最强势的5个板块(涨幅、换手率、领涨股表现综合考虑)
+ - 识别当前最弱势的3个板块
+ - 分析板块强弱的内在逻辑(基本面、资金面、情绪面)
+ - 判断强势板块的持续性
+
+2. **板块估值与位置**
+ - 评估热门板块的估值合理性
+ - 判断板块所处的位置(启动期/加速期/高位/调整期)
+ - 识别估值洼地(低估且有潜力的板块)
+ - 提示估值泡沫风险
+
+3. **板块轮动特征**
+ - 分析当前的板块轮动特征
+ - 识别资金轮动的方向和节奏
+ - 判断是否存在明显的板块切换信号
+ - 预判下一个可能轮动的板块
+
+4. **成长性与基本面**
+ - 分析强势板块的成长驱动因素
+ - 评估板块的中长期发展前景
+ - 识别具有持续成长潜力的板块
+ - 提示基本面恶化的风险板块
+
+5. **技术形态分析**
+ - 分析板块的技术走势特征
+ - 识别突破、整理、调整等形态
+ - 判断技术面的支撑和阻力
+ - 提供技术性买卖点参考
+
+6. **投资建议**
+ - 推荐3-5个值得关注的板块(多头方向)
+ - 提示2-3个需要规避的板块(空头方向)
+ - 给出每个板块的投资逻辑和风险提示
+ - 建议配置比例和持有周期
+
+请给出专业、详细的板块诊断报告。
+"""
+
+ messages = [
+ {"role": "system", "content": "你是一名资深的板块分析师,擅长板块趋势判断和投资价值评估。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ analysis = self.deepseek_client.call_api(messages, max_tokens=4000)
+
+ print(" ✓ 板块诊断师分析完成")
+
+ return {
+ "agent_name": "板块诊断师",
+ "agent_role": "深入分析板块走势、估值水平、基本面因素和成长性",
+ "analysis": analysis,
+ "focus_areas": ["板块走势", "估值分析", "基本面", "技术形态", "板块轮动"],
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
+ }
+
+ def fund_flow_analyst_agent(self, fund_flow_data: Dict, north_flow_data: Dict, sectors_data: Dict) -> Dict[str, Any]:
+ """
+ 资金流向分析师 - 分析板块资金流向和主力行为
+
+ 职责:
+ - 实时跟踪主力资金在板块间的流动
+ - 分析北向资金的板块偏好
+ - 判断资金进攻或撤离的方向
+ """
+ print("💰 资金流向分析师正在分析...")
+ time.sleep(1)
+
+ # 构建资金流向数据
+ fund_flow_summary = ""
+ if fund_flow_data and fund_flow_data.get("today"):
+ flow_list = fund_flow_data["today"]
+
+ # 净流入前15
+ sorted_inflow = sorted(flow_list, key=lambda x: x["main_net_inflow"], reverse=True)
+ fund_flow_summary = f"""
+【板块资金流向】(更新时间: {fund_flow_data.get('update_time', 'N/A')})
+
+主力资金净流入 TOP15:
+"""
+ for idx, item in enumerate(sorted_inflow[:15], 1):
+ fund_flow_summary += f"{idx}. {item['sector']}: {item['main_net_inflow']:.2f}万 ({item['main_net_inflow_pct']:+.2f}%) | 涨跌: {item['change_pct']:+.2f}% | 超大单: {item['super_large_net_inflow']:.2f}万\n"
+
+ # 净流出前10
+ sorted_outflow = sorted(flow_list, key=lambda x: x["main_net_inflow"])
+ fund_flow_summary += f"""
+主力资金净流出 TOP10:
+"""
+ for idx, item in enumerate(sorted_outflow[:10], 1):
+ fund_flow_summary += f"{idx}. {item['sector']}: {item['main_net_inflow']:.2f}万 ({item['main_net_inflow_pct']:+.2f}%) | 涨跌: {item['change_pct']:+.2f}%\n"
+
+ # 构建北向资金数据
+ north_summary = ""
+ if north_flow_data:
+ north_summary = f"""
+【北向资金】
+日期: {north_flow_data.get('date', 'N/A')}
+今日北向资金净流入: {north_flow_data.get('north_net_inflow', 0):.2f} 万元
+ 沪股通净流入: {north_flow_data.get('hgt_net_inflow', 0):.2f} 万元
+ 深股通净流入: {north_flow_data.get('sgt_net_inflow', 0):.2f} 万元
+"""
+ if north_flow_data.get('history'):
+ north_summary += "\n近10日北向资金流向:\n"
+ for item in north_flow_data['history'][:10]:
+ north_summary += f" {item['date']}: {item['net_inflow']:.2f}万\n"
+
+ prompt = f"""
+你是一名资深的资金流向分析师,拥有15年的市场资金研究经验,擅长从资金流向中洞察主力意图和市场趋势。
+
+{fund_flow_summary}
+
+{north_summary}
+
+请基于以上资金流向数据,进行深入的板块资金分析:
+
+1. **主力资金流向分析** ⭐ 核心
+ - 识别主力资金重点流入的板块(TOP5)
+ - 分析主力资金大幅流出的板块(TOP3)
+ - 判断资金流向的集中度(集中/分散)
+ - 评估资金流向的持续性和强度
+
+2. **资金类型分析**
+ - 超大单资金的流向特征(机构大资金)
+ - 大单资金的流向特征(主力资金)
+ - 中小单资金的流向(散户资金)
+ - 主力与散户的博弈特征
+
+3. **量价配合分析**
+ - 分析资金流入与板块涨幅的匹配度
+ - 识别"资金流入+板块上涨"的强势板块
+ - 识别"资金流入+板块下跌"的低吸信号
+ - 识别"资金流出+板块上涨"的出货警示
+ - 识别"资金流出+板块下跌"的弱势板块
+
+4. **北向资金偏好**
+ - 分析北向资金的流向趋势
+ - 判断外资对A股的态度(积极/观望/撤离)
+ - 识别北向资金偏好的板块
+ - 评估北向资金的指示意义
+
+5. **板块资金轮动**
+ - 识别资金从哪些板块流出
+ - 识别资金流向哪些板块
+ - 分析板块资金轮动的节奏和方向
+ - 预判下一个资金可能流入的板块
+
+6. **主力操作意图研判**
+ - 判断主力是否在积极建仓某些板块
+ - 识别主力可能在出货的板块
+ - 分析主力的操作风格(激进/稳健)
+ - 评估主力对后市的态度
+
+7. **投资策略建议**
+ - 基于资金流向,推荐3-5个强势板块
+ - 提示2-3个资金流出的风险板块
+ - 给出板块配置的优先级
+ - 提供跟随主力的操作建议
+
+8. **风险提示**
+ - 识别资金面的潜在风险
+ - 提示可能的资金陷阱
+ - 评估市场流动性状况
+
+请给出专业、深度的资金流向分析报告。
+"""
+
+ messages = [
+ {"role": "system", "content": "你是一名资深的资金流向分析师,擅长从资金数据中洞察主力意图和市场趋势。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ analysis = self.deepseek_client.call_api(messages, max_tokens=4000)
+
+ print(" ✓ 资金流向分析师分析完成")
+
+ return {
+ "agent_name": "资金流向分析师",
+ "agent_role": "跟踪板块资金流向,分析主力行为和资金轮动",
+ "analysis": analysis,
+ "focus_areas": ["资金流向", "主力行为", "北向资金", "板块轮动", "量价配合"],
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
+ }
+
+ def market_sentiment_decoder_agent(self, market_data: Dict, sectors_data: Dict, concepts_data: Dict) -> Dict[str, Any]:
+ """
+ 市场情绪解码员 - 从多维度解读市场情绪
+
+ 职责:
+ - 量化市场情绪指标
+ - 识别过度乐观或恐慌信号
+ - 评估板块热度和市场关注度
+ """
+ print("📈 市场情绪解码员正在分析...")
+ time.sleep(1)
+
+ # 构建市场情绪指标
+ sentiment_summary = ""
+ if market_data:
+ sentiment_summary = f"""
+【市场情绪指标】
+
+涨跌统计:
+ 总股票数: {market_data.get('total_stocks', 0)}
+ 上涨股票: {market_data.get('up_count', 0)} ({market_data.get('up_ratio', 0):.1f}%)
+ 下跌股票: {market_data.get('down_count', 0)}
+ 涨停数: {market_data.get('limit_up', 0)}
+ 跌停数: {market_data.get('limit_down', 0)}
+
+大盘表现:
+"""
+ if market_data.get("sh_index"):
+ sh = market_data["sh_index"]
+ sentiment_summary += f" 上证指数: {sh['close']} ({sh['change_pct']:+.2f}%)\n"
+ if market_data.get("sz_index"):
+ sz = market_data["sz_index"]
+ sentiment_summary += f" 深证成指: {sz['close']} ({sz['change_pct']:+.2f}%)\n"
+ if market_data.get("cyb_index"):
+ cyb = market_data["cyb_index"]
+ sentiment_summary += f" 创业板指: {cyb['close']} ({cyb['change_pct']:+.2f}%)\n"
+
+ # 板块热度分析
+ hot_sectors = ""
+ if sectors_data:
+ sorted_sectors = sorted(sectors_data.items(), key=lambda x: abs(x[1]["change_pct"]), reverse=True)
+ hot_sectors = f"""
+【板块热度排行】(按涨跌幅绝对值排序)
+
+最活跃板块 TOP10:
+"""
+ for idx, (name, info) in enumerate(sorted_sectors[:10], 1):
+ hot_sectors += f"{idx}. {name}: {info['change_pct']:+.2f}% | 换手率: {info['turnover']:.2f}% | 涨跌家数: {info['up_count']}/{info['down_count']}\n"
+
+ # 概念热度
+ hot_concepts = ""
+ if concepts_data:
+ sorted_concepts = sorted(concepts_data.items(), key=lambda x: abs(x[1]["change_pct"]), reverse=True)
+ hot_concepts = f"""
+【概念热度排行】
+
+最热概念 TOP10:
+"""
+ for idx, (name, info) in enumerate(sorted_concepts[:10], 1):
+ hot_concepts += f"{idx}. {name}: {info['change_pct']:+.2f}% | 换手率: {info['turnover']:.2f}%\n"
+
+ prompt = f"""
+你是一名资深的市场情绪分析师,拥有心理学和金融学双重背景,擅长从市场数据中解读投资者情绪和市场心理。
+
+{sentiment_summary}
+
+{hot_sectors}
+
+{hot_concepts}
+
+请基于以上数据,进行深入的市场情绪分析:
+
+1. **整体市场情绪评估**
+ - 量化当前市场情绪(0-100分,0=极度恐慌,50=中性,100=极度亢奋)
+ - 判断市场情绪状态(恐慌/谨慎/中性/乐观/亢奋)
+ - 分析情绪的强度和持续性
+ - 对比历史情绪水平
+
+2. **赚钱效应分析**
+ - 评估市场的赚钱效应(强/中/弱)
+ - 分析上涨股票占比和涨停数量
+ - 判断是否存在明显的板块效应
+ - 评估散户参与热情
+
+3. **市场热点分析**
+ - 识别当前最热门的3-5个板块/概念
+ - 分析热点的形成原因和逻辑
+ - 评估热点的持续性和扩散性
+ - 判断是否存在炒作泡沫
+
+4. **恐慌贪婪指数**
+ - 综合判断市场的贪婪或恐慌程度
+ - 分析涨跌停数量反映的情绪极端
+ - 识别情绪拐点信号
+ - 提示过度贪婪或过度恐慌的风险
+
+5. **板块情绪分化**
+ - 分析不同板块的情绪差异
+ - 识别高情绪板块和低情绪板块
+ - 判断情绪分化是否合理
+ - 预判情绪可能扩散的方向
+
+6. **换手率与活跃度**
+ - 分析整体市场和板块的换手率
+ - 评估市场活跃度(活跃/一般/低迷)
+ - 判断资金参与意愿
+ - 识别异常活跃的板块
+
+7. **情绪对市场的影响**
+ - 分析当前情绪对大盘的支撑或压制
+ - 判断情绪反转的可能性和时机
+ - 评估情绪驱动的交易机会
+ - 提示情绪面的风险
+
+8. **投资策略建议**
+ - 基于市场情绪给出操作建议
+ - 推荐情绪支持的板块(2-3个)
+ - 提示情绪透支的风险板块(1-2个)
+ - 给出仓位管理建议
+
+请给出专业、客观的市场情绪分析报告,避免主观臆测。
+"""
+
+ messages = [
+ {"role": "system", "content": "你是一名资深的市场情绪分析师,擅长从市场数据中解读投资者情绪和市场心理。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ analysis = self.deepseek_client.call_api(messages, max_tokens=4000)
+
+ print(" ✓ 市场情绪解码员分析完成")
+
+ return {
+ "agent_name": "市场情绪解码员",
+ "agent_role": "量化市场情绪,识别恐慌贪婪信号,评估板块热度",
+ "analysis": analysis,
+ "focus_areas": ["市场情绪", "赚钱效应", "热点识别", "恐慌贪婪", "活跃度"],
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
+ }
+
+ def _format_market_overview(self, market_data):
+ """格式化市场概况"""
+ if not market_data:
+ return "暂无市场数据"
+
+ text = ""
+ if market_data.get("sh_index"):
+ sh = market_data["sh_index"]
+ text += f"上证指数: {sh['close']} ({sh['change_pct']:+.2f}%)\n"
+ if market_data.get("sz_index"):
+ sz = market_data["sz_index"]
+ text += f"深证成指: {sz['close']} ({sz['change_pct']:+.2f}%)\n"
+ if market_data.get("total_stocks"):
+ text += f"涨跌统计: 上涨{market_data['up_count']}只({market_data['up_ratio']:.1f}%),下跌{market_data['down_count']}只\n"
+
+ return text
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智策AI智能体系统")
+ print("=" * 60)
+
+ # 创建模拟数据
+ test_market_data = {
+ "sh_index": {"close": 3200, "change_pct": 0.5},
+ "sz_index": {"close": 10500, "change_pct": 0.8},
+ "total_stocks": 5000,
+ "up_count": 3000,
+ "up_ratio": 60.0,
+ "down_count": 2000
+ }
+
+ test_news = [
+ {"title": "央行宣布降准0.5个百分点", "content": "为支持实体经济发展...", "publish_time": "2024-01-15 10:00"}
+ ]
+
+ agents = SectorStrategyAgents()
+
+ # 测试宏观策略师
+ print("\n测试宏观策略师...")
+ result = agents.macro_strategist_agent(test_market_data, test_news)
+ print(f"分析师: {result['agent_name']}")
+ print(f"分析内容长度: {len(result['analysis'])} 字符")
+
diff --git a/sector_strategy_data.py b/sector_strategy_data.py
new file mode 100644
index 0000000..2e0027b
--- /dev/null
+++ b/sector_strategy_data.py
@@ -0,0 +1,462 @@
+"""
+智策板块数据采集模块
+使用AKShare获取板块相关数据
+"""
+
+import akshare as ak
+import pandas as pd
+from datetime import datetime, timedelta
+import warnings
+import time
+
+warnings.filterwarnings('ignore')
+
+
+class SectorStrategyDataFetcher:
+ """板块策略数据获取类"""
+
+ def __init__(self):
+ print("[智策] 板块数据获取器初始化...")
+ self.max_retries = 3 # 最大重试次数
+ self.retry_delay = 2 # 重试延迟(秒)
+ self.request_delay = 1 # 请求间隔(秒)
+
+ def _safe_request(self, func, *args, **kwargs):
+ """安全的请求函数,包含重试机制"""
+ for attempt in range(self.max_retries):
+ try:
+ result = func(*args, **kwargs)
+ # 添加请求延迟,避免请求过快
+ time.sleep(self.request_delay)
+ return result
+ except Exception as e:
+ if attempt < self.max_retries - 1:
+ print(f" 请求失败,{self.retry_delay}秒后重试... (尝试 {attempt + 1}/{self.max_retries})")
+ time.sleep(self.retry_delay)
+ else:
+ print(f" 请求失败,已达最大重试次数: {e}")
+ raise e
+
+ def get_all_sector_data(self):
+ """
+ 获取所有板块的综合数据
+
+ Returns:
+ dict: 包含多个维度的板块数据
+ """
+ print("[智策] 开始获取板块综合数据...")
+
+ data = {
+ "success": False,
+ "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ "sectors": {},
+ "sector_fund_flow": {},
+ "market_overview": {},
+ "north_flow": {},
+ "news": []
+ }
+
+ try:
+ # 1. 获取行业板块数据
+ print(" [1/6] 获取行业板块行情...")
+ sectors_data = self._get_sector_performance()
+ if sectors_data:
+ data["sectors"] = sectors_data
+ print(f" ✓ 成功获取 {len(sectors_data)} 个行业板块数据")
+
+ # 2. 获取概念板块数据
+ print(" [2/6] 获取概念板块行情...")
+ concept_data = self._get_concept_performance()
+ if concept_data:
+ data["concepts"] = concept_data
+ print(f" ✓ 成功获取 {len(concept_data)} 个概念板块数据")
+
+ # 3. 获取板块资金流向
+ print(" [3/6] 获取行业资金流向...")
+ fund_flow_data = self._get_sector_fund_flow()
+ if fund_flow_data:
+ data["sector_fund_flow"] = fund_flow_data
+ print(f" ✓ 成功获取资金流向数据")
+
+ # 4. 获取市场总体情况
+ print(" [4/6] 获取市场总体情况...")
+ market_data = self._get_market_overview()
+ if market_data:
+ data["market_overview"] = market_data
+ print(f" ✓ 成功获取市场概况")
+
+ # 5. 获取北向资金流向
+ print(" [5/6] 获取北向资金流向...")
+ north_flow = self._get_north_money_flow()
+ if north_flow:
+ data["north_flow"] = north_flow
+ print(f" ✓ 成功获取北向资金数据")
+
+ # 6. 获取财经新闻
+ print(" [6/6] 获取财经新闻...")
+ news_data = self._get_financial_news()
+ if news_data:
+ data["news"] = news_data
+ print(f" ✓ 成功获取 {len(news_data)} 条新闻")
+
+ data["success"] = True
+ print("[智策] ✓ 板块数据获取完成!")
+
+ except Exception as e:
+ print(f"[智策] ✗ 数据获取出错: {e}")
+ data["error"] = str(e)
+
+ return data
+
+ def _get_sector_performance(self):
+ """获取行业板块表现"""
+ try:
+ # 获取行业板块实时行情(使用重试机制)
+ df = self._safe_request(ak.stock_board_industry_name_em)
+
+ if df is None or df.empty:
+ return {}
+
+ # 转换为字典格式
+ sectors = {}
+ for idx, row in df.iterrows():
+ sector_name = row.get('板块名称', '')
+ if sector_name:
+ sectors[sector_name] = {
+ "name": sector_name,
+ "change_pct": row.get('涨跌幅', 0),
+ "turnover": row.get('换手率', 0),
+ "total_market_cap": row.get('总市值', 0),
+ "top_stock": row.get('领涨股票', ''),
+ "top_stock_change": row.get('领涨股票涨跌幅', 0),
+ "up_count": row.get('上涨家数', 0),
+ "down_count": row.get('下跌家数', 0)
+ }
+
+ return sectors
+
+ except Exception as e:
+ print(f" 获取行业板块数据失败: {e}")
+ return {}
+
+ def _get_concept_performance(self):
+ """获取概念板块表现"""
+ try:
+ # 获取概念板块实时行情(使用重试机制)
+ df = self._safe_request(ak.stock_board_concept_name_em)
+
+ if df is None or df.empty:
+ return {}
+
+ # 转换为字典格式
+ concepts = {}
+ for idx, row in df.iterrows():
+ concept_name = row.get('板块名称', '')
+ if concept_name:
+ concepts[concept_name] = {
+ "name": concept_name,
+ "change_pct": row.get('涨跌幅', 0),
+ "turnover": row.get('换手率', 0),
+ "total_market_cap": row.get('总市值', 0),
+ "top_stock": row.get('领涨股票', ''),
+ "top_stock_change": row.get('领涨股票涨跌幅', 0),
+ "up_count": row.get('上涨家数', 0),
+ "down_count": row.get('下跌家数', 0)
+ }
+
+ return concepts
+
+ except Exception as e:
+ print(f" 获取概念板块数据失败: {e}")
+ return {}
+
+ def _get_sector_fund_flow(self):
+ """获取行业资金流向"""
+ try:
+ # 获取行业资金流向(使用重试机制)
+ df = self._safe_request(ak.stock_sector_fund_flow_rank, indicator="今日")
+
+ if df is None or df.empty:
+ return {}
+
+ # 转换为字典格式
+ fund_flow = {
+ "today": [],
+ "update_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+ }
+
+ for idx, row in df.head(50).iterrows(): # 取前50个
+ fund_flow["today"].append({
+ "sector": row.get('名称', ''),
+ "main_net_inflow": row.get('今日主力净流入-净额', 0),
+ "main_net_inflow_pct": row.get('今日主力净流入-净占比', 0),
+ "super_large_net_inflow": row.get('今日超大单净流入-净额', 0),
+ "large_net_inflow": row.get('今日大单净流入-净额', 0),
+ "medium_net_inflow": row.get('今日中单净流入-净额', 0),
+ "small_net_inflow": row.get('今日小单净流入-净额', 0),
+ "change_pct": row.get('今日涨跌幅', 0)
+ })
+
+ return fund_flow
+
+ except Exception as e:
+ print(f" 获取行业资金流向失败: {e}")
+ return {}
+
+ def _get_market_overview(self):
+ """获取市场总体情况"""
+ try:
+ # 获取A股市场统计
+ overview = {}
+
+ # 涨跌家数
+ try:
+ df_stat = self._safe_request(ak.stock_zh_a_spot_em)
+ if df_stat is not None and not df_stat.empty:
+ total_count = len(df_stat)
+ up_count = len(df_stat[df_stat['涨跌幅'] > 0])
+ down_count = len(df_stat[df_stat['涨跌幅'] < 0])
+ flat_count = total_count - up_count - down_count
+
+ overview["total_stocks"] = total_count
+ overview["up_count"] = up_count
+ overview["down_count"] = down_count
+ overview["flat_count"] = flat_count
+ overview["up_ratio"] = round(up_count / total_count * 100, 2) if total_count > 0 else 0
+
+ # 涨停跌停
+ limit_up = len(df_stat[df_stat['涨跌幅'] >= 9.5])
+ limit_down = len(df_stat[df_stat['涨跌幅'] <= -9.5])
+ overview["limit_up"] = limit_up
+ overview["limit_down"] = limit_down
+ except:
+ pass
+
+ # 大盘指数
+ try:
+ # 上证指数
+ df_sh = ak.stock_zh_index_spot_em(symbol="上证指数")
+ if df_sh is not None and not df_sh.empty:
+ overview["sh_index"] = {
+ "code": "000001",
+ "name": "上证指数",
+ "close": df_sh.iloc[0].get('最新价', 0),
+ "change_pct": df_sh.iloc[0].get('涨跌幅', 0),
+ "change": df_sh.iloc[0].get('涨跌额', 0)
+ }
+
+ # 深证成指
+ df_sz = self._safe_request(ak.stock_zh_index_spot_em, symbol="深证成指")
+ if df_sz is not None and not df_sz.empty:
+ overview["sz_index"] = {
+ "code": "399001",
+ "name": "深证成指",
+ "close": df_sz.iloc[0].get('最新价', 0),
+ "change_pct": df_sz.iloc[0].get('涨跌幅', 0),
+ "change": df_sz.iloc[0].get('涨跌额', 0)
+ }
+
+ # 创业板指
+ df_cyb = self._safe_request(ak.stock_zh_index_spot_em, symbol="创业板指")
+ if df_cyb is not None and not df_cyb.empty:
+ overview["cyb_index"] = {
+ "code": "399006",
+ "name": "创业板指",
+ "close": df_cyb.iloc[0].get('最新价', 0),
+ "change_pct": df_cyb.iloc[0].get('涨跌幅', 0),
+ "change": df_cyb.iloc[0].get('涨跌额', 0)
+ }
+ except:
+ pass
+
+ return overview
+
+ except Exception as e:
+ print(f" 获取市场概况失败: {e}")
+ return {}
+
+ def _get_north_money_flow(self):
+ """获取北向资金流向"""
+ try:
+ # 获取沪深港通资金流向(使用重试机制)
+ df = self._safe_request(ak.stock_hsgt_fund_flow_summary_em)
+
+ if df is None or df.empty:
+ return {}
+
+ # 获取最新数据
+ latest = df.iloc[0]
+
+ north_flow = {
+ "date": str(latest.get('日期', '')),
+ "north_net_inflow": latest.get('北向资金-成交净买额', 0),
+ "hgt_net_inflow": latest.get('沪股通-成交净买额', 0),
+ "sgt_net_inflow": latest.get('深股通-成交净买额', 0),
+ "north_total_amount": latest.get('北向资金-成交金额', 0)
+ }
+
+ # 获取历史趋势(最近10天)
+ history = []
+ for idx, row in df.head(10).iterrows():
+ history.append({
+ "date": str(row.get('日期', '')),
+ "net_inflow": row.get('北向资金-成交净买额', 0)
+ })
+ north_flow["history"] = history
+
+ return north_flow
+
+ except Exception as e:
+ print(f" 获取北向资金失败: {e}")
+ return {}
+
+ def _get_financial_news(self):
+ """获取财经新闻"""
+ try:
+ # 获取东方财富财经新闻(使用重试机制)
+ df = self._safe_request(ak.stock_news_em, symbol="全球")
+
+ if df is None or df.empty:
+ return []
+
+ news_list = []
+ for idx, row in df.head(150).iterrows(): # 取前150条
+ news_list.append({
+ "title": row.get('新闻标题', ''),
+ "content": row.get('新闻内容', ''),
+ "publish_time": str(row.get('发布时间', '')),
+ "source": row.get('文章来源', ''),
+ "url": row.get('新闻链接', '')
+ })
+
+ return news_list
+
+ except Exception as e:
+ print(f" 获取财经新闻失败: {e}")
+ return []
+
+ def format_data_for_ai(self, data):
+ """
+ 将数据格式化为适合AI分析的文本格式
+ """
+ if not data.get("success"):
+ return "数据获取失败"
+
+ text_parts = []
+
+ # 市场概况
+ if data.get("market_overview"):
+ market = data["market_overview"]
+ text_parts.append(f"""
+【市场总体情况】
+时间: {data.get('timestamp', 'N/A')}
+
+大盘指数:
+""")
+ if market.get("sh_index"):
+ sh = market["sh_index"]
+ text_parts.append(f" 上证指数: {sh['close']} ({sh['change_pct']:+.2f}%)")
+ if market.get("sz_index"):
+ sz = market["sz_index"]
+ text_parts.append(f" 深证成指: {sz['close']} ({sz['change_pct']:+.2f}%)")
+ if market.get("cyb_index"):
+ cyb = market["cyb_index"]
+ text_parts.append(f" 创业板指: {cyb['close']} ({cyb['change_pct']:+.2f}%)")
+
+ if market.get("total_stocks"):
+ text_parts.append(f"""
+市场统计:
+ 总股票数: {market['total_stocks']}
+ 上涨: {market['up_count']} ({market['up_ratio']:.1f}%)
+ 下跌: {market['down_count']}
+ 平盘: {market['flat_count']}
+ 涨停: {market['limit_up']}
+ 跌停: {market['limit_down']}
+""")
+
+ # 北向资金
+ if data.get("north_flow"):
+ north = data["north_flow"]
+ text_parts.append(f"""
+【北向资金流向】
+日期: {north.get('date', 'N/A')}
+北向资金净流入: {north.get('north_net_inflow', 0):.2f} 万元
+ 沪股通: {north.get('hgt_net_inflow', 0):.2f} 万元
+ 深股通: {north.get('sgt_net_inflow', 0):.2f} 万元
+""")
+
+ # 行业板块表现(前20)
+ if data.get("sectors"):
+ sectors = data["sectors"]
+ sorted_sectors = sorted(sectors.items(), key=lambda x: x[1]["change_pct"], reverse=True)
+
+ text_parts.append(f"""
+【行业板块表现 TOP20】
+涨幅榜前10:
+""")
+ for name, info in sorted_sectors[:10]:
+ text_parts.append(f" {name}: {info['change_pct']:+.2f}% | 领涨: {info['top_stock']} ({info['top_stock_change']:+.2f}%)")
+
+ text_parts.append(f"""
+跌幅榜前10:
+""")
+ for name, info in sorted_sectors[-10:]:
+ text_parts.append(f" {name}: {info['change_pct']:+.2f}% | 领跌: {info['top_stock']} ({info['top_stock_change']:+.2f}%)")
+
+ # 概念板块表现(前20)
+ if data.get("concepts"):
+ concepts = data["concepts"]
+ sorted_concepts = sorted(concepts.items(), key=lambda x: x[1]["change_pct"], reverse=True)
+
+ text_parts.append(f"""
+【概念板块表现 TOP20】
+涨幅榜前10:
+""")
+ for name, info in sorted_concepts[:10]:
+ text_parts.append(f" {name}: {info['change_pct']:+.2f}% | 领涨: {info['top_stock']} ({info['top_stock_change']:+.2f}%)")
+
+ # 板块资金流向(前15)
+ if data.get("sector_fund_flow") and data["sector_fund_flow"].get("today"):
+ flow = data["sector_fund_flow"]["today"]
+
+ text_parts.append(f"""
+【行业资金流向 TOP15】
+主力资金净流入前15:
+""")
+ sorted_flow = sorted(flow, key=lambda x: x["main_net_inflow"], reverse=True)
+ for item in sorted_flow[:15]:
+ text_parts.append(f" {item['sector']}: {item['main_net_inflow']:.2f}万 ({item['main_net_inflow_pct']:+.2f}%) | 涨跌: {item['change_pct']:+.2f}%")
+
+ # 重要新闻(前20条)
+ if data.get("news"):
+ text_parts.append(f"""
+【重要财经新闻 TOP20】
+""")
+ for idx, news in enumerate(data["news"][:20], 1):
+ text_parts.append(f"{idx}. [{news['publish_time']}] {news['title']}")
+ if news.get('content') and len(news['content']) > 100:
+ text_parts.append(f" {news['content'][:100]}...")
+
+ return "\n".join(text_parts)
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智策板块数据采集模块")
+ print("=" * 60)
+
+ fetcher = SectorStrategyDataFetcher()
+ data = fetcher.get_all_sector_data()
+
+ if data.get("success"):
+ print("\n" + "=" * 60)
+ print("数据采集成功!")
+ print("=" * 60)
+
+ formatted_text = fetcher.format_data_for_ai(data)
+ print(formatted_text[:3000]) # 显示前3000字符
+ print(f"\n... (总长度: {len(formatted_text)} 字符)")
+ else:
+ print(f"\n数据采集失败: {data.get('error', '未知错误')}")
+
diff --git a/sector_strategy_engine.py b/sector_strategy_engine.py
new file mode 100644
index 0000000..7fdfb9c
--- /dev/null
+++ b/sector_strategy_engine.py
@@ -0,0 +1,364 @@
+"""
+智策综合研判引擎
+整合各智能体分析,生成板块多空/轮动/热度预测
+"""
+
+from sector_strategy_agents import SectorStrategyAgents
+from deepseek_client import DeepSeekClient
+from typing import Dict, Any
+import time
+import json
+
+
+class SectorStrategyEngine:
+ """板块策略综合研判引擎"""
+
+ def __init__(self, model="deepseek-chat"):
+ self.model = model
+ self.agents = SectorStrategyAgents(model=model)
+ self.deepseek_client = DeepSeekClient(model=model)
+ print(f"[智策引擎] 初始化完成 (模型: {model})")
+
+ def run_comprehensive_analysis(self, data: Dict) -> Dict[str, Any]:
+ """
+ 运行综合分析流程
+
+ Args:
+ data: 包含市场数据的字典
+
+ Returns:
+ 完整的分析结果
+ """
+ print("\n" + "=" * 60)
+ print("🚀 智策综合分析系统启动")
+ print("=" * 60)
+
+ results = {
+ "success": False,
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
+ "agents_analysis": {},
+ "comprehensive_report": "",
+ "final_predictions": {}
+ }
+
+ try:
+ # 1. 运行四个AI智能体分析
+ print("\n[阶段1] AI智能体分析集群工作中...")
+ print("-" * 60)
+
+ agents_results = {}
+
+ # 宏观策略师
+ print("1/4 宏观策略师...")
+ macro_result = self.agents.macro_strategist_agent(
+ market_data=data.get("market_overview", {}),
+ news_data=data.get("news", [])
+ )
+ agents_results["macro"] = macro_result
+
+ # 板块诊断师
+ print("2/4 板块诊断师...")
+ sector_result = self.agents.sector_diagnostician_agent(
+ sectors_data=data.get("sectors", {}),
+ concepts_data=data.get("concepts", {}),
+ market_data=data.get("market_overview", {})
+ )
+ agents_results["sector"] = sector_result
+
+ # 资金流向分析师
+ print("3/4 资金流向分析师...")
+ fund_result = self.agents.fund_flow_analyst_agent(
+ fund_flow_data=data.get("sector_fund_flow", {}),
+ north_flow_data=data.get("north_flow", {}),
+ sectors_data=data.get("sectors", {})
+ )
+ agents_results["fund"] = fund_result
+
+ # 市场情绪解码员
+ print("4/4 市场情绪解码员...")
+ sentiment_result = self.agents.market_sentiment_decoder_agent(
+ market_data=data.get("market_overview", {}),
+ sectors_data=data.get("sectors", {}),
+ concepts_data=data.get("concepts", {})
+ )
+ agents_results["sentiment"] = sentiment_result
+
+ results["agents_analysis"] = agents_results
+ print("\n✓ 所有智能体分析完成")
+
+ # 2. 综合研判
+ print("\n[阶段2] 综合研判引擎工作中...")
+ print("-" * 60)
+ comprehensive_report = self._conduct_comprehensive_discussion(agents_results)
+ results["comprehensive_report"] = comprehensive_report
+ print("✓ 综合研判完成")
+
+ # 3. 生成最终预测
+ print("\n[阶段3] 生成最终预测...")
+ print("-" * 60)
+ predictions = self._generate_final_predictions(comprehensive_report, agents_results, data)
+ results["final_predictions"] = predictions
+ print("✓ 预测生成完成")
+
+ results["success"] = True
+
+ print("\n" + "=" * 60)
+ print("✓ 智策综合分析完成!")
+ print("=" * 60)
+
+ except Exception as e:
+ print(f"\n✗ 分析过程出错: {e}")
+ import traceback
+ traceback.print_exc()
+ results["error"] = str(e)
+
+ return results
+
+ def _conduct_comprehensive_discussion(self, agents_results: Dict) -> str:
+ """
+ 综合研判 - 整合各智能体的分析
+ """
+ print(" 🤝 智能体团队正在综合讨论...")
+ time.sleep(2)
+
+ # 收集各分析师的报告
+ macro_analysis = agents_results.get("macro", {}).get("analysis", "")
+ sector_analysis = agents_results.get("sector", {}).get("analysis", "")
+ fund_analysis = agents_results.get("fund", {}).get("analysis", "")
+ sentiment_analysis = agents_results.get("sentiment", {}).get("analysis", "")
+
+ prompt = f"""
+你是智策系统的首席策略官,现在需要综合四位专业分析师的报告,形成全面的市场和板块研判。
+
+【宏观策略师报告】
+{macro_analysis}
+
+【板块诊断师报告】
+{sector_analysis}
+
+【资金流向分析师报告】
+{fund_analysis}
+
+【市场情绪解码员报告】
+{sentiment_analysis}
+
+请基于以上四位分析师的专业报告,进行深度综合研判:
+
+1. **观点一致性分析**
+ - 四位分析师的核心观点有哪些一致之处?
+ - 在哪些方面存在分歧或不同看法?
+ - 如何理解这些分歧的合理性?
+
+2. **多维度交叉验证**
+ - 宏观环境、板块基本面、资金流向、市场情绪是否形成共振?
+ - 哪些板块得到了多维度的支持?
+ - 哪些板块存在多维度的风险信号?
+
+3. **关键矛盾识别**
+ - 当前市场和板块的主要矛盾是什么?
+ - 哪些因素可能成为决定性因素?
+ - 如何平衡不同维度的分析结论?
+
+4. **综合判断**
+ - 基于四个维度的综合分析,对市场整体趋势的判断
+ - 对板块轮动方向的判断
+ - 对市场风险收益比的评估
+ - 当前最值得把握的机会在哪里?
+
+5. **策略权重建议**
+ - 在当前环境下,四个分析维度的重要性权重(宏观/板块/资金/情绪)
+ - 应该重点参考哪个维度的建议?
+ - 需要警惕哪个维度的风险?
+
+请给出专业、全面的综合研判报告,体现多维度分析的价值。
+"""
+
+ messages = [
+ {"role": "system", "content": "你是智策系统的首席策略官,需要整合多维度分析,形成全面的投资策略。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ report = self.deepseek_client.call_api(messages, max_tokens=5000)
+
+ print(" ✓ 综合研判完成")
+ return report
+
+ def _generate_final_predictions(self, comprehensive_report: str, agents_results: Dict, raw_data: Dict) -> Dict:
+ """
+ 生成最终预测 - 板块多空/轮动/热度
+ """
+ print(" 📊 生成板块多空/轮动/热度预测...")
+ time.sleep(2)
+
+ # 提取板块列表用于预测
+ sectors_list = []
+ if raw_data.get("sectors"):
+ sorted_sectors = sorted(raw_data["sectors"].items(), key=lambda x: abs(x[1]["change_pct"]), reverse=True)
+ sectors_list = [name for name, _ in sorted_sectors[:30]] # 取前30个活跃板块
+
+ sectors_str = ", ".join(sectors_list) if sectors_list else "未知板块"
+
+ prompt = f"""
+基于前期的深度分析和综合研判,现在需要生成最终的板块预测报告。
+
+【综合研判结论】
+{comprehensive_report}
+
+【参考板块列表】
+{sectors_str}
+
+请生成以下三类预测,并以JSON格式输出:
+
+1. **板块多空情况**
+ - 看多板块(5-8个):综合判断未来1-2周看涨的板块
+ - 看空板块(3-5个):综合判断未来1-2周看跌的板块
+ - 中性板块(2-3个):走势不明朗的板块
+
+ 对每个板块给出:
+ - 板块名称
+ - 多空判断(看多/看空/中性)
+ - 推荐理由(100字以内)
+ - 信心度(1-10分)
+ - 风险提示
+
+2. **板块轮动预测**
+ - 当前强势板块(正在走强的2-3个板块)
+ - 潜力接力板块(可能轮动到的3-5个板块)
+ - 衰退板块(正在走弱的2-3个板块)
+
+ 对每个板块给出:
+ - 板块名称
+ - 轮动阶段(强势/潜力/衰退)
+ - 轮动逻辑(150字以内)
+ - 预计时间窗口
+ - 操作建议
+
+3. **板块热度排行**
+ - 最热板块TOP5(综合资金、情绪、涨幅)
+ - 升温板块TOP5(热度快速上升的板块)
+ - 降温板块TOP3(热度快速下降的板块)
+
+ 对每个板块给出:
+ - 板块名称
+ - 热度评分(0-100分)
+ - 热度变化趋势(升温/降温/稳定)
+ - 持续性评估(强/中/弱)
+
+请严格按照以下JSON格式输出:
+{{
+ "long_short": {{
+ "bullish": [
+ {{
+ "sector": "板块名称",
+ "direction": "看多",
+ "reason": "推荐理由",
+ "confidence": 8,
+ "risk": "风险提示"
+ }}
+ ],
+ "bearish": [...],
+ "neutral": [...]
+ }},
+ "rotation": {{
+ "current_strong": [
+ {{
+ "sector": "板块名称",
+ "stage": "强势",
+ "logic": "轮动逻辑",
+ "time_window": "1-2周",
+ "advice": "操作建议"
+ }}
+ ],
+ "potential": [...],
+ "declining": [...]
+ }},
+ "heat": {{
+ "hottest": [
+ {{
+ "sector": "板块名称",
+ "score": 95,
+ "trend": "升温",
+ "sustainability": "强"
+ }}
+ ],
+ "heating": [...],
+ "cooling": [...]
+ }},
+ "summary": {{
+ "market_view": "市场整体看法",
+ "key_opportunity": "核心机会",
+ "major_risk": "主要风险",
+ "strategy": "整体策略建议"
+ }}
+}}
+
+注意:
+1. 所有板块名称必须从参考板块列表中选择
+2. 分析要基于前期的多维度研判
+3. 给出的建议要具体、可操作
+4. 预测要客观、理性,避免过度乐观或悲观
+"""
+
+ messages = [
+ {"role": "system", "content": "你是智策系统的预测引擎,需要生成专业、精准的板块预测报告。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ response = self.deepseek_client.call_api(messages, temperature=0.3, max_tokens=6000)
+
+ # 尝试解析JSON
+ try:
+ import re
+ json_match = re.search(r'\{.*\}', response, re.DOTALL)
+ if json_match:
+ predictions = json.loads(json_match.group())
+ print(" ✓ 预测报告生成成功(JSON格式)")
+ return predictions
+ else:
+ print(" ⚠ 未能解析JSON,返回文本格式")
+ return {"prediction_text": response}
+ except Exception as e:
+ print(f" ⚠ JSON解析失败: {e},返回文本格式")
+ return {"prediction_text": response}
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智策综合研判引擎")
+ print("=" * 60)
+
+ # 创建模拟数据
+ test_data = {
+ "success": True,
+ "sectors": {
+ "电子": {"change_pct": 2.5, "turnover": 3.5, "top_stock": "某某科技", "top_stock_change": 5.0, "up_count": 80, "down_count": 20},
+ "计算机": {"change_pct": 1.8, "turnover": 4.0, "top_stock": "某某软件", "top_stock_change": 4.5, "up_count": 70, "down_count": 30}
+ },
+ "market_overview": {
+ "sh_index": {"close": 3200, "change_pct": 0.5},
+ "total_stocks": 5000,
+ "up_count": 3000,
+ "up_ratio": 60.0
+ },
+ "news": [
+ {"title": "测试新闻", "content": "测试内容", "publish_time": "2024-01-15"}
+ ],
+ "sector_fund_flow": {
+ "today": [
+ {"sector": "电子", "main_net_inflow": 100000, "main_net_inflow_pct": 2.0, "change_pct": 2.5, "super_large_net_inflow": 50000}
+ ]
+ },
+ "north_flow": {
+ "date": "2024-01-15",
+ "north_net_inflow": 50000
+ }
+ }
+
+ engine = SectorStrategyEngine()
+
+ print("\n开始综合分析...")
+ # 注意:这只是测试框架,实际运行需要真实数据和API key
+ # results = engine.run_comprehensive_analysis(test_data)
+ # print(f"\n分析结果: {results.get('success')}")
+
diff --git a/sector_strategy_pdf.py b/sector_strategy_pdf.py
new file mode 100644
index 0000000..bb0f5a7
--- /dev/null
+++ b/sector_strategy_pdf.py
@@ -0,0 +1,538 @@
+"""
+智策报告PDF导出模块
+"""
+
+from reportlab.lib import colors
+from reportlab.lib.pagesizes import A4
+from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
+from reportlab.lib.units import inch
+from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
+from reportlab.pdfbase import pdfmetrics
+from reportlab.pdfbase.ttfonts import TTFont
+from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
+from datetime import datetime
+import os
+import tempfile
+
+
+class SectorStrategyPDFGenerator:
+ """智策报告PDF生成器"""
+
+ def __init__(self):
+ """初始化PDF生成器"""
+ self.setup_fonts()
+
+ def setup_fonts(self):
+ """设置中文字体"""
+ try:
+ # 尝试注册常见的中文字体
+ font_paths = [
+ 'C:/Windows/Fonts/msyh.ttc', # 微软雅黑
+ 'C:/Windows/Fonts/simsun.ttc', # 宋体
+ 'C:/Windows/Fonts/simhei.ttf', # 黑体
+ ]
+
+ for font_path in font_paths:
+ if os.path.exists(font_path):
+ try:
+ pdfmetrics.registerFont(TTFont('ChineseFont', font_path))
+ self.chinese_font = 'ChineseFont'
+ print(f"[PDF] 成功加载字体: {font_path}")
+ return
+ except:
+ continue
+
+ # 如果都失败,使用默认字体
+ self.chinese_font = 'Helvetica'
+ print("[PDF] 警告: 未找到中文字体,使用默认字体")
+
+ except Exception as e:
+ print(f"[PDF] 字体设置失败: {e}")
+ self.chinese_font = 'Helvetica'
+
+ def generate_pdf(self, result_data: dict, output_path: str = None) -> str:
+ """
+ 生成智策分析PDF报告
+
+ Args:
+ result_data: 分析结果数据
+ output_path: 输出路径,如果为None则生成临时文件
+
+ Returns:
+ PDF文件路径
+ """
+ try:
+ # 如果没有指定输出路径,创建临时文件
+ if output_path is None:
+ temp_dir = tempfile.gettempdir()
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+ output_path = os.path.join(temp_dir, f"智策报告_{timestamp}.pdf")
+
+ # 创建PDF文档
+ doc = SimpleDocTemplate(
+ output_path,
+ pagesize=A4,
+ rightMargin=0.5*inch,
+ leftMargin=0.5*inch,
+ topMargin=0.5*inch,
+ bottomMargin=0.5*inch
+ )
+
+ # 构建内容
+ story = []
+
+ # 添加标题页
+ story.extend(self._create_title_page(result_data))
+ story.append(PageBreak())
+
+ # 添加市场概况
+ story.extend(self._create_market_overview(result_data))
+ story.append(PageBreak())
+
+ # 添加核心预测
+ story.extend(self._create_predictions_section(result_data))
+ story.append(PageBreak())
+
+ # 添加智能体分析摘要
+ story.extend(self._create_agents_summary(result_data))
+ story.append(PageBreak())
+
+ # 添加综合研判
+ story.extend(self._create_comprehensive_report(result_data))
+
+ # 生成PDF
+ doc.build(story)
+
+ print(f"[PDF] 报告生成成功: {output_path}")
+ return output_path
+
+ except Exception as e:
+ print(f"[PDF] 生成失败: {e}")
+ import traceback
+ traceback.print_exc()
+ raise
+
+ def _create_title_page(self, data: dict) -> list:
+ """创建标题页"""
+ styles = self._get_styles()
+ elements = []
+
+ # 添加空白
+ elements.append(Spacer(1, 2*inch))
+
+ # 主标题
+ title = Paragraph("智策板块策略分析报告", styles['Title'])
+ elements.append(title)
+ elements.append(Spacer(1, 0.5*inch))
+
+ # 副标题
+ subtitle = Paragraph("AI驱动的多维度板块投资决策支持系统", styles['Heading2'])
+ elements.append(subtitle)
+ elements.append(Spacer(1, 1*inch))
+
+ # 报告信息
+ timestamp = data.get('timestamp', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
+ info_text = f"""
+
+ 分析周期: 当日市场数据
+ AI模型: DeepSeek Multi-Agent System
+ 分析维度: 宏观·板块·资金·情绪
+
"
+ "投资有风险,决策需谨慎。
+ • 宏观策略师 - 分析宏观经济、政策导向、新闻事件
+ • 板块诊断师 - 分析板块走势、估值水平、轮动特征
+ • 资金流向分析师 - 分析主力资金、北向资金流向
+ • 市场情绪解码员 - 分析市场情绪、热度、赚钱效应
+
+ 理由: {item.get('reason', 'N/A')}
+ 风险: {item.get('risk', 'N/A')}
+ """
+ elements.append(Paragraph(text, styles['Small']))
+ elements.append(Spacer(1, 0.05*inch))
+
+ # 看空板块
+ bearish = long_short.get('bearish', [])
+ if bearish:
+ elements.append(Spacer(1, 0.1*inch))
+ elements.append(Paragraph("看空板块:", styles['Normal']))
+
+ for idx, item in enumerate(bearish, 1):
+ text = f"""
+ {idx}. {item.get('sector', 'N/A')} (信心度: {item.get('confidence', 0)}/10)
+ 理由: {item.get('reason', 'N/A')}
+ 风险: {item.get('risk', 'N/A')}
+ """
+ elements.append(Paragraph(text, styles['Small']))
+ elements.append(Spacer(1, 0.05*inch))
+
+ return elements
+
+ def _create_rotation_section(self, predictions: dict, styles: dict) -> list:
+ """创建板块轮动部分"""
+ elements = []
+
+ elements.append(Paragraph("2.2 板块轮动预测", styles['Heading2']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ rotation = predictions.get('rotation', {})
+
+ # 当前强势
+ current_strong = rotation.get('current_strong', [])
+ if current_strong:
+ elements.append(Paragraph("当前强势板块:", styles['Normal']))
+ for item in current_strong:
+ text = f"""
+ • {item.get('sector', 'N/A')}
+ 轮动逻辑: {item.get('logic', 'N/A')[:100]}...
+ 时间窗口: {item.get('time_window', 'N/A')}
+ 操作建议: {item.get('advice', 'N/A')}
+ """
+ elements.append(Paragraph(text, styles['Small']))
+ elements.append(Spacer(1, 0.05*inch))
+
+ # 潜力接力
+ potential = rotation.get('potential', [])
+ if potential:
+ elements.append(Spacer(1, 0.1*inch))
+ elements.append(Paragraph("潜力接力板块:", styles['Normal']))
+ for item in potential:
+ text = f"""
+ • {item.get('sector', 'N/A')}
+ 轮动逻辑: {item.get('logic', 'N/A')[:100]}...
+ 时间窗口: {item.get('time_window', 'N/A')}
+ 操作建议: {item.get('advice', 'N/A')}
+ """
+ elements.append(Paragraph(text, styles['Small']))
+ elements.append(Spacer(1, 0.05*inch))
+
+ return elements
+
+ def _create_heat_section(self, predictions: dict, styles: dict) -> list:
+ """创建板块热度部分"""
+ elements = []
+
+ elements.append(Paragraph("2.3 板块热度排行", styles['Heading2']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ heat = predictions.get('heat', {})
+
+ # 创建表格数据
+ table_data = [['排名', '板块', '热度评分', '趋势', '持续性']]
+
+ # 最热板块
+ hottest = heat.get('hottest', [])
+ for idx, item in enumerate(hottest[:5], 1):
+ table_data.append([
+ str(idx),
+ item.get('sector', 'N/A'),
+ str(item.get('score', 0)),
+ item.get('trend', 'N/A'),
+ item.get('sustainability', 'N/A')
+ ])
+
+ if len(table_data) > 1:
+ # 创建表格
+ table = Table(table_data, colWidths=[0.8*inch, 2*inch, 1*inch, 1*inch, 1*inch])
+ table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
+ ('FONTNAME', (0, 0), (-1, 0), self.chinese_font),
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
+ ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
+ ('GRID', (0, 0), (-1, -1), 1, colors.black),
+ ('FONTNAME', (0, 1), (-1, -1), self.chinese_font),
+ ('FONTSIZE', (0, 1), (-1, -1), 9),
+ ]))
+ elements.append(table)
+
+ return elements
+
+ def _create_summary_section(self, predictions: dict, styles: dict) -> list:
+ """创建策略总结部分"""
+ elements = []
+
+ summary = predictions.get('summary', {})
+
+ if not summary:
+ return elements
+
+ elements.append(Paragraph("2.4 策略总结", styles['Heading2']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ # 市场观点
+ if summary.get('market_view'):
+ elements.append(Paragraph("市场观点:", styles['Normal']))
+ elements.append(Paragraph(summary['market_view'], styles['Small']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ # 核心机会
+ if summary.get('key_opportunity'):
+ elements.append(Paragraph("核心机会:", styles['Normal']))
+ elements.append(Paragraph(summary['key_opportunity'], styles['Small']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ # 主要风险
+ if summary.get('major_risk'):
+ elements.append(Paragraph("主要风险:", styles['Normal']))
+ elements.append(Paragraph(summary['major_risk'], styles['Small']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ # 整体策略
+ if summary.get('strategy'):
+ elements.append(Paragraph("整体策略:", styles['Normal']))
+ elements.append(Paragraph(summary['strategy'], styles['Small']))
+
+ return elements
+
+ def _create_agents_summary(self, data: dict) -> list:
+ """创建智能体分析摘要"""
+ styles = self._get_styles()
+ elements = []
+
+ elements.append(Paragraph("三、AI智能体分析摘要", styles['Heading1']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ agents_analysis = data.get('agents_analysis', {})
+
+ for key, agent_data in agents_analysis.items():
+ agent_name = agent_data.get('agent_name', '未知分析师')
+ agent_role = agent_data.get('agent_role', '')
+ analysis = agent_data.get('analysis', '')
+
+ # 分析师名称和职责
+ elements.append(Paragraph(f"{agent_name}", styles['Heading2']))
+ elements.append(Paragraph(f"{agent_role}", styles['Small']))
+ elements.append(Spacer(1, 0.1*inch))
+
+ # 分析内容(截取前500字)
+ analysis_preview = analysis[:500] + "..." if len(analysis) > 500 else analysis
+ elements.append(Paragraph(analysis_preview, styles['Small']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ return elements
+
+ def _create_comprehensive_report(self, data: dict) -> list:
+ """创建综合研判部分"""
+ styles = self._get_styles()
+ elements = []
+
+ elements.append(Paragraph("四、综合研判", styles['Heading1']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ report = data.get('comprehensive_report', '')
+
+ if report:
+ # 截取前1000字
+ report_preview = report[:1000] + "..." if len(report) > 1000 else report
+ elements.append(Paragraph(report_preview, styles['Small']))
+ else:
+ elements.append(Paragraph("暂无综合研判数据", styles['Normal']))
+
+ elements.append(Spacer(1, 0.3*inch))
+
+ # 添加结束语
+ ending = Paragraph(
+ "
"
+ "本报告由智策AI系统自动生成
信心度: {item.get('confidence', 0)}/10
+理由: {item.get('reason', '')}
+风险: {item.get('risk', '')}
+信心度: {item.get('confidence', 0)}/10
+理由: {item.get('reason', '')}
+风险: {item.get('risk', '')}
+{summary.get('market_view', 'N/A')}
+{summary.get('key_opportunity', 'N/A')}
+{summary.get('major_risk', 'N/A')}
+{summary.get('strategy', 'N/A')}
+职责: {agent.get('agent_role', '未知')}
+关注领域: {', '.join(agent.get('focus_areas', []))}
+分析时间: {agent.get('timestamp', '未知')}
+基于四位专业分析师的深度分析,形成的全面市场和板块研判
+