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""" + + 生成时间: {timestamp}
+ 分析周期: 当日市场数据
+ AI模型: DeepSeek Multi-Agent System
+ 分析维度: 宏观·板块·资金·情绪 +
+ """ + info = Paragraph(info_text, styles['Normal']) + elements.append(info) + elements.append(Spacer(1, 1*inch)) + + # 免责声明 + disclaimer = Paragraph( + "本报告由AI系统自动生成,仅供参考,不构成投资建议。
" + "投资有风险,决策需谨慎。
", + styles['Normal'] + ) + elements.append(disclaimer) + + return elements + + def _create_market_overview(self, data: dict) -> list: + """创建市场概况部分""" + styles = self._get_styles() + elements = [] + + # 标题 + elements.append(Paragraph("一、市场概况", styles['Heading1'])) + elements.append(Spacer(1, 0.2*inch)) + + # 这里需要从原始数据中提取市场概况 + # 由于result_data中可能没有直接的市场数据,我们从agents_analysis中提取 + + overview_text = f""" + + 本报告基于{data.get('timestamp', 'N/A')}的实时市场数据, + 通过四位AI智能体的多维度分析,为您提供板块投资策略建议。 + + """ + elements.append(Paragraph(overview_text, styles['Normal'])) + elements.append(Spacer(1, 0.2*inch)) + + # 分析师团队 + team_text = """ + + 分析师团队:
+ • 宏观策略师 - 分析宏观经济、政策导向、新闻事件
+ • 板块诊断师 - 分析板块走势、估值水平、轮动特征
+ • 资金流向分析师 - 分析主力资金、北向资金流向
+ • 市场情绪解码员 - 分析市场情绪、热度、赚钱效应 +
+ """ + elements.append(Paragraph(team_text, styles['Normal'])) + + return elements + + def _create_predictions_section(self, data: dict) -> list: + """创建核心预测部分""" + styles = self._get_styles() + elements = [] + + predictions = data.get('final_predictions', {}) + + if predictions.get('prediction_text'): + # 文本格式 + elements.append(Paragraph("二、核心预测", styles['Heading1'])) + elements.append(Spacer(1, 0.2*inch)) + elements.append(Paragraph(predictions['prediction_text'], styles['Normal'])) + return elements + + # JSON格式预测 + elements.append(Paragraph("二、核心预测", styles['Heading1'])) + elements.append(Spacer(1, 0.2*inch)) + + # 1. 板块多空 + elements.extend(self._create_long_short_section(predictions, styles)) + elements.append(Spacer(1, 0.3*inch)) + + # 2. 板块轮动 + elements.extend(self._create_rotation_section(predictions, styles)) + elements.append(Spacer(1, 0.3*inch)) + + # 3. 板块热度 + elements.extend(self._create_heat_section(predictions, styles)) + elements.append(Spacer(1, 0.3*inch)) + + # 4. 策略总结 + elements.extend(self._create_summary_section(predictions, styles)) + + return elements + + def _create_long_short_section(self, predictions: dict, styles: dict) -> list: + """创建板块多空部分""" + elements = [] + + elements.append(Paragraph("2.1 板块多空预测", styles['Heading2'])) + elements.append(Spacer(1, 0.1*inch)) + + long_short = predictions.get('long_short', {}) + + # 看多板块 + bullish = long_short.get('bullish', []) + if bullish: + elements.append(Paragraph("看多板块:", styles['Normal'])) + + for idx, item in enumerate(bullish, 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)) + + # 看空板块 + 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系统自动生成
", + styles['Normal'] + ) + elements.append(ending) + + return elements + + def _get_styles(self) -> dict: + """获取样式""" + styles = getSampleStyleSheet() + + # 自定义样式 + custom_styles = { + 'Title': ParagraphStyle( + 'CustomTitle', + parent=styles['Title'], + fontName=self.chinese_font, + fontSize=24, + textColor=colors.HexColor('#667eea'), + spaceAfter=30, + alignment=TA_CENTER + ), + 'Heading1': ParagraphStyle( + 'CustomHeading1', + parent=styles['Heading1'], + fontName=self.chinese_font, + fontSize=16, + textColor=colors.HexColor('#667eea'), + spaceAfter=12, + spaceBefore=12 + ), + 'Heading2': ParagraphStyle( + 'CustomHeading2', + parent=styles['Heading2'], + fontName=self.chinese_font, + fontSize=14, + textColor=colors.HexColor('#764ba2'), + spaceAfter=10, + spaceBefore=10 + ), + 'Normal': ParagraphStyle( + 'CustomNormal', + parent=styles['Normal'], + fontName=self.chinese_font, + fontSize=11, + leading=16, + alignment=TA_JUSTIFY + ), + 'Small': ParagraphStyle( + 'CustomSmall', + parent=styles['Normal'], + fontName=self.chinese_font, + fontSize=9, + leading=14, + alignment=TA_LEFT + ) + } + + return custom_styles + + +# 测试函数 +if __name__ == "__main__": + # 创建测试数据 + test_data = { + "success": True, + "timestamp": "2024-01-15 10:30:00", + "final_predictions": { + "long_short": { + "bullish": [ + { + "sector": "电子", + "confidence": 8, + "reason": "政策支持,资金持续流入", + "risk": "估值偏高,注意回调风险" + } + ], + "bearish": [] + }, + "rotation": { + "current_strong": [], + "potential": [], + "declining": [] + }, + "heat": { + "hottest": [ + {"sector": "电子", "score": 95, "trend": "升温", "sustainability": "强"} + ] + }, + "summary": { + "market_view": "市场整体向好", + "key_opportunity": "科技板块", + "major_risk": "估值风险", + "strategy": "积极配置科技" + } + }, + "agents_analysis": {}, + "comprehensive_report": "综合研判内容..." + } + + generator = SectorStrategyPDFGenerator() + output_path = generator.generate_pdf(test_data) + print(f"测试PDF生成: {output_path}") + diff --git a/sector_strategy_ui.py b/sector_strategy_ui.py new file mode 100644 index 0000000..da1f58f --- /dev/null +++ b/sector_strategy_ui.py @@ -0,0 +1,610 @@ +""" +智策UI界面模块 +展示板块分析结果和预测 +""" + +import streamlit as st +import plotly.graph_objects as go +import plotly.express as px +import pandas as pd +from datetime import datetime +import time +import base64 + +from sector_strategy_data import SectorStrategyDataFetcher +from sector_strategy_engine import SectorStrategyEngine +from sector_strategy_pdf import SectorStrategyPDFGenerator + + +def display_sector_strategy(): + """显示智策板块分析主界面""" + + st.markdown(""" +
+

🎯 智策 - AI驱动的板块策略分析

+ +
+ """, unsafe_allow_html=True) + + st.markdown("---") + + # 功能说明 + with st.expander("💡 智策系统介绍", expanded=False): + st.markdown(""" + ### 🌟 系统特色 + + **智策**是基于多AI智能体的板块策略分析系统,通过四位专业分析师的协同工作,为您提供全方位的板块投资决策支持。 + + ### 🤖 AI智能体团队 + + 1. **🌐 宏观策略师** + - 分析宏观经济形势和政策导向 + - 解读财经新闻对市场的影响 + - 识别行业发展趋势 + + 2. **📊 板块诊断师** + - 深入分析板块走势和估值 + - 评估板块基本面和成长性 + - 预判板块轮动方向 + + 3. **💰 资金流向分析师** + - 跟踪主力资金的板块流向 + - 分析北向资金的偏好 + - 识别资金轮动信号 + + 4. **📈 市场情绪解码员** + - 量化市场情绪指标 + - 识别恐慌贪婪信号 + - 评估板块热度 + + ### 📊 核心预测 + + - **板块多空**: 看多/看空板块推荐 + - **板块轮动**: 强势/潜力/衰退板块识别 + - **板块热度**: 热度排行和升降温趋势 + + ### 📈 数据来源 + + 所有数据来自**AKShare**开源库,包括: + - 行业板块和概念板块行情 + - 板块资金流向数据 + - 北向资金数据 + - 市场统计数据 + - 财经新闻数据 + """) + + st.markdown("---") + + # 模型选择 + col1, col2, col3 = st.columns([2, 2, 2]) + + with col1: + selected_model = st.selectbox( + "选择AI模型", + ["deepseek-chat", "deepseek-reasoner"], + help="Reasoner模型提供更强的推理能力" + ) + + with col2: + st.write("") + st.write("") + analyze_button = st.button("🚀 开始智策分析", type="primary", use_container_width=True) + + with col3: + st.write("") + st.write("") + if st.button("🔄 清除结果", use_container_width=True): + if 'sector_strategy_result' in st.session_state: + del st.session_state.sector_strategy_result + st.success("已清除分析结果") + st.rerun() + + st.markdown("---") + + # 开始分析 + if analyze_button: + # 清除之前的结果 + if 'sector_strategy_result' in st.session_state: + del st.session_state.sector_strategy_result + + run_sector_strategy_analysis(selected_model) + + # 显示分析结果 + if 'sector_strategy_result' in st.session_state: + result = st.session_state.sector_strategy_result + + if result.get("success"): + display_analysis_results(result) + else: + st.error(f"❌ 分析失败: {result.get('error', '未知错误')}") + + +def run_sector_strategy_analysis(model="deepseek-chat"): + """运行智策分析""" + + # 进度显示 + progress_bar = st.progress(0) + status_text = st.empty() + + try: + # 1. 获取数据 + status_text.text("📊 正在获取市场数据...") + progress_bar.progress(10) + + fetcher = SectorStrategyDataFetcher() + data = fetcher.get_all_sector_data() + + if not data.get("success"): + st.error("❌ 数据获取失败") + return + + progress_bar.progress(30) + status_text.text("✓ 数据获取完成") + + # 显示数据摘要 + display_data_summary(data) + + # 2. 运行AI分析 + status_text.text("🤖 AI智能体团队正在分析,预计需要10分钟...") + progress_bar.progress(40) + + engine = SectorStrategyEngine(model=model) + result = engine.run_comprehensive_analysis(data) + + progress_bar.progress(90) + + if result.get("success"): + # 保存结果 + st.session_state.sector_strategy_result = result + + progress_bar.progress(100) + status_text.text("✅ 分析完成!") + + time.sleep(1) + status_text.empty() + progress_bar.empty() + + # 自动刷新显示结果 + st.rerun() + else: + st.error(f"❌ 分析失败: {result.get('error', '未知错误')}") + + except Exception as e: + st.error(f"❌ 分析过程出错: {str(e)}") + import traceback + st.code(traceback.format_exc()) + finally: + progress_bar.empty() + status_text.empty() + + +def display_data_summary(data): + """显示数据摘要""" + st.subheader("📊 市场数据概览") + + col1, col2, col3, col4 = st.columns(4) + + market = data.get("market_overview", {}) + + with col1: + if market.get("sh_index"): + sh = market["sh_index"] + st.metric( + "上证指数", + f"{sh['close']:.2f}", + f"{sh['change_pct']:+.2f}%" + ) + + with col2: + if market.get("up_count"): + st.metric( + "上涨股票", + market['up_count'], + f"{market['up_ratio']:.1f}%" + ) + + with col3: + sectors_count = len(data.get("sectors", {})) + st.metric("行业板块", sectors_count) + + with col4: + concepts_count = len(data.get("concepts", {})) + st.metric("概念板块", concepts_count) + + +def display_analysis_results(result): + """显示分析结果""" + + st.success("✅ 智策分析完成!") + st.info(f"📅 分析时间: {result.get('timestamp', 'N/A')}") + + # PDF导出功能 + display_pdf_export_section(result) + + st.markdown("---") + + # 创建标签页 + tab1, tab2, tab3, tab4 = st.tabs([ + "📋 核心预测", + "🤖 智能体分析", + "📊 综合研判", + "📈 数据可视化" + ]) + + # Tab 1: 核心预测 + with tab1: + display_predictions(result.get("final_predictions", {})) + + # Tab 2: 智能体分析 + with tab2: + display_agents_reports(result.get("agents_analysis", {})) + + # Tab 3: 综合研判 + with tab3: + display_comprehensive_report(result.get("comprehensive_report", "")) + + # Tab 4: 数据可视化 + with tab4: + display_visualizations(result.get("final_predictions", {})) + + +def display_predictions(predictions): + """显示核心预测""" + + st.subheader("🎯 智策核心预测") + + if not predictions or predictions.get("prediction_text"): + # 文本格式 + st.markdown("### 预测报告") + st.write(predictions.get("prediction_text", "暂无预测")) + return + + # JSON格式预测 + + # 1. 板块多空 + st.markdown("### 📊 板块多空预测") + + col1, col2 = st.columns(2) + + with col1: + st.markdown("#### 🟢 看多板块") + bullish = predictions.get("long_short", {}).get("bullish", []) + if bullish: + for item in bullish: + st.markdown(f""" +
+

{item.get('sector', 'N/A')}

+

信心度: {item.get('confidence', 0)}/10

+

理由: {item.get('reason', '')}

+

风险: {item.get('risk', '')}

+
+ """, unsafe_allow_html=True) + else: + st.info("暂无看多板块") + + with col2: + st.markdown("#### 🔴 看空板块") + bearish = predictions.get("long_short", {}).get("bearish", []) + if bearish: + for item in bearish: + st.markdown(f""" +
+

{item.get('sector', 'N/A')}

+

信心度: {item.get('confidence', 0)}/10

+

理由: {item.get('reason', '')}

+

风险: {item.get('risk', '')}

+
+ """, unsafe_allow_html=True) + else: + st.info("暂无看空板块") + + st.markdown("---") + + # 2. 板块轮动 + st.markdown("### 🔄 板块轮动预测") + + rotation = predictions.get("rotation", {}) + + col1, col2, col3 = st.columns(3) + + with col1: + st.markdown("#### 💪 当前强势") + current_strong = rotation.get("current_strong", []) + for item in current_strong: + st.markdown(f""" + **{item.get('sector', 'N/A')}** + - 时间窗口: {item.get('time_window', 'N/A')} + - 逻辑: {item.get('logic', '')[:50]}... + - 建议: {item.get('advice', '')} + """) + + with col2: + st.markdown("#### 🌱 潜力接力") + potential = rotation.get("potential", []) + for item in potential: + st.markdown(f""" + **{item.get('sector', 'N/A')}** + - 时间窗口: {item.get('time_window', 'N/A')} + - 逻辑: {item.get('logic', '')[:50]}... + - 建议: {item.get('advice', '')} + """) + + with col3: + st.markdown("#### 📉 衰退板块") + declining = rotation.get("declining", []) + for item in declining: + st.markdown(f""" + **{item.get('sector', 'N/A')}** + - 时间窗口: {item.get('time_window', 'N/A')} + - 逻辑: {item.get('logic', '')[:50]}... + - 建议: {item.get('advice', '')} + """) + + st.markdown("---") + + # 3. 板块热度 + st.markdown("### 🔥 板块热度排行") + + heat = predictions.get("heat", {}) + + col1, col2, col3 = st.columns(3) + + with col1: + st.markdown("#### 🔥 最热板块") + hottest = heat.get("hottest", []) + for idx, item in enumerate(hottest, 1): + st.metric( + f"{idx}. {item.get('sector', 'N/A')}", + f"{item.get('score', 0)}分", + f"{item.get('trend', 'N/A')}" + ) + + with col2: + st.markdown("#### 📈 升温板块") + heating = heat.get("heating", []) + for idx, item in enumerate(heating, 1): + st.metric( + f"{idx}. {item.get('sector', 'N/A')}", + f"{item.get('score', 0)}分", + "↗️ 升温" + ) + + with col3: + st.markdown("#### 📉 降温板块") + cooling = heat.get("cooling", []) + for idx, item in enumerate(cooling, 1): + st.metric( + f"{idx}. {item.get('sector', 'N/A')}", + f"{item.get('score', 0)}分", + "↘️ 降温" + ) + + st.markdown("---") + + # 4. 总结建议 + summary = predictions.get("summary", {}) + if summary: + st.markdown("### 📝 策略总结") + + col1, col2 = st.columns(2) + + with col1: + st.markdown(f""" +
+

💡 市场观点

+

{summary.get('market_view', 'N/A')}

+
+ """, unsafe_allow_html=True) + + st.markdown(f""" +
+

🎯 核心机会

+

{summary.get('key_opportunity', 'N/A')}

+
+ """, unsafe_allow_html=True) + + with col2: + st.markdown(f""" +
+

⚠️ 主要风险

+

{summary.get('major_risk', 'N/A')}

+
+ """, unsafe_allow_html=True) + + st.markdown(f""" +
+

📋 整体策略

+

{summary.get('strategy', 'N/A')}

+
+ """, unsafe_allow_html=True) + + +def display_agents_reports(agents_analysis): + """显示智能体分析报告""" + + st.subheader("🤖 AI智能体分析报告") + + if not agents_analysis: + st.info("暂无智能体分析数据") + return + + # 创建子标签页 + agent_names = [] + agent_data = [] + + for key, value in agents_analysis.items(): + agent_names.append(value.get("agent_name", "未知分析师")) + agent_data.append(value) + + tabs = st.tabs(agent_names) + + for idx, tab in enumerate(tabs): + with tab: + agent = agent_data[idx] + + st.markdown(f""" +
+

👨‍💼 {agent.get('agent_name', '未知')}

+

职责: {agent.get('agent_role', '未知')}

+

关注领域: {', '.join(agent.get('focus_areas', []))}

+

分析时间: {agent.get('timestamp', '未知')}

+
+ """, unsafe_allow_html=True) + + st.markdown("---") + + st.markdown("### 📄 分析报告") + st.write(agent.get("analysis", "暂无分析")) + + +def display_comprehensive_report(report): + """显示综合研判报告""" + + st.subheader("📊 综合研判报告") + + if not report: + st.info("暂无综合研判数据") + return + + st.markdown(""" +
+

🎯 智策综合研判

+

基于四位专业分析师的深度分析,形成的全面市场和板块研判

+
+ """, unsafe_allow_html=True) + + st.markdown("---") + + st.write(report) + + +def display_visualizations(predictions): + """显示数据可视化""" + + st.subheader("📈 数据可视化") + + if not predictions or predictions.get("prediction_text"): + st.info("暂无可视化数据") + return + + # 1. 板块多空雷达图 + st.markdown("### 📊 板块多空信心度对比") + + bullish = predictions.get("long_short", {}).get("bullish", []) + bearish = predictions.get("long_short", {}).get("bearish", []) + + if bullish or bearish: + # 准备数据 + sectors = [] + confidence = [] + types = [] + + for item in bullish[:5]: + sectors.append(item.get('sector', 'N/A')) + confidence.append(item.get('confidence', 0)) + types.append('看多') + + for item in bearish[:5]: + sectors.append(item.get('sector', 'N/A')) + confidence.append(-item.get('confidence', 0)) # 负值表示看空 + types.append('看空') + + # 创建条形图 + df = pd.DataFrame({ + '板块': sectors, + '信心度': confidence, + '类型': types + }) + + fig = px.bar(df, x='板块', y='信心度', color='类型', + color_discrete_map={'看多': '#4caf50', '看空': '#f44336'}, + title='板块多空信心度对比') + + fig.update_layout(height=400) + st.plotly_chart(fig, use_container_width=True, key="sector_confidence") + + st.markdown("---") + + # 2. 板块热度分布 + st.markdown("### 🔥 板块热度分布") + + heat = predictions.get("heat", {}) + hottest = heat.get("hottest", []) + heating = heat.get("heating", []) + + if hottest or heating: + sectors = [] + scores = [] + trends = [] + + for item in hottest: + sectors.append(item.get('sector', 'N/A')) + scores.append(item.get('score', 0)) + trends.append('最热') + + for item in heating: + sectors.append(item.get('sector', 'N/A')) + scores.append(item.get('score', 0)) + trends.append('升温') + + df = pd.DataFrame({ + '板块': sectors, + '热度': scores, + '趋势': trends + }) + + fig = px.scatter(df, x='板块', y='热度', size='热度', color='趋势', + color_discrete_map={'最热': '#ff5722', '升温': '#ff9800'}, + title='板块热度分布图') + + fig.update_layout(height=400) + st.plotly_chart(fig, use_container_width=True, key="sector_heat") + + +def display_pdf_export_section(result): + """显示PDF导出部分""" + st.subheader("📄 导出报告") + + col1, col2, col3 = st.columns([2, 1, 1]) + + with col1: + st.write("将分析报告导出为PDF文件,方便保存和分享") + + with col2: + if st.button("📥 生成PDF报告", type="primary", use_container_width=True): + with st.spinner("正在生成PDF报告..."): + try: + # 生成PDF + generator = SectorStrategyPDFGenerator() + pdf_path = generator.generate_pdf(result) + + # 读取PDF文件 + with open(pdf_path, "rb") as f: + pdf_bytes = f.read() + + # 保存到session_state + st.session_state.sector_pdf_data = pdf_bytes + st.session_state.sector_pdf_filename = f"智策报告_{result.get('timestamp', datetime.now().strftime('%Y%m%d_%H%M%S')).replace(':', '').replace(' ', '_')}.pdf" + + st.success("✅ PDF报告生成成功!") + st.rerun() + + except Exception as e: + st.error(f"❌ PDF生成失败: {str(e)}") + + with col3: + # 如果已经生成了PDF,显示下载按钮 + if 'sector_pdf_data' in st.session_state: + st.download_button( + label="💾 下载PDF", + data=st.session_state.sector_pdf_data, + file_name=st.session_state.sector_pdf_filename, + mime="application/pdf", + use_container_width=True + ) + + +# 主入口 +if __name__ == "__main__": + display_sector_strategy() + diff --git a/sector_strategy_ui_clean.py b/sector_strategy_ui_clean.py new file mode 100644 index 0000000..e69de29 diff --git a/智策板块使用指南.md b/智策板块使用指南.md new file mode 100644 index 0000000..2841f7f --- /dev/null +++ b/智策板块使用指南.md @@ -0,0 +1,298 @@ +# 智策板块使用指南 + +## 📋 功能概述 + +**智策**是基于多AI智能体的板块策略分析系统,通过四位专业分析师的协同工作,为您提供全方位的板块投资决策支持。 + +## 🎯 核心功能 + +### 1. 板块多空预测 +- **看多板块**:推荐未来1-2周看涨的板块(5-8个) +- **看空板块**:推荐未来1-2周看跌的板块(3-5个) +- **中性板块**:走势不明朗的板块(2-3个) + +每个预测包含: +- 板块名称 +- 多空判断 +- 推荐理由 +- 信心度(1-10分) +- 风险提示 + +### 2. 板块轮动预测 +- **当前强势板块**:正在走强的板块 +- **潜力接力板块**:可能轮动到的板块 +- **衰退板块**:正在走弱的板块 + +每个预测包含: +- 轮动阶段判断 +- 轮动逻辑分析 +- 预计时间窗口 +- 操作建议 + +### 3. 板块热度排行 +- **最热板块TOP5**:综合资金、情绪、涨幅 +- **升温板块TOP5**:热度快速上升的板块 +- **降温板块TOP3**:热度快速下降的板块 + +每个板块给出: +- 热度评分(0-100分) +- 热度变化趋势 +- 持续性评估 + +## 🤖 AI智能体团队 + +### 1. 🌐 宏观策略师 +**职责**: +- 分析国际国内新闻和宏观经济数据 +- 判断对整体市场和不同板块的潜在影响 +- 识别政策导向和宏观趋势 + +**关注领域**: +- 宏观经济形势 +- 政策解读(货币政策、财政政策) +- 国际环境影响 +- 市场风险偏好 + +### 2. 📊 板块诊断师 +**职责**: +- 深入分析板块的历史走势 +- 评估板块的估值水平 +- 分析板块的成长性和基本面因素 + +**关注领域**: +- 板块强弱分析 +- 估值与位置判断 +- 板块轮动特征 +- 技术形态分析 + +### 3. 💰 资金流向分析师 +**职责**: +- 实时跟踪主力资金在板块间的流动 +- 分析北向资金的板块偏好 +- 判断资金进攻或撤离的方向 + +**关注领域**: +- 主力资金流向 +- 北向资金偏好 +- 板块资金轮动 +- 量价配合分析 + +### 4. 📈 市场情绪解码员 +**职责**: +- 从多维度解读市场情绪 +- 量化市场情绪指标 +- 识别过度乐观或恐慌信号 + +**关注领域**: +- 市场情绪评估 +- 赚钱效应分析 +- 恐慌贪婪指数 +- 板块热度识别 + +## 📊 数据来源 + +所有数据来自**AKShare**开源库,包括: + +1. **行业板块数据** + - 板块实时行情 + - 板块涨跌幅排行 + - 领涨股票信息 + +2. **概念板块数据** + - 概念板块行情 + - 热门概念排行 + +3. **资金流向数据** + - 行业资金流向(今日、3日、5日、10日) + - 主力资金净流入 + - 超大单、大单、中单、小单流向 + +4. **市场统计数据** + - 涨跌家数 + - 涨停跌停数量 + - 大盘指数表现 + +5. **北向资金数据** + - 沪股通、深股通资金流向 + - 北向资金历史趋势 + +6. **财经新闻数据** + - 东方财富财经快讯 + - 重要新闻事件 + +## 🚀 使用步骤 + +### 1. 进入智策板块 +在侧边栏点击 **"🎯 智策板块"** 按钮 + +### 2. 选择AI模型 +- **deepseek-chat**:标准模型,速度快 +- **deepseek-reasoner**:推理增强模型,分析更深入但速度较慢 + +### 3. 开始分析 +点击 **"🚀 开始智策分析"** 按钮 + +### 4. 等待分析完成 +系统将执行以下步骤: +1. 获取市场数据(30秒) +2. AI智能体团队分析(2-3分钟) +3. 综合研判 +4. 生成预测报告 + +### 5. 查看分析结果 +分析完成后,可以查看四个标签页: +- **📋 核心预测**:板块多空/轮动/热度预测 +- **🤖 智能体分析**:四位分析师的详细报告 +- **📊 综合研判**:团队综合讨论结果 +- **📈 数据可视化**:图表展示 + +### 6. 导出PDF报告 +点击"📥 生成PDF报告"按钮,系统会生成包含完整分析的PDF文件: +- 封面页 +- 市场概况 +- 核心预测(板块多空、轮动、热度) +- AI智能体分析摘要 +- 综合研判报告 + +## 💡 使用技巧 + +### 1. 最佳使用时间 +- **盘前**(8:30-9:30):获取前一交易日数据,制定当日策略 +- **盘中**(10:00-14:30):实时数据,调整策略 +- **盘后**(15:30-20:00):总结当日,布局明日 + +### 2. 结合多维度分析 +智策的预测综合了四个维度: +- **宏观面**:政策、新闻、经济环境 +- **基本面**:板块估值、成长性、基本面 +- **资金面**:主力资金、北向资金流向 +- **情绪面**:市场情绪、赚钱效应、热度 + +建议: +- 当四个维度共振时,信号更强 +- 出现分歧时,重点关注资金面和基本面 + +### 3. 关注信心度 +- **8-10分**:高信心,可重点关注 +- **5-7分**:中等信心,谨慎参与 +- **1-4分**:低信心,观望为主 + +### 4. 结合板块轮动 +- **当前强势板块**:可能已处于高位,注意风险 +- **潜力接力板块**:最佳布局时机 +- **衰退板块**:及时止损或规避 + +### 5. 热度判断 +- **最热板块**:关注度高,但可能透支 +- **升温板块**:热度上升,有机会 +- **降温板块**:关注度下降,注意风险 + +## ⚠️ 风险提示 + +1. **AI预测不是投资建议** + - 智策提供的是分析参考,不构成投资建议 + - 投资决策需要您自己判断 + +2. **市场风险** + - 股市有风险,投资需谨慎 + - 板块轮动可能快速变化 + - 黑天鹅事件无法预测 + +3. **数据时效性** + - 数据有一定延迟 + - 建议盘中实时验证 + +4. **模型局限性** + - AI模型基于历史数据训练 + - 极端市场环境下可能失效 + - 需要结合实际情况判断 + +## 🔧 技术说明 + +### 系统架构 +``` +数据采集 → AI智能体分析 → 综合研判 → 预测输出 + ↓ ↓ ↓ ↓ +AKShare 4位分析师 加权融合 多空/轮动/热度 +``` + +### 分析流程 +1. **数据采集**:从AKShare获取实时数据 +2. **特征工程**:数据清洗和特征提取 +3. **多智能体分析**:四位分析师并行分析 +4. **综合研判**:整合多维度分析 +5. **预测生成**:输出板块多空/轮动/热度 + +### 模型选择 +- **deepseek-chat**:适合日常使用,响应快 +- **deepseek-reasoner**:适合重要决策,推理能力强 + +## 📞 常见问题 + +### Q1: 分析需要多长时间? +A: 通常2-3分钟,包括: +- 数据获取:30秒 +- AI分析:1.5-2分钟 +- 综合研判:30秒 + +### Q2: 可以分析指定板块吗? +A: 当前版本分析所有板块,未来会增加指定板块分析功能。 + +### Q3: 预测准确率如何? +A: AI预测是基于多维度分析的综合判断,准确率取决于市场环境。建议: +- 高信心度预测准确率相对较高 +- 结合实际市场验证 +- 作为参考而非唯一依据 + +### Q4: 数据更新频率? +A: 每次点击"开始分析"都会获取最新数据。 + +### Q5: 可以保存分析结果吗? +A: 可以!系统支持导出PDF报告。 +- 分析完成后,点击"📥 生成PDF报告"按钮 +- 等待几秒钟生成完成 +- 点击"💾 下载PDF"按钮保存到本地 + +## 📈 使用案例 + +### 案例1:盘前策略制定 +**时间**:8:30 +**操作**: +1. 运行智策分析 +2. 查看"看多板块"TOP3 +3. 查看"潜力接力板块" +4. 制定当日关注列表 + +### 案例2:板块轮动捕捉 +**时间**:盘中 +**操作**: +1. 关注"当前强势板块"是否有资金流出迹象 +2. 观察"潜力接力板块"是否有资金流入 +3. 在轮动发生时及时切换 + +### 案例3:风险规避 +**时间**:盘后 +**操作**: +1. 查看持仓板块是否在"看空板块"中 +2. 查看是否在"衰退板块"中 +3. 查看是否在"降温板块"中 +4. 及时调整仓位 + +## 🔄 更新日志 + +### v1.0.0 (2024-01-15) +- ✨ 首次发布 +- 🤖 四位AI智能体分析师 +- 📊 板块多空/轮动/热度预测 +- 📈 数据可视化展示 + +## 📚 相关文档 + +- [快速开始指南](QUICK_START.md) +- [系统架构说明](README.md) +- [API配置指南](环境配置功能说明.md) + +--- + +**提示**:智策系统持续优化中,欢迎反馈使用体验! + diff --git a/智策板块快速开始.md b/智策板块快速开始.md new file mode 100644 index 0000000..c66174f --- /dev/null +++ b/智策板块快速开始.md @@ -0,0 +1,165 @@ +# 智策板块快速开始 + +## 🚀 5分钟快速上手 + +### 第一步:启动系统 +```bash +# 激活虚拟环境(如果使用) +venv\Scripts\activate + +# 启动应用 +streamlit run app.py +``` + +### 第二步:进入智策 +1. 在浏览器中打开 http://localhost:8501 +2. 在左侧边栏找到 **"🎯 智策板块"** 按钮 +3. 点击进入智策分析界面 + +### 第三步:开始分析 +1. 选择AI模型(建议初次使用选择 `deepseek-chat`) +2. 点击 **"🚀 开始智策分析"** 按钮 +3. 等待2-3分钟,系统会自动完成分析 + +### 第四步:查看结果 +分析完成后,查看四个标签页: + +#### 1. 📋 核心预测(最重要) +- **看多板块**:重点关注信心度≥7的板块 +- **板块轮动**:关注"潜力接力板块" +- **板块热度**:关注"升温板块" + +#### 2. 🤖 智能体分析 +- 查看四位分析师的详细报告 +- 了解不同维度的分析逻辑 + +#### 3. 📊 综合研判 +- 查看团队综合讨论结果 +- 了解多维度分析的权重 + +#### 4. 📈 数据可视化 +- 直观的图表展示 +- 板块对比分析 + +### 第五步:导出报告(可选) +1. 点击"📥 生成PDF报告"按钮 +2. 等待几秒钟生成完成 +3. 点击"💾 下载PDF"按钮 +4. PDF包含完整分析内容,方便保存和分享 + +## 💡 快速应用 + +### 场景1:今日盘前布局 +``` +1. 运行智策分析 +2. 找到"看多板块"TOP3 +3. 查看"潜力接力板块" +4. 在开盘后关注这些板块的龙头股 +``` + +### 场景2:持仓检查 +``` +1. 运行智策分析 +2. 查看持仓板块是否在"看空板块"中 +3. 查看是否在"衰退板块"或"降温板块"中 +4. 决定是否调整仓位 +``` + +### 场景3:捕捉轮动机会 +``` +1. 关注"当前强势板块"是否见顶 +2. 观察"潜力接力板块" +3. 在资金流入时提前布局 +``` + +## ⚡ 效率技巧 + +### 1. 盘前快速决策(5分钟) +- 只看"核心预测"标签页 +- 重点关注高信心度预测 +- 快速制定今日策略 + +### 2. 深度研究(15分钟) +- 查看全部四个标签页 +- 理解不同维度的分析逻辑 +- 形成完整的投资认知 + +### 3. 定期复盘(每周) +- 对比预测与实际走势 +- 总结成功和失败案例 +- 优化使用策略 + +## ⚠️ 新手注意事项 + +1. **AI预测不是投资建议** + - 仅供参考,不构成买卖依据 + - 需要结合自己的判断 + +2. **从小仓位开始** + - 初期用小仓位验证 + - 积累经验后再加大 + +3. **设置止损** + - 任何预测都可能失败 + - 必须设置止损保护 + +4. **分散投资** + - 不要全仓单一板块 + - 建议3-5个板块分散 + +5. **关注市场变化** + - 预测有时效性 + - 市场快速变化时及时调整 + +## 🎯 核心指标解读 + +### 信心度(1-10分) +- **8-10分**:高信心 → 可以重点关注 +- **5-7分**:中等信心 → 谨慎参与 +- **1-4分**:低信心 → 观望为主 + +### 板块轮动阶段 +- **强势**:正在走强,注意高位风险 +- **潜力**:可能接力,最佳布局时机 +- **衰退**:正在走弱,及时止损 + +### 热度评分(0-100分) +- **80-100分**:极热,可能透支 +- **60-79分**:较热,有关注度 +- **40-59分**:温和,适度关注 +- **0-39分**:冷清,关注度低 + +## 📞 遇到问题? + +### 常见错误处理 + +**错误1:数据获取失败** +``` +原因:网络问题或AKShare服务异常 +解决:检查网络连接,稍后重试 +``` + +**错误2:API调用失败** +``` +原因:DeepSeek API Key未配置或失效 +解决:在"⚙️ 环境配置"中检查API配置 +``` + +**错误3:分析超时** +``` +原因:网络慢或模型繁忙 +解决:重新运行分析,或更换时间段 +``` + +## 🔄 下一步 + +掌握基本使用后,建议: +1. 阅读[完整使用指南](智策板块使用指南.md) +2. 了解[四位AI分析师](智策板块使用指南.md#ai智能体团队)的分析逻辑 +3. 学习[使用技巧](智策板块使用指南.md#使用技巧) +4. 查看[案例分析](智策板块使用指南.md#使用案例) + +--- + +**开始您的智策之旅吧!** 🚀 +