""" 智策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()