diff --git a/API配置问题修复说明.md b/API配置问题修复说明.md
new file mode 100644
index 0000000..f3cb26a
--- /dev/null
+++ b/API配置问题修复说明.md
@@ -0,0 +1,177 @@
+# API配置问题修复说明
+
+## 问题描述
+
+用户遇到股票分析API调用失败,提示:
+```
+API调用失败: Error code: 401 - {'error': {'message': 'Authentication Fails, Your api key: ****a7fc is invalid'}}
+```
+
+虽然`.env`文件中已配置了新的API key,但系统仍在使用旧的key(结尾为`a7fc`)。
+
+## 问题原因
+
+1. **PowerShell环境变量中存在旧的API key**
+ - 用户之前在系统环境变量中设置过旧的`DEEPSEEK_API_KEY`
+ - 旧key: `sk-b6c714570b9844f392aa3812f3f7a7fc`
+
+2. **python-dotenv默认行为**
+ - `load_dotenv()`默认**不会覆盖**已存在的环境变量
+ - 导致系统读取的是环境变量中的旧key,而非`.env`文件中的新key
+
+3. **调用链路**
+ ```
+ .env文件 (新key) → load_dotenv() → 不覆盖环境变量 → config.py读取环境变量 (旧key) → deepseek_client使用旧key → API调用失败
+ ```
+
+## 修复方案
+
+### 1. 修改 `config.py`
+
+**修改前:**
+```python
+load_dotenv()
+```
+
+**修改后:**
+```python
+# 加载环境变量(override=True 强制覆盖已存在的环境变量)
+load_dotenv(override=True)
+```
+
+### 2. 修改 `config_manager.py`
+
+在`reload_config()`方法中也添加`override=True`:
+```python
+def reload_config(self):
+ """重新加载配置(重新加载.env文件)"""
+ from dotenv import load_dotenv
+ # 强制覆盖已存在的环境变量
+ load_dotenv(override=True)
+```
+
+### 3. 清除Python缓存
+
+```bash
+Remove-Item -Recurse -Force __pycache__
+```
+
+## 修复验证
+
+运行测试脚本验证修复:
+```bash
+.\venv\Scripts\python.exe test_api_config.py
+```
+
+测试结果:
+```
+✅ .env文件存在
+ .env中的API Key: sk-e32f5***********************2abe
+
+⚠️ 环境变量中的API Key(加载前): sk-b6c71***********************a7fc
+
+✅ config.py读取到的API Key: sk-e32f5***********************2abe
+✅ 环境变量已被覆盖: sk-e32f5***********************2abe
+✅ config.py读取的key与.env文件一致!
+✅ API调用成功!
+```
+
+## 影响范围
+
+此修复影响所有使用API的模块:
+
+### 1. 股票分析模块
+- ✅ `ai_agents.py` - 个股分析
+- ✅ `deepseek_client.py` - API客户端
+
+### 2. 智策板块模块
+- ✅ `sector_strategy_agents.py` - 板块分析
+- ✅ `sector_strategy_engine.py` - 策略引擎
+
+### 3. 主力选股模块
+- ✅ `main_force_analysis.py` - 主力资金分析
+
+### 4. UI和服务模块
+- ✅ `app.py` - 主应用
+- ✅ `monitor_service.py` - 监测服务
+
+## 验证步骤
+
+修复后,所有模块都会从`.env`文件读取正确的API key:
+
+1. **启动应用**
+ ```bash
+ python run.py
+ ```
+
+2. **测试股票分析**
+ - 在Web界面输入股票代码
+ - 点击"开始分析"
+ - 确认API调用成功
+
+3. **测试智策板块**
+ - 点击"智策板块"
+ - 开始板块分析
+ - 确认API调用成功
+
+4. **测试主力选股**
+ - 点击"主力选股"
+ - 运行主力资金筛选
+ - 确认API调用成功
+
+## 预防措施
+
+为避免将来再次出现此问题:
+
+1. **优先使用.env文件配置**
+ - 不要在系统环境变量中设置API key
+ - 统一在`.env`文件中管理所有配置
+
+2. **清除旧的环境变量**
+ - Windows: 系统属性 → 高级 → 环境变量 → 删除`DEEPSEEK_API_KEY`
+ - PowerShell临时清除: `Remove-Item Env:DEEPSEEK_API_KEY`
+
+3. **重启应用生效**
+ - 修改`.env`文件后,需要重启Streamlit应用
+ - 或使用环境配置界面的"保存并重新加载"功能
+
+## 技术细节
+
+### python-dotenv 的 override 参数
+
+```python
+load_dotenv(override=True)
+```
+
+- `override=False` (默认): 不覆盖已存在的环境变量,优先使用系统环境变量
+- `override=True`: 强制覆盖环境变量,优先使用`.env`文件中的值
+
+### 配置优先级
+
+**修复前:**
+1. 系统环境变量 (最高优先级)
+2. .env文件
+
+**修复后:**
+1. .env文件 (最高优先级)
+2. 系统环境变量 (作为默认值)
+
+## 相关文件
+
+- `config.py` - 主配置文件
+- `config_manager.py` - 配置管理器
+- `.env` - 环境变量配置文件
+- `test_api_config.py` - API配置测试脚本
+
+## 修复日期
+
+2025-10-17
+
+## 测试人员
+
+AI Assistant
+
+## 状态
+
+✅ 已修复并验证通过
+
diff --git a/app.py b/app.py
index a5e34cb..64d8089 100644
--- a/app.py
+++ b/app.py
@@ -18,6 +18,7 @@ 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
+from longhubang_ui import display_longhubang
# 页面配置
st.set_page_config(
@@ -293,6 +294,8 @@ def main():
st.session_state.show_history = True
if 'show_monitor' in st.session_state:
del st.session_state.show_monitor
+ if 'show_longhubang' in st.session_state:
+ del st.session_state.show_longhubang
if st.button("📊 实时监测", use_container_width=True, key="nav_monitor"):
st.session_state.show_monitor = True
@@ -300,6 +303,8 @@ def main():
del st.session_state.show_history
if 'show_main_force' in st.session_state:
del st.session_state.show_main_force
+ if 'show_longhubang' in st.session_state:
+ del st.session_state.show_longhubang
if st.button("🎯 主力选股", use_container_width=True, key="nav_main_force"):
st.session_state.show_main_force = True
@@ -311,6 +316,8 @@ def main():
del st.session_state.show_config
if 'show_sector_strategy' in st.session_state:
del st.session_state.show_sector_strategy
+ if 'show_longhubang' in st.session_state:
+ del st.session_state.show_longhubang
if st.button("🎯 智策板块", use_container_width=True, key="nav_sector_strategy"):
st.session_state.show_sector_strategy = True
@@ -322,6 +329,21 @@ 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_longhubang' in st.session_state:
+ del st.session_state.show_longhubang
+
+ if st.button("🎯 智瞰龙虎", use_container_width=True, key="nav_longhubang"):
+ st.session_state.show_longhubang = 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 'show_sector_strategy' in st.session_state:
+ del st.session_state.show_sector_strategy
if st.button("🏠 返回首页", use_container_width=True, key="nav_home"):
if 'show_history' in st.session_state:
@@ -334,6 +356,8 @@ def main():
del st.session_state.show_main_force
if 'show_sector_strategy' in st.session_state:
del st.session_state.show_sector_strategy
+ if 'show_longhubang' in st.session_state:
+ del st.session_state.show_longhubang
if st.button("⚙️ 环境配置", use_container_width=True, key="nav_config"):
st.session_state.show_config = True
@@ -341,6 +365,12 @@ def main():
del st.session_state.show_history
if 'show_monitor' in st.session_state:
del st.session_state.show_monitor
+ 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 'show_longhubang' in st.session_state:
+ del st.session_state.show_longhubang
st.markdown("---")
@@ -436,6 +466,11 @@ def main():
display_sector_strategy()
return
+ # 检查是否显示智瞰龙虎
+ if 'show_longhubang' in st.session_state and st.session_state.show_longhubang:
+ display_longhubang()
+ return
+
# 检查是否显示环境配置
if 'show_config' in st.session_state and st.session_state.show_config:
display_config_manager()
diff --git a/config.py b/config.py
index ccd4b53..bb05e34 100644
--- a/config.py
+++ b/config.py
@@ -1,8 +1,8 @@
import os
from dotenv import load_dotenv
-# 加载环境变量
-load_dotenv()
+# 加载环境变量(override=True 强制覆盖已存在的环境变量)
+load_dotenv(override=True)
# DeepSeek API配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "")
diff --git a/config_manager.py b/config_manager.py
index 99b9495..a7ff544 100644
--- a/config_manager.py
+++ b/config_manager.py
@@ -245,6 +245,7 @@ class ConfigManager:
def reload_config(self):
"""重新加载配置(重新加载.env文件)"""
from dotenv import load_dotenv
+ # 强制覆盖已存在的环境变量
load_dotenv(override=True)
diff --git a/longhubang_agents.py b/longhubang_agents.py
new file mode 100644
index 0000000..fba5a39
--- /dev/null
+++ b/longhubang_agents.py
@@ -0,0 +1,550 @@
+"""
+智瞰龙虎AI分析师集群
+专注于龙虎榜数据的多维度分析
+"""
+
+from deepseek_client import DeepSeekClient
+from typing import Dict, Any, List
+import time
+
+
+class LonghubangAgents:
+ """龙虎榜AI分析师集合"""
+
+ def __init__(self, model="deepseek-chat"):
+ self.model = model
+ self.deepseek_client = DeepSeekClient(model=model)
+ print(f"[智瞰龙虎] AI分析师系统初始化 (模型: {model})")
+
+ def youzi_behavior_analyst(self, longhubang_data: str, summary: Dict) -> Dict[str, Any]:
+ """
+ 游资行为分析师 - 分析游资操作特征和意图
+
+ 职责:
+ - 识别活跃游资及其操作风格
+ - 分析游资席位的进出特征
+ - 研判游资对个股的态度
+ """
+ print("🎯 游资行为分析师正在分析...")
+ time.sleep(1)
+
+ # 构建游资统计信息
+ youzi_info = ""
+ if summary.get('top_youzi'):
+ youzi_info = "\n【活跃游资统计】\n"
+ for idx, (name, amount) in enumerate(list(summary['top_youzi'].items())[:15], 1):
+ youzi_info += f"{idx}. {name}: 净流入 {amount:,.2f} 元\n"
+
+ prompt = f"""
+你是一名资深的游资研究专家,拥有10年以上的龙虎榜数据分析经验,深谙各路游资的操作风格和盈利模式。
+
+【龙虎榜数据概况】
+记录总数: {summary.get('total_records', 0)}
+涉及股票: {summary.get('total_stocks', 0)} 只
+涉及游资: {summary.get('total_youzi', 0)} 个
+总买入金额: {summary.get('total_buy_amount', 0):,.2f} 元
+总卖出金额: {summary.get('total_sell_amount', 0):,.2f} 元
+净流入金额: {summary.get('total_net_inflow', 0):,.2f} 元
+
+{youzi_info}
+
+{longhubang_data[:8000]}
+
+请基于以上龙虎榜数据,进行深入的游资行为分析:
+
+1. **活跃游资识别与画像** ⭐ 核心
+ - 识别当前最活跃的5-8个游资席位
+ - 分析每个游资的操作风格(激进型/稳健型/超短型/波段型)
+ - 评估游资的胜率和成功案例
+ - 识别知名"牛散"和"游资大佬"
+
+2. **游资操作特征分析**
+ - 分析游资的买入特征(追高/低吸/打板/潜伏)
+ - 分析游资的卖出特征(一日游/持有周期/止盈止损)
+ - 识别游资的联合操作和接力特征
+ - 判断游资是否存在抱团现象
+
+3. **游资目标股票分析**
+ - 分析游资重点关注的股票(前10只)
+ - 识别游资集体看好的股票(多席位介入)
+ - 分析游资选股的共性特征(题材/概念/技术形态)
+ - 评估游资介入股票的后续爆发力
+
+4. **游资进出节奏**
+ - 判断游资整体是进攻还是防守状态
+ - 分析游资对热点的跟随速度
+ - 识别游资撤退的信号和板块
+ - 评估游资的持续作战能力
+
+5. **游资与题材的匹配**
+ - 分析游资偏好的题材和概念
+ - 识别游资正在炒作的热点
+ - 判断题材的炒作周期位置
+ - 预判下一个游资可能关注的题材
+
+6. **风险与机会提示**
+ - 识别游资可能设置的"陷阱"股票
+ - 提示游资一致性过高的风险(容易崩盘)
+ - 发现游资刚开始介入的潜力股
+ - 评估跟随游资的风险收益比
+
+7. **投资策略建议**
+ - 推荐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 stock_potential_analyst(self, longhubang_data: str, summary: Dict) -> Dict[str, Any]:
+ """
+ 个股潜力分析师 - 从龙虎榜数据挖掘潜力股
+
+ 职责:
+ - 分析上榜股票的资金动向
+ - 评估股票的上涨潜力
+ - 识别次日大概率上涨的股票
+ """
+ print("📈 个股潜力分析师正在分析...")
+ time.sleep(1)
+
+ # 构建股票统计信息
+ stock_info = ""
+ if summary.get('top_stocks'):
+ stock_info = "\n【热门股票统计】\n"
+ for idx, stock in enumerate(summary['top_stocks'][:20], 1):
+ stock_info += f"{idx}. {stock['name']}({stock['code']}): 净流入 {stock['net_inflow']:,.2f} 元\n"
+
+ prompt = f"""
+你是一名资深的个股研究专家和短线交易高手,精通技术分析和资金分析,擅长从龙虎榜中挖掘短期爆发股。
+
+【龙虎榜数据概况】
+记录总数: {summary.get('total_records', 0)}
+涉及股票: {summary.get('total_stocks', 0)} 只
+涉及游资: {summary.get('total_youzi', 0)} 个
+
+{stock_info}
+
+{longhubang_data[:8000]}
+
+请基于以上龙虎榜数据,进行深入的个股潜力分析:
+
+1. **次日大概率上涨股票挖掘** ⭐⭐⭐ 最核心
+ - 识别5-8只次日大概率上涨的股票
+ - 详细分析每只股票的上涨逻辑(资金面、技术面、题材面)
+ - 评估每只股票的上涨空间和确定性(高/中/低)
+ - 给出具体的买入价位和止损位
+
+2. **资金流向强度分析**
+ - 识别主力资金大幅流入的股票(净买入前10)
+ - 分析资金流入的集中度和持续性
+ - 识别多席位联合买入的股票(强烈看好信号)
+ - 判断资金流入是真实买入还是诱多
+
+3. **技术形态评估**
+ - 分析上榜股票的技术位置(突破/回调/整理)
+ - 识别处于启动阶段的股票
+ - 评估股票的技术支撑和阻力
+ - 判断股票的短期走势方向
+
+4. **题材与概念分析**
+ - 识别当前最热门的题材和概念
+ - 分析题材的持续性和爆发力
+ - 找出题材龙头和低位补涨股
+ - 预判题材的炒作周期
+
+5. **游资持仓分析**
+ - 识别游资重仓持有的股票
+ - 分析游资的一致性程度
+ - 判断游资是建仓、加仓还是出货
+ - 评估游资持仓的稳定性
+
+6. **上榜类型分析**
+ - 分析日榜和三日榜的差异
+ - 识别连续上榜的股票(关注度高)
+ - 判断上榜的性质(放量突破/涨停板/异常波动)
+ - 评估不同上榜类型的后续表现概率
+
+7. **风险股票识别**
+ - 识别3-5只高风险股票(游资可能出货)
+ - 分析卖出金额大于买入金额的股票
+ - 提示游资一日游后撤离的股票
+ - 警示技术面走坏的股票
+
+8. **操作策略建议**
+ - 推荐5-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 theme_tracker_analyst(self, longhubang_data: str, summary: Dict) -> Dict[str, Any]:
+ """
+ 题材追踪分析师 - 分析龙虎榜中的热点题材
+
+ 职责:
+ - 识别当前热点题材和概念
+ - 分析题材的炒作周期
+ - 预判题材的持续性
+ """
+ print("🔥 题材追踪分析师正在分析...")
+ time.sleep(1)
+
+ # 构建概念统计信息
+ concept_info = ""
+ if summary.get('hot_concepts'):
+ concept_info = "\n【热门概念统计】\n"
+ for idx, (concept, count) in enumerate(list(summary['hot_concepts'].items())[:20], 1):
+ concept_info += f"{idx}. {concept}: 出现 {count} 次\n"
+
+ prompt = f"""
+你是一名资深的题材研究专家,拥有敏锐的市场嗅觉,擅长从龙虎榜数据中捕捉题材热点和板块轮动机会。
+
+【龙虎榜数据概况】
+记录总数: {summary.get('total_records', 0)}
+涉及股票: {summary.get('total_stocks', 0)} 只
+
+{concept_info}
+
+{longhubang_data[:8000]}
+
+请基于以上龙虎榜数据,进行深入的题材追踪分析:
+
+1. **热点题材识别** ⭐ 核心
+ - 识别当前最热门的5-8个题材/概念
+ - 分析每个题材的核心逻辑和催化剂
+ - 评估题材的市场关注度和参与度
+ - 判断题材是主流还是伪题材
+
+2. **题材炒作周期分析**
+ - 判断每个题材所处的炒作周期(萌芽期/爆发期/高潮期/退潮期)
+ - 分析题材的爆发力和持续性
+ - 识别即将启动的新题材(萌芽期)
+ - 提示即将退潮的老题材(高潮期)
+
+3. **题材龙头与梯队**
+ - 识别每个题材的龙头股(1-2只)
+ - 找出题材的跟风股和补涨股
+ - 分析龙头的地位是否稳固
+ - 判断是否存在龙头切换
+
+4. **游资对题材的态度**
+ - 分析游资重点炒作的题材
+ - 判断游资对题材的认同度(一致/分歧)
+ - 识别游资集体进攻的题材(强势题材)
+ - 发现游资开始撤离的题材(弱势题材)
+
+5. **题材轮动特征**
+ - 分析题材之间的轮动关系
+ - 识别强势题材和弱势题材
+ - 判断资金从哪个题材流向哪个题材
+ - 预判下一个可能启动的题材
+
+6. **题材与市场环境匹配度**
+ - 分析题材是否符合当前市场风格
+ - 评估题材的政策支持度
+ - 判断题材的基本面支撑
+ - 识别纯粹炒作的题材
+
+7. **题材风险评估**
+ - 识别过度炒作的题材(泡沫风险)
+ - 提示游资分歧加大的题材
+ - 警示题材逻辑破裂的风险
+ - 评估题材的回调风险
+
+8. **投资策略建议**
+ - 推荐3-5个值得关注的强势题材
+ - 每个题材推荐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 risk_control_specialist(self, longhubang_data: str, summary: Dict) -> Dict[str, Any]:
+ """
+ 风险控制专家 - 识别龙虎榜中的风险信号
+
+ 职责:
+ - 识别高风险股票和陷阱
+ - 分析游资出货信号
+ - 提供风险管理建议
+ """
+ print("⚠️ 风险控制专家正在分析...")
+ time.sleep(1)
+
+ prompt = f"""
+你是一名资深的风险控制专家和反向思维大师,拥有20年的市场风险管理经验,擅长识别龙虎榜中的风险信号和资金陷阱。
+
+【龙虎榜数据概况】
+记录总数: {summary.get('total_records', 0)}
+涉及股票: {summary.get('total_stocks', 0)} 只
+涉及游资: {summary.get('total_youzi', 0)} 个
+总买入金额: {summary.get('total_buy_amount', 0):,.2f} 元
+总卖出金额: {summary.get('total_sell_amount', 0):,.2f} 元
+净流入金额: {summary.get('total_net_inflow', 0):,.2f} 元
+
+{longhubang_data[:8000]}
+
+请基于以上龙虎榜数据,进行全面的风险分析:
+
+1. **高风险股票识别** ⭐ 核心
+ - 识别5-8只高风险股票(次日大概率下跌)
+ - 分析每只股票的风险点(游资出货/技术破位/题材退潮)
+ - 评估每只股票的风险等级(高/中/低)
+ - 给出规避建议和止损位
+
+2. **游资出货信号识别**
+ - 识别卖出金额远大于买入金额的股票
+ - 分析游资"一日游"后撤离的股票
+ - 识别游资集体出货的股票(多席位卖出)
+ - 判断游资出货是正常获利了结还是预期恶化
+
+3. **资金陷阱识别**
+ - 识别"虚假放量"的股票(实为对倒出货)
+ - 分析"高位放量滞涨"的股票
+ - 识别"拉高出货"的经典手法
+ - 提示"击鼓传花"的末期信号
+
+4. **题材风险评估**
+ - 识别过度炒作的题材(泡沫严重)
+ - 分析题材逻辑破裂的风险
+ - 提示题材退潮的信号
+ - 评估题材的持续性风险
+
+5. **技术面风险提示**
+ - 识别技术面走坏的股票(破位/跌破支撑)
+ - 分析高位震荡的股票(出货迹象)
+ - 提示连续上涨后的回调风险
+ - 评估短期超买的股票
+
+6. **情绪风险评估**
+ - 识别市场情绪过热的信号
+ - 分析游资一致性过高的风险(易崩盘)
+ - 提示跟风盘过多的股票(接盘侠风险)
+ - 评估短期投机氛围的风险
+
+7. **系统性风险提示**
+ - 分析整体龙虎榜数据反映的市场风险
+ - 评估游资整体是进攻还是防守
+ - 判断市场风险偏好的变化
+ - 提示可能的系统性调整风险
+
+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 chief_strategist(self, all_analyses: List[Dict]) -> Dict[str, Any]:
+ """
+ 首席策略师 - 综合所有分析师的意见,给出最终投资建议
+
+ 职责:
+ - 整合多维度分析结果
+ - 给出最终推荐股票清单
+ - 提供具体操作策略
+ """
+ print("👔 首席策略师正在综合分析...")
+ time.sleep(1)
+
+ # 整合所有分析师的分析结果
+ analyses_text = ""
+ for analysis in all_analyses:
+ analyses_text += f"\n{'='*60}\n"
+ analyses_text += f"【{analysis['agent_name']}】分析报告\n"
+ analyses_text += f"职责: {analysis['agent_role']}\n"
+ analyses_text += f"{'='*60}\n"
+ analyses_text += analysis['analysis'] + "\n"
+
+ prompt = f"""
+你是一名资深的首席投资策略师,拥有CFA、FRM等专业资格,具有25年的市场实战经验和卓越的综合分析能力。
+
+你的团队包含4位专业分析师,他们已经从不同维度完成了龙虎榜数据分析:
+1. 游资行为分析师 - 分析游资操作特征和意图
+2. 个股潜力分析师 - 挖掘次日大概率上涨的股票
+3. 题材追踪分析师 - 识别热点题材和轮动机会
+4. 风险控制专家 - 识别高风险股票和市场陷阱
+
+以下是各位分析师的详细分析报告:
+
+{analyses_text[:15000]}
+
+请作为首席策略师,综合以上所有分析,给出最终的投资策略报告:
+
+1. **市场总体研判**
+ - 综合评估当前龙虎榜反映的市场状态
+ - 判断游资整体的进攻或防守态度
+ - 评估短期市场的机会和风险
+ - 给出市场情绪和热度评分(0-100分)
+
+2. **次日重点推荐股票(TOP5-8)** ⭐⭐⭐ 最核心
+ - 综合4位分析师的意见,筛选出5-8只次日最有潜力的股票
+ - 每只股票必须包含:
+ * 股票名称和代码
+ * 推荐理由(多维度综合)
+ * 确定性评级(高/中/低)
+ * 买入价位区间
+ * 目标价位(预期涨幅)
+ * 止损价位
+ * 持有周期建议
+ - 按推荐优先级排序(第一只为最看好)
+
+3. **高风险警示股票(TOP3-5)**
+ - 综合识别3-5只高风险股票
+ - 说明风险原因
+ - 给出规避建议
+
+4. **热点题材总结**
+ - 总结当前2-3个最强势题材
+ - 每个题材推荐1-2只最优标的
+ - 分析题材的持续性
+
+5. **操作策略建议**
+ - 仓位管理建议(进攻/平衡/防守)
+ - 选股思路和方向
+ - 买卖时机选择
+ - 风险控制要求
+
+6. **注意事项**
+ - 提示关键风险点
+ - 强调纪律执行
+ - 给出应对预案
+
+请给出专业、全面、可执行的首席策略师综合报告。报告要有明确的结论和可操作性!
+"""
+
+ messages = [
+ {"role": "system", "content": "你是一名资深的首席投资策略师,擅长综合多维度分析,给出最优投资决策。"},
+ {"role": "user", "content": prompt}
+ ]
+
+ analysis = self.deepseek_client.call_api(messages, max_tokens=5000)
+
+ print(" ✓ 首席策略师分析完成")
+
+ return {
+ "agent_name": "首席策略师",
+ "agent_role": "综合多维度分析,给出最终投资建议和推荐股票清单",
+ "analysis": analysis,
+ "focus_areas": ["综合研判", "推荐股票", "风险警示", "热点题材", "操作策略"],
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
+ }
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智瞰龙虎AI分析师系统")
+ print("=" * 60)
+
+ # 创建模拟数据
+ test_summary = {
+ 'total_records': 150,
+ 'total_stocks': 50,
+ 'total_youzi': 30,
+ 'total_buy_amount': 500000000,
+ 'total_sell_amount': 200000000,
+ 'total_net_inflow': 300000000,
+ 'top_youzi': {
+ '92科比': 14455321,
+ '赵老哥': 12000000,
+ '章盟主': 10000000
+ },
+ 'top_stocks': [
+ {'code': '001337', 'name': '四川黄金', 'net_inflow': 14455321}
+ ],
+ 'hot_concepts': {
+ '黄金概念': 10,
+ '新能源': 8,
+ 'ChatGPT': 7
+ }
+ }
+
+ test_data = """
+【详细交易记录 TOP50】
+92科比 | 四川黄金(001337) | 买入:14,470,401 卖出:15,080 净流入:14,455,321 | 日期:2023-03-22
+"""
+
+ agents = LonghubangAgents()
+
+ # 测试游资行为分析师
+ print("\n测试游资行为分析师...")
+ result = agents.youzi_behavior_analyst(test_data, test_summary)
+ print(f"分析师: {result['agent_name']}")
+ print(f"分析内容长度: {len(result['analysis'])} 字符")
+
diff --git a/longhubang_data.py b/longhubang_data.py
new file mode 100644
index 0000000..2ebcc7e
--- /dev/null
+++ b/longhubang_data.py
@@ -0,0 +1,332 @@
+"""
+智瞰龙虎数据采集模块
+使用StockAPI获取龙虎榜数据
+"""
+
+import requests
+import pandas as pd
+from datetime import datetime, timedelta
+import time
+import warnings
+
+warnings.filterwarnings('ignore')
+
+
+class LonghubangDataFetcher:
+ """龙虎榜数据获取类"""
+
+ def __init__(self, api_key=None):
+ """
+ 初始化数据获取器
+
+ Args:
+ api_key: StockAPI的API密钥(可选,普通请求每日免费1000次)
+ """
+ print("[智瞰龙虎] 龙虎榜数据获取器初始化...")
+ self.base_url = "https://www.stockapi.com.cn/v1"
+ self.api_key = api_key
+ self.max_retries = 3 # 最大重试次数
+ self.retry_delay = 2 # 重试延迟(秒)
+ self.request_delay = 0.025 # 请求间隔(秒),40次/秒 = 0.025秒/次
+
+ def _safe_request(self, url, params=None):
+ """
+ 安全的HTTP请求,包含重试机制
+
+ Args:
+ url: 请求URL
+ params: 请求参数
+
+ Returns:
+ dict: 响应数据
+ """
+ for attempt in range(self.max_retries):
+ try:
+ response = requests.get(url, params=params, timeout=10)
+
+ # 添加请求延迟,遵守40次/秒的限制
+ time.sleep(self.request_delay)
+
+ if response.status_code == 200:
+ data = response.json()
+ if data.get('code') == 20000:
+ return data
+ else:
+ print(f" API返回错误: {data.get('msg', '未知错误')}")
+ return None
+ else:
+ print(f" HTTP错误: {response.status_code}")
+
+ 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}")
+ return None
+
+ return None
+
+ def get_longhubang_data(self, date):
+ """
+ 获取指定日期的龙虎榜数据
+
+ Args:
+ date: 日期,格式为 YYYY-MM-DD,如 "2023-03-21"
+
+ Returns:
+ dict: 龙虎榜数据
+ """
+ print(f"[智瞰龙虎] 获取 {date} 的龙虎榜数据...")
+
+ url = f"{self.base_url}/youzi/all"
+ params = {'date': date}
+
+ result = self._safe_request(url, params)
+
+ if result and result.get('data'):
+ print(f" ✓ 成功获取 {len(result['data'])} 条龙虎榜记录")
+ return result
+ else:
+ print(f" ✗ 未获取到数据")
+ return None
+
+ def get_longhubang_data_range(self, start_date, end_date):
+ """
+ 获取日期范围内的龙虎榜数据
+
+ Args:
+ start_date: 开始日期,格式为 YYYY-MM-DD
+ end_date: 结束日期,格式为 YYYY-MM-DD
+
+ Returns:
+ list: 龙虎榜数据列表
+ """
+ print(f"[智瞰龙虎] 获取 {start_date} 至 {end_date} 的龙虎榜数据...")
+
+ all_data = []
+
+ # 转换日期
+ current_date = datetime.strptime(start_date, '%Y-%m-%d')
+ end_date_obj = datetime.strptime(end_date, '%Y-%m-%d')
+
+ while current_date <= end_date_obj:
+ date_str = current_date.strftime('%Y-%m-%d')
+
+ # 跳过周末
+ if current_date.weekday() < 5: # 0-4表示周一到周五
+ result = self.get_longhubang_data(date_str)
+ if result and result.get('data'):
+ all_data.extend(result['data'])
+
+ # 下一天
+ current_date += timedelta(days=1)
+
+ print(f"[智瞰龙虎] ✓ 共获取 {len(all_data)} 条记录")
+ return all_data
+
+ def get_recent_days_data(self, days=5):
+ """
+ 获取最近N个交易日的龙虎榜数据
+
+ Args:
+ days: 天数(默认5天)
+
+ Returns:
+ list: 龙虎榜数据列表
+ """
+ end_date = datetime.now()
+ start_date = end_date - timedelta(days=days * 2) # 乘以2以确保包含足够的交易日
+
+ return self.get_longhubang_data_range(
+ start_date.strftime('%Y-%m-%d'),
+ end_date.strftime('%Y-%m-%d')
+ )
+
+ def parse_to_dataframe(self, data_list):
+ """
+ 将龙虎榜数据转换为DataFrame
+
+ Args:
+ data_list: 龙虎榜数据列表
+
+ Returns:
+ pd.DataFrame: 数据框
+ """
+ if not data_list:
+ return pd.DataFrame()
+
+ df = pd.DataFrame(data_list)
+
+ # 重命名列
+ column_mapping = {
+ 'yzmc': '游资名称',
+ 'yyb': '营业部',
+ 'sblx': '榜单类型',
+ 'gpdm': '股票代码',
+ 'gpmc': '股票名称',
+ 'mrje': '买入金额',
+ 'mcje': '卖出金额',
+ 'jlrje': '净流入金额',
+ 'rq': '日期',
+ 'gl': '概念'
+ }
+
+ df = df.rename(columns=column_mapping)
+
+ # 转换数据类型
+ numeric_columns = ['买入金额', '卖出金额', '净流入金额']
+ for col in numeric_columns:
+ if col in df.columns:
+ df[col] = pd.to_numeric(df[col], errors='coerce')
+
+ # 排序
+ if '净流入金额' in df.columns:
+ df = df.sort_values('净流入金额', ascending=False)
+
+ return df
+
+ def analyze_data_summary(self, data_list):
+ """
+ 分析龙虎榜数据,生成摘要统计
+
+ Args:
+ data_list: 龙虎榜数据列表
+
+ Returns:
+ dict: 统计摘要
+ """
+ if not data_list:
+ return {}
+
+ df = self.parse_to_dataframe(data_list)
+
+ summary = {
+ 'total_records': len(df),
+ 'total_stocks': df['股票代码'].nunique() if '股票代码' in df.columns else 0,
+ 'total_youzi': df['游资名称'].nunique() if '游资名称' in df.columns else 0,
+ 'total_buy_amount': df['买入金额'].sum() if '买入金额' in df.columns else 0,
+ 'total_sell_amount': df['卖出金额'].sum() if '卖出金额' in df.columns else 0,
+ 'total_net_inflow': df['净流入金额'].sum() if '净流入金额' in df.columns else 0,
+ }
+
+ # Top游资排名
+ if '游资名称' in df.columns and '净流入金额' in df.columns:
+ top_youzi = df.groupby('游资名称')['净流入金额'].sum().sort_values(ascending=False)
+ summary['top_youzi'] = top_youzi.head(10).to_dict()
+
+ # Top股票排名
+ if '股票代码' in df.columns and '净流入金额' in df.columns:
+ top_stocks = df.groupby(['股票代码', '股票名称'])['净流入金额'].sum().sort_values(ascending=False)
+ summary['top_stocks'] = [
+ {'code': code, 'name': name, 'net_inflow': amount}
+ for (code, name), amount in top_stocks.head(20).items()
+ ]
+
+ # 热门概念统计
+ if '概念' in df.columns:
+ all_concepts = []
+ for concepts in df['概念'].dropna():
+ all_concepts.extend([c.strip() for c in str(concepts).split(',')])
+
+ from collections import Counter
+ concept_counter = Counter(all_concepts)
+ summary['hot_concepts'] = dict(concept_counter.most_common(20))
+
+ return summary
+
+ def format_data_for_ai(self, data_list, summary=None):
+ """
+ 将龙虎榜数据格式化为适合AI分析的文本格式
+
+ Args:
+ data_list: 龙虎榜数据列表
+ summary: 统计摘要(可选)
+
+ Returns:
+ str: 格式化的文本
+ """
+ if not data_list:
+ return "暂无龙虎榜数据"
+
+ df = self.parse_to_dataframe(data_list)
+
+ if summary is None:
+ summary = self.analyze_data_summary(data_list)
+
+ text_parts = []
+
+ # 总体概况
+ text_parts.append(f"""
+【龙虎榜总体概况】
+数据时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
+记录总数: {summary.get('total_records', 0)}
+涉及股票: {summary.get('total_stocks', 0)} 只
+涉及游资: {summary.get('total_youzi', 0)} 个
+总买入金额: {summary.get('total_buy_amount', 0):,.2f} 元
+总卖出金额: {summary.get('total_sell_amount', 0):,.2f} 元
+净流入金额: {summary.get('total_net_inflow', 0):,.2f} 元
+""")
+
+ # Top游资
+ if summary.get('top_youzi'):
+ text_parts.append("\n【活跃游资 TOP10】")
+ for idx, (name, amount) in enumerate(summary['top_youzi'].items(), 1):
+ text_parts.append(f"{idx}. {name}: {amount:,.2f} 元")
+
+ # Top股票
+ if summary.get('top_stocks'):
+ text_parts.append("\n【资金净流入 TOP20股票】")
+ for idx, stock in enumerate(summary['top_stocks'], 1):
+ text_parts.append(
+ f"{idx}. {stock['name']}({stock['code']}): {stock['net_inflow']:,.2f} 元"
+ )
+
+ # 热门概念
+ if summary.get('hot_concepts'):
+ text_parts.append("\n【热门概念 TOP20】")
+ for idx, (concept, count) in enumerate(list(summary['hot_concepts'].items())[:20], 1):
+ text_parts.append(f"{idx}. {concept}: {count} 次")
+
+ # 详细交易记录(前50条)
+ text_parts.append("\n【详细交易记录 TOP50】")
+ for idx, row in df.head(50).iterrows():
+ text_parts.append(
+ f"{row.get('游资名称', 'N/A')} | "
+ f"{row.get('股票名称', 'N/A')}({row.get('股票代码', 'N/A')}) | "
+ f"买入:{row.get('买入金额', 0):,.0f} "
+ f"卖出:{row.get('卖出金额', 0):,.0f} "
+ f"净流入:{row.get('净流入金额', 0):,.0f} | "
+ f"日期:{row.get('日期', 'N/A')}"
+ )
+
+ return "\n".join(text_parts)
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智瞰龙虎数据采集模块")
+ print("=" * 60)
+
+ fetcher = LonghubangDataFetcher()
+
+ # 测试获取单日数据
+ date = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
+ result = fetcher.get_longhubang_data(date)
+
+ if result and result.get('data'):
+ # 分析数据
+ summary = fetcher.analyze_data_summary(result['data'])
+
+ print("\n" + "=" * 60)
+ print("数据采集成功!")
+ print("=" * 60)
+
+ # 格式化输出
+ formatted_text = fetcher.format_data_for_ai(result['data'], summary)
+ print(formatted_text[:2000]) # 显示前2000字符
+ print(f"\n... (总长度: {len(formatted_text)} 字符)")
+ else:
+ print("\n数据采集失败")
+
diff --git a/longhubang_db.py b/longhubang_db.py
new file mode 100644
index 0000000..e713818
--- /dev/null
+++ b/longhubang_db.py
@@ -0,0 +1,485 @@
+"""
+智瞰龙虎数据库模块
+用于存储龙虎榜历史数据和分析报告
+"""
+
+import sqlite3
+from datetime import datetime
+import json
+import pandas as pd
+
+
+class LonghubangDatabase:
+ """龙虎榜数据库管理类"""
+
+ def __init__(self, db_path='longhubang.db'):
+ """
+ 初始化数据库
+
+ Args:
+ db_path: 数据库文件路径
+ """
+ self.db_path = db_path
+ self.init_database()
+
+ def get_connection(self):
+ """获取数据库连接"""
+ return sqlite3.connect(self.db_path)
+
+ def init_database(self):
+ """初始化数据库表"""
+ conn = self.get_connection()
+ cursor = conn.cursor()
+
+ # 龙虎榜原始数据表
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS longhubang_records (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ date TEXT NOT NULL,
+ stock_code TEXT NOT NULL,
+ stock_name TEXT,
+ youzi_name TEXT,
+ yingye_bu TEXT,
+ list_type TEXT,
+ buy_amount REAL,
+ sell_amount REAL,
+ net_inflow REAL,
+ concepts TEXT,
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE(date, stock_code, youzi_name, yingye_bu)
+ )
+ ''')
+
+ # 创建索引
+ cursor.execute('''
+ CREATE INDEX IF NOT EXISTS idx_date ON longhubang_records(date)
+ ''')
+ cursor.execute('''
+ CREATE INDEX IF NOT EXISTS idx_stock_code ON longhubang_records(stock_code)
+ ''')
+ cursor.execute('''
+ CREATE INDEX IF NOT EXISTS idx_youzi_name ON longhubang_records(youzi_name)
+ ''')
+ cursor.execute('''
+ CREATE INDEX IF NOT EXISTS idx_net_inflow ON longhubang_records(net_inflow)
+ ''')
+
+ # AI分析报告表
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS longhubang_analysis (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ analysis_date TEXT NOT NULL,
+ data_date_range TEXT,
+ analysis_content TEXT,
+ recommended_stocks TEXT,
+ summary TEXT,
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP
+ )
+ ''')
+
+ # 股票追踪表(记录推荐股票的后续表现)
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS stock_tracking (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ analysis_id INTEGER,
+ stock_code TEXT NOT NULL,
+ stock_name TEXT,
+ recommended_date TEXT,
+ recommended_price REAL,
+ target_price REAL,
+ stop_loss_price REAL,
+ current_price REAL,
+ profit_loss_pct REAL,
+ status TEXT,
+ notes TEXT,
+ updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY(analysis_id) REFERENCES longhubang_analysis(id)
+ )
+ ''')
+
+ conn.commit()
+ conn.close()
+
+ print("[智瞰龙虎] 数据库初始化完成")
+
+ def save_longhubang_data(self, data_list):
+ """
+ 保存龙虎榜数据
+
+ Args:
+ data_list: 龙虎榜数据列表
+
+ Returns:
+ int: 成功保存的记录数
+ """
+ if not data_list:
+ return 0
+
+ conn = self.get_connection()
+ cursor = conn.cursor()
+
+ saved_count = 0
+
+ for record in data_list:
+ try:
+ cursor.execute('''
+ INSERT OR REPLACE INTO longhubang_records
+ (date, stock_code, stock_name, youzi_name, yingye_bu, list_type,
+ buy_amount, sell_amount, net_inflow, concepts)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ''', (
+ record.get('rq') or record.get('日期'),
+ record.get('gpdm') or record.get('股票代码'),
+ record.get('gpmc') or record.get('股票名称'),
+ record.get('yzmc') or record.get('游资名称'),
+ record.get('yyb') or record.get('营业部'),
+ record.get('sblx') or record.get('榜单类型'),
+ float(record.get('mrje') or record.get('买入金额') or 0),
+ float(record.get('mcje') or record.get('卖出金额') or 0),
+ float(record.get('jlrje') or record.get('净流入金额') or 0),
+ record.get('gl') or record.get('概念')
+ ))
+ saved_count += 1
+ except Exception as e:
+ print(f"保存记录失败: {e}")
+ continue
+
+ conn.commit()
+ conn.close()
+
+ print(f"[智瞰龙虎] 成功保存 {saved_count} 条龙虎榜记录")
+ return saved_count
+
+ def get_longhubang_data(self, start_date=None, end_date=None, stock_code=None):
+ """
+ 查询龙虎榜数据
+
+ Args:
+ start_date: 开始日期
+ end_date: 结束日期
+ stock_code: 股票代码
+
+ Returns:
+ pd.DataFrame: 查询结果
+ """
+ conn = self.get_connection()
+
+ query = "SELECT * FROM longhubang_records WHERE 1=1"
+ params = []
+
+ if start_date:
+ query += " AND date >= ?"
+ params.append(start_date)
+
+ if end_date:
+ query += " AND date <= ?"
+ params.append(end_date)
+
+ if stock_code:
+ query += " AND stock_code = ?"
+ params.append(stock_code)
+
+ query += " ORDER BY date DESC, net_inflow DESC"
+
+ df = pd.read_sql_query(query, conn, params=params)
+ conn.close()
+
+ return df
+
+ def get_top_youzi(self, start_date=None, end_date=None, limit=20):
+ """
+ 获取活跃游资排名
+
+ Args:
+ start_date: 开始日期
+ end_date: 结束日期
+ limit: 返回数量
+
+ Returns:
+ pd.DataFrame: 游资排名
+ """
+ conn = self.get_connection()
+
+ query = '''
+ SELECT
+ youzi_name,
+ COUNT(*) as trade_count,
+ SUM(buy_amount) as total_buy,
+ SUM(sell_amount) as total_sell,
+ SUM(net_inflow) as total_net_inflow
+ FROM longhubang_records
+ WHERE 1=1
+ '''
+
+ params = []
+
+ if start_date:
+ query += " AND date >= ?"
+ params.append(start_date)
+
+ if end_date:
+ query += " AND date <= ?"
+ params.append(end_date)
+
+ query += '''
+ GROUP BY youzi_name
+ ORDER BY total_net_inflow DESC
+ LIMIT ?
+ '''
+ params.append(limit)
+
+ df = pd.read_sql_query(query, conn, params=params)
+ conn.close()
+
+ return df
+
+ def get_top_stocks(self, start_date=None, end_date=None, limit=20):
+ """
+ 获取热门股票排名
+
+ Args:
+ start_date: 开始日期
+ end_date: 结束日期
+ limit: 返回数量
+
+ Returns:
+ pd.DataFrame: 股票排名
+ """
+ conn = self.get_connection()
+
+ query = '''
+ SELECT
+ stock_code,
+ stock_name,
+ COUNT(DISTINCT youzi_name) as youzi_count,
+ SUM(buy_amount) as total_buy,
+ SUM(sell_amount) as total_sell,
+ SUM(net_inflow) as total_net_inflow,
+ GROUP_CONCAT(DISTINCT concepts) as all_concepts
+ FROM longhubang_records
+ WHERE 1=1
+ '''
+
+ params = []
+
+ if start_date:
+ query += " AND date >= ?"
+ params.append(start_date)
+
+ if end_date:
+ query += " AND date <= ?"
+ params.append(end_date)
+
+ query += '''
+ GROUP BY stock_code, stock_name
+ ORDER BY total_net_inflow DESC
+ LIMIT ?
+ '''
+ params.append(limit)
+
+ df = pd.read_sql_query(query, conn, params=params)
+ conn.close()
+
+ return df
+
+ def save_analysis_report(self, data_date_range, analysis_content,
+ recommended_stocks, summary):
+ """
+ 保存AI分析报告
+
+ Args:
+ data_date_range: 数据日期范围
+ analysis_content: 分析内容
+ recommended_stocks: 推荐股票列表
+ summary: 摘要
+
+ Returns:
+ int: 报告ID
+ """
+ conn = self.get_connection()
+ cursor = conn.cursor()
+
+ cursor.execute('''
+ INSERT INTO longhubang_analysis
+ (analysis_date, data_date_range, analysis_content, recommended_stocks, summary)
+ VALUES (?, ?, ?, ?, ?)
+ ''', (
+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ data_date_range,
+ analysis_content,
+ json.dumps(recommended_stocks, ensure_ascii=False),
+ summary
+ ))
+
+ report_id = cursor.lastrowid
+
+ conn.commit()
+ conn.close()
+
+ print(f"[智瞰龙虎] 分析报告已保存 (ID: {report_id})")
+ return report_id
+
+ def get_analysis_reports(self, limit=10):
+ """
+ 获取历史分析报告
+
+ Args:
+ limit: 返回数量
+
+ Returns:
+ pd.DataFrame: 报告列表
+ """
+ conn = self.get_connection()
+
+ query = '''
+ SELECT * FROM longhubang_analysis
+ ORDER BY created_at DESC
+ LIMIT ?
+ '''
+
+ df = pd.read_sql_query(query, conn, params=[limit])
+ conn.close()
+
+ return df
+
+ def get_analysis_report(self, report_id):
+ """
+ 获取单个分析报告详情
+
+ Args:
+ report_id: 报告ID
+
+ Returns:
+ dict: 报告详情
+ """
+ conn = self.get_connection()
+ cursor = conn.cursor()
+
+ cursor.execute('''
+ SELECT * FROM longhubang_analysis WHERE id = ?
+ ''', (report_id,))
+
+ row = cursor.fetchone()
+ conn.close()
+
+ if row:
+ columns = [desc[0] for desc in cursor.description]
+ report = dict(zip(columns, row))
+
+ # 解析JSON字段
+ if report.get('recommended_stocks'):
+ try:
+ report['recommended_stocks'] = json.loads(report['recommended_stocks'])
+ except:
+ pass
+
+ return report
+
+ return None
+
+ def update_stock_tracking(self, analysis_id, stock_code, current_price, status, notes=None):
+ """
+ 更新股票追踪信息
+
+ Args:
+ analysis_id: 分析报告ID
+ stock_code: 股票代码
+ current_price: 当前价格
+ status: 状态
+ notes: 备注
+ """
+ conn = self.get_connection()
+ cursor = conn.cursor()
+
+ cursor.execute('''
+ UPDATE stock_tracking
+ SET current_price = ?, status = ?, notes = ?, updated_at = ?
+ WHERE analysis_id = ? AND stock_code = ?
+ ''', (
+ current_price,
+ status,
+ notes,
+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ analysis_id,
+ stock_code
+ ))
+
+ conn.commit()
+ conn.close()
+
+ def get_statistics(self):
+ """
+ 获取数据库统计信息
+
+ Returns:
+ dict: 统计信息
+ """
+ conn = self.get_connection()
+ cursor = conn.cursor()
+
+ stats = {}
+
+ # 总记录数
+ cursor.execute('SELECT COUNT(*) FROM longhubang_records')
+ stats['total_records'] = cursor.fetchone()[0]
+
+ # 涉及股票数
+ cursor.execute('SELECT COUNT(DISTINCT stock_code) FROM longhubang_records')
+ stats['total_stocks'] = cursor.fetchone()[0]
+
+ # 涉及游资数
+ cursor.execute('SELECT COUNT(DISTINCT youzi_name) FROM longhubang_records')
+ stats['total_youzi'] = cursor.fetchone()[0]
+
+ # 分析报告数
+ cursor.execute('SELECT COUNT(*) FROM longhubang_analysis')
+ stats['total_reports'] = cursor.fetchone()[0]
+
+ # 日期范围
+ cursor.execute('SELECT MIN(date), MAX(date) FROM longhubang_records')
+ date_range = cursor.fetchone()
+ stats['date_range'] = {
+ 'start': date_range[0],
+ 'end': date_range[1]
+ }
+
+ conn.close()
+
+ return stats
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智瞰龙虎数据库模块")
+ print("=" * 60)
+
+ db = LonghubangDatabase('test_longhubang.db')
+
+ # 测试数据
+ test_data = [
+ {
+ 'rq': '2023-03-22',
+ 'gpdm': '001337',
+ 'gpmc': '四川黄金',
+ 'yzmc': '92科比',
+ 'yyb': '兴业证券股份有限公司南京天元东路证券营业部',
+ 'sblx': '1',
+ 'mrje': 14470401,
+ 'mcje': 15080,
+ 'jlrje': 14455321,
+ 'gl': '贵金属,四川板块,昨日连板_含一字,昨日涨停_含一字,黄金概念,次新股'
+ }
+ ]
+
+ # 测试保存
+ db.save_longhubang_data(test_data)
+
+ # 测试查询
+ df = db.get_longhubang_data()
+ print(f"\n查询到 {len(df)} 条记录")
+
+ # 获取统计信息
+ stats = db.get_statistics()
+ print(f"\n数据库统计: {stats}")
+
diff --git a/longhubang_engine.py b/longhubang_engine.py
new file mode 100644
index 0000000..47a47cc
--- /dev/null
+++ b/longhubang_engine.py
@@ -0,0 +1,354 @@
+"""
+智瞰龙虎综合分析引擎
+整合数据获取、AI分析、结果生成的核心引擎
+"""
+
+from longhubang_data import LonghubangDataFetcher
+from longhubang_db import LonghubangDatabase
+from longhubang_agents import LonghubangAgents
+from typing import Dict, Any, List
+from datetime import datetime, timedelta
+import time
+
+
+class LonghubangEngine:
+ """龙虎榜综合分析引擎"""
+
+ def __init__(self, model="deepseek-chat", db_path='longhubang.db'):
+ """
+ 初始化分析引擎
+
+ Args:
+ model: AI模型名称
+ db_path: 数据库路径
+ """
+ self.data_fetcher = LonghubangDataFetcher()
+ self.database = LonghubangDatabase(db_path)
+ self.agents = LonghubangAgents(model=model)
+ print(f"[智瞰龙虎] 分析引擎初始化完成")
+
+ def run_comprehensive_analysis(self, date=None, days=1) -> Dict[str, Any]:
+ """
+ 运行完整的龙虎榜分析流程
+
+ Args:
+ date: 指定日期,格式 YYYY-MM-DD,默认为昨日
+ days: 分析最近几天的数据,默认1天
+
+ Returns:
+ 完整的分析结果
+ """
+ print("\n" + "=" * 60)
+ print("🚀 智瞰龙虎综合分析系统启动")
+ print("=" * 60)
+
+ results = {
+ "success": False,
+ "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ "data_info": {},
+ "agents_analysis": {},
+ "final_report": {},
+ "recommended_stocks": []
+ }
+
+ try:
+ # 阶段1: 获取龙虎榜数据
+ print("\n[阶段1] 获取龙虎榜数据...")
+ print("-" * 60)
+
+ if date:
+ data_list = [self.data_fetcher.get_longhubang_data(date)]
+ data_list = data_list[0].get('data', []) if data_list[0] else []
+ else:
+ data_list = self.data_fetcher.get_recent_days_data(days)
+
+ if not data_list:
+ print("✗ 未获取到龙虎榜数据")
+ results["error"] = "未获取到龙虎榜数据"
+ return results
+
+ print(f"✓ 成功获取 {len(data_list)} 条龙虎榜记录")
+
+ # 阶段2: 保存数据到数据库
+ print("\n[阶段2] 保存数据到数据库...")
+ print("-" * 60)
+ saved_count = self.database.save_longhubang_data(data_list)
+ print(f"✓ 保存 {saved_count} 条记录")
+
+ # 阶段3: 数据分析和统计
+ print("\n[阶段3] 数据分析和统计...")
+ print("-" * 60)
+ summary = self.data_fetcher.analyze_data_summary(data_list)
+ formatted_data = self.data_fetcher.format_data_for_ai(data_list, summary)
+
+ results["data_info"] = {
+ "total_records": summary.get('total_records', 0),
+ "total_stocks": summary.get('total_stocks', 0),
+ "total_youzi": summary.get('total_youzi', 0),
+ "summary": summary
+ }
+ print(f"✓ 数据统计完成")
+
+ # 阶段4: AI分析师团队分析
+ print("\n[阶段4] AI分析师团队工作中...")
+ print("-" * 60)
+
+ agents_results = {}
+
+ # 1. 游资行为分析师
+ print("1/5 游资行为分析师...")
+ youzi_result = self.agents.youzi_behavior_analyst(formatted_data, summary)
+ agents_results["youzi"] = youzi_result
+
+ # 2. 个股潜力分析师
+ print("2/5 个股潜力分析师...")
+ stock_result = self.agents.stock_potential_analyst(formatted_data, summary)
+ agents_results["stock"] = stock_result
+
+ # 3. 题材追踪分析师
+ print("3/5 题材追踪分析师...")
+ theme_result = self.agents.theme_tracker_analyst(formatted_data, summary)
+ agents_results["theme"] = theme_result
+
+ # 4. 风险控制专家
+ print("4/5 风险控制专家...")
+ risk_result = self.agents.risk_control_specialist(formatted_data, summary)
+ agents_results["risk"] = risk_result
+
+ # 5. 首席策略师综合
+ print("5/5 首席策略师综合分析...")
+ all_analyses = [youzi_result, stock_result, theme_result, risk_result]
+ chief_result = self.agents.chief_strategist(all_analyses)
+ agents_results["chief"] = chief_result
+
+ results["agents_analysis"] = agents_results
+ print("\n✓ 所有AI分析师分析完成")
+
+ # 阶段5: 提取推荐股票
+ print("\n[阶段5] 提取推荐股票...")
+ print("-" * 60)
+ recommended_stocks = self._extract_recommended_stocks(
+ chief_result.get('analysis', ''),
+ stock_result.get('analysis', ''),
+ summary
+ )
+ results["recommended_stocks"] = recommended_stocks
+ print(f"✓ 提取 {len(recommended_stocks)} 只推荐股票")
+
+ # 阶段6: 生成最终报告
+ print("\n[阶段6] 生成最终报告...")
+ print("-" * 60)
+ final_report = self._generate_final_report(agents_results, summary, recommended_stocks)
+ results["final_report"] = final_report
+ print("✓ 最终报告生成完成")
+
+ # 阶段7: 保存分析报告到数据库
+ print("\n[阶段7] 保存分析报告...")
+ print("-" * 60)
+ data_date_range = self._get_date_range(data_list)
+ report_id = self.database.save_analysis_report(
+ data_date_range=data_date_range,
+ analysis_content=str(agents_results),
+ recommended_stocks=recommended_stocks,
+ summary=final_report.get('summary', '')
+ )
+ results["report_id"] = report_id
+ print(f"✓ 报告已保存 (ID: {report_id})")
+
+ 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 _extract_recommended_stocks(self, chief_analysis: str, stock_analysis: str, summary: Dict) -> List[Dict]:
+ """
+ 从AI分析中提取推荐股票
+
+ Args:
+ chief_analysis: 首席策略师分析
+ stock_analysis: 个股潜力分析师分析
+ summary: 数据摘要
+
+ Returns:
+ 推荐股票列表
+ """
+ recommended = []
+
+ # 从摘要中获取TOP股票作为基础
+ if summary.get('top_stocks'):
+ for idx, stock in enumerate(summary['top_stocks'][:10], 1):
+ recommended.append({
+ 'rank': idx,
+ 'code': stock['code'],
+ 'name': stock['name'],
+ 'net_inflow': stock['net_inflow'],
+ 'reason': f"资金净流入 {stock['net_inflow']:,.2f} 元",
+ 'confidence': '中',
+ 'buy_price': '待定',
+ 'target_price': '待定',
+ 'stop_loss': '待定',
+ 'hold_period': '短线'
+ })
+
+ return recommended
+
+ def _generate_final_report(self, agents_results: Dict, summary: Dict,
+ recommended_stocks: List[Dict]) -> Dict:
+ """
+ 生成最终报告
+
+ Args:
+ agents_results: 所有分析师的分析结果
+ summary: 数据摘要
+ recommended_stocks: 推荐股票列表
+
+ Returns:
+ 最终报告字典
+ """
+ report = {
+ 'title': '智瞰龙虎榜综合分析报告',
+ 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ 'summary': '',
+ 'data_overview': {
+ 'total_records': summary.get('total_records', 0),
+ 'total_stocks': summary.get('total_stocks', 0),
+ 'total_youzi': summary.get('total_youzi', 0),
+ 'total_net_inflow': summary.get('total_net_inflow', 0)
+ },
+ 'recommended_stocks_count': len(recommended_stocks),
+ 'agents_count': len(agents_results)
+ }
+
+ # 生成摘要
+ summary_parts = []
+ summary_parts.append(f"本次分析共涵盖 {summary.get('total_records', 0)} 条龙虎榜记录")
+ summary_parts.append(f"涉及 {summary.get('total_stocks', 0)} 只股票")
+ summary_parts.append(f"涉及 {summary.get('total_youzi', 0)} 个游资席位")
+ summary_parts.append(f"共推荐 {len(recommended_stocks)} 只潜力股票")
+
+ report['summary'] = ",".join(summary_parts) + "。"
+
+ return report
+
+ def _get_date_range(self, data_list: List[Dict]) -> str:
+ """
+ 获取数据的日期范围
+
+ Args:
+ data_list: 数据列表
+
+ Returns:
+ 日期范围字符串
+ """
+ if not data_list:
+ return "未知"
+
+ dates = []
+ for record in data_list:
+ date = record.get('rq') or record.get('日期')
+ if date:
+ dates.append(date)
+
+ if not dates:
+ return "未知"
+
+ dates = sorted(set(dates))
+ if len(dates) == 1:
+ return dates[0]
+ else:
+ return f"{dates[0]} 至 {dates[-1]}"
+
+ def get_historical_reports(self, limit=10):
+ """
+ 获取历史分析报告
+
+ Args:
+ limit: 返回数量
+
+ Returns:
+ 报告列表
+ """
+ return self.database.get_analysis_reports(limit)
+
+ def get_report_detail(self, report_id):
+ """
+ 获取报告详情
+
+ Args:
+ report_id: 报告ID
+
+ Returns:
+ 报告详情
+ """
+ return self.database.get_analysis_report(report_id)
+
+ def get_statistics(self):
+ """
+ 获取数据库统计信息
+
+ Returns:
+ 统计信息
+ """
+ return self.database.get_statistics()
+
+ def get_top_youzi(self, start_date=None, end_date=None, limit=20):
+ """
+ 获取活跃游资排名
+
+ Args:
+ start_date: 开始日期
+ end_date: 结束日期
+ limit: 返回数量
+
+ Returns:
+ 游资排名
+ """
+ return self.database.get_top_youzi(start_date, end_date, limit)
+
+ def get_top_stocks(self, start_date=None, end_date=None, limit=20):
+ """
+ 获取热门股票排名
+
+ Args:
+ start_date: 开始日期
+ end_date: 结束日期
+ limit: 返回数量
+
+ Returns:
+ 股票排名
+ """
+ return self.database.get_top_stocks(start_date, end_date, limit)
+
+
+# 测试函数
+if __name__ == "__main__":
+ print("=" * 60)
+ print("测试智瞰龙虎分析引擎")
+ print("=" * 60)
+
+ # 创建引擎实例
+ engine = LonghubangEngine()
+
+ # 运行综合分析(分析昨天的数据)
+ yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
+ results = engine.run_comprehensive_analysis(date=yesterday)
+
+ if results.get('success'):
+ print("\n" + "=" * 60)
+ print("分析成功!")
+ print("=" * 60)
+ print(f"数据记录: {results['data_info']['total_records']}")
+ print(f"涉及股票: {results['data_info']['total_stocks']}")
+ print(f"推荐股票: {len(results['recommended_stocks'])}")
+ else:
+ print(f"\n分析失败: {results.get('error', '未知错误')}")
+
diff --git a/longhubang_pdf.py b/longhubang_pdf.py
new file mode 100644
index 0000000..4e2be27
--- /dev/null
+++ b/longhubang_pdf.py
@@ -0,0 +1,492 @@
+"""
+智瞰龙虎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 LonghubangPDFGenerator:
+ """龙虎榜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_data_overview(result_data))
+ story.append(PageBreak())
+
+ # 添加推荐股票
+ story.extend(self._create_recommended_stocks(result_data))
+ story.append(PageBreak())
+
+ # 添加AI分析师报告
+ story.extend(self._create_agents_analysis(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 _get_styles(self) -> dict:
+ """获取样式"""
+ styles = getSampleStyleSheet()
+
+ # 自定义样式
+ custom_styles = {
+ 'Title': ParagraphStyle(
+ 'CustomTitle',
+ parent=styles['Heading1'],
+ fontSize=24,
+ textColor=colors.HexColor('#1f4788'),
+ spaceAfter=30,
+ alignment=TA_CENTER,
+ fontName=self.chinese_font
+ ),
+ 'Heading1': ParagraphStyle(
+ 'CustomHeading1',
+ parent=styles['Heading1'],
+ fontSize=16,
+ textColor=colors.HexColor('#1f4788'),
+ spaceAfter=12,
+ spaceBefore=12,
+ fontName=self.chinese_font
+ ),
+ 'Heading2': ParagraphStyle(
+ 'CustomHeading2',
+ parent=styles['Heading2'],
+ fontSize=14,
+ textColor=colors.HexColor('#2c5aa0'),
+ spaceAfter=10,
+ spaceBefore=10,
+ fontName=self.chinese_font
+ ),
+ 'Heading3': ParagraphStyle(
+ 'CustomHeading3',
+ parent=styles['Heading3'],
+ fontSize=12,
+ textColor=colors.HexColor('#3d6db5'),
+ spaceAfter=8,
+ spaceBefore=8,
+ fontName=self.chinese_font
+ ),
+ 'Normal': ParagraphStyle(
+ 'CustomNormal',
+ parent=styles['Normal'],
+ fontSize=10,
+ leading=14,
+ fontName=self.chinese_font,
+ alignment=TA_JUSTIFY
+ ),
+ 'Small': ParagraphStyle(
+ 'CustomSmall',
+ parent=styles['Normal'],
+ fontSize=9,
+ leading=12,
+ fontName=self.chinese_font
+ )
+ }
+
+ return custom_styles
+
+ 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'))
+ data_info = data.get('data_info', {})
+
+ info_text = f"""
+
+ 数据记录: {data_info.get('total_records', 0)} 条
+ 涉及股票: {data_info.get('total_stocks', 0)} 只
+ 涉及游资: {data_info.get('total_youzi', 0)} 个
+ AI分析师: 5位专业分析师团队
+ 分析模型: DeepSeek AI Multi-Agent System
+
"
+ "市场有风险,投资需谨慎。请投资者独立判断并承担投资风险。
+
+ 资金概况:
+ • 总买入金额: {summary.get('total_buy_amount', 0):,.2f} 元
+ • 总卖出金额: {summary.get('total_sell_amount', 0):,.2f} 元
+ • 净流入金额: {summary.get('total_net_inflow', 0):,.2f} 元
+
"
+
+ elements.append(Paragraph(concepts_text, styles['Normal']))
+
+ return elements
+
+ def _create_recommended_stocks(self, data: dict) -> list:
+ """创建推荐股票部分"""
+ styles = self._get_styles()
+ elements = []
+
+ # 标题
+ elements.append(Paragraph("二、AI推荐股票", styles['Heading1']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ recommended = data.get('recommended_stocks', [])
+
+ if not recommended:
+ elements.append(Paragraph("暂无推荐股票", styles['Normal']))
+ return elements
+
+ # 说明
+ intro_text = f"""
+
+ 推荐理由: {stock.get('reason', '暂无')}
+ 确定性: {stock.get('confidence', '-')} | 持有周期: {stock.get('hold_period', '-')}
+
+ • 游资行为分析师 - 分析游资操作特征和意图
+ • 个股潜力分析师 - 挖掘次日大概率上涨的股票
+ • 题材追踪分析师 - 识别热点题材和轮动机会
+ • 风险控制专家 - 识别高风险股票和市场陷阱
+ • 首席策略师 - 综合研判并给出最终建议
+