增加智瞰龙虎板块
This commit is contained in:
+177
@@ -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
|
||||
|
||||
## 状态
|
||||
|
||||
✅ 已修复并验证通过
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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", "")
|
||||
|
||||
@@ -245,6 +245,7 @@ class ConfigManager:
|
||||
def reload_config(self):
|
||||
"""重新加载配置(重新加载.env文件)"""
|
||||
from dotenv import load_dotenv
|
||||
# 强制覆盖已存在的环境变量
|
||||
load_dotenv(override=True)
|
||||
|
||||
|
||||
|
||||
@@ -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'])} 字符")
|
||||
|
||||
@@ -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数据采集失败")
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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', '未知错误')}")
|
||||
|
||||
@@ -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"""
|
||||
<para align=center>
|
||||
<b>生成时间:</b> {timestamp}<br/>
|
||||
<b>数据记录:</b> {data_info.get('total_records', 0)} 条<br/>
|
||||
<b>涉及股票:</b> {data_info.get('total_stocks', 0)} 只<br/>
|
||||
<b>涉及游资:</b> {data_info.get('total_youzi', 0)} 个<br/>
|
||||
<b>AI分析师:</b> 5位专业分析师团队<br/>
|
||||
<b>分析模型:</b> DeepSeek AI Multi-Agent System
|
||||
</para>
|
||||
"""
|
||||
info = Paragraph(info_text, styles['Normal'])
|
||||
elements.append(info)
|
||||
elements.append(Spacer(1, 1*inch))
|
||||
|
||||
# 免责声明
|
||||
disclaimer = Paragraph(
|
||||
"<para align=center><i>本报告由AI系统基于龙虎榜公开数据自动生成,仅供参考,不构成投资建议。<br/>"
|
||||
"市场有风险,投资需谨慎。请投资者独立判断并承担投资风险。</i></para>",
|
||||
styles['Normal']
|
||||
)
|
||||
elements.append(disclaimer)
|
||||
|
||||
return elements
|
||||
|
||||
def _create_data_overview(self, data: dict) -> list:
|
||||
"""创建数据概况部分"""
|
||||
styles = self._get_styles()
|
||||
elements = []
|
||||
|
||||
# 标题
|
||||
elements.append(Paragraph("一、数据概况", styles['Heading1']))
|
||||
elements.append(Spacer(1, 0.2*inch))
|
||||
|
||||
data_info = data.get('data_info', {})
|
||||
summary = data_info.get('summary', {})
|
||||
|
||||
# 基本统计
|
||||
overview_text = f"""
|
||||
<para>
|
||||
本次分析共涵盖 <b>{data_info.get('total_records', 0)}</b> 条龙虎榜记录,
|
||||
涉及 <b>{data_info.get('total_stocks', 0)}</b> 只股票和
|
||||
<b>{data_info.get('total_youzi', 0)}</b> 个游资席位。<br/><br/>
|
||||
|
||||
<b>资金概况:</b><br/>
|
||||
• 总买入金额: {summary.get('total_buy_amount', 0):,.2f} 元<br/>
|
||||
• 总卖出金额: {summary.get('total_sell_amount', 0):,.2f} 元<br/>
|
||||
• 净流入金额: {summary.get('total_net_inflow', 0):,.2f} 元
|
||||
</para>
|
||||
"""
|
||||
elements.append(Paragraph(overview_text, styles['Normal']))
|
||||
elements.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# TOP游资
|
||||
if summary.get('top_youzi'):
|
||||
elements.append(Paragraph("1.1 活跃游资 TOP10", styles['Heading2']))
|
||||
elements.append(Spacer(1, 0.1*inch))
|
||||
|
||||
table_data = [['排名', '游资名称', '净流入金额(元)']]
|
||||
for idx, (name, amount) in enumerate(list(summary['top_youzi'].items())[:10], 1):
|
||||
table_data.append([str(idx), name, f"{amount:,.2f}"])
|
||||
|
||||
table = Table(table_data, colWidths=[0.8*inch, 3.5*inch, 2*inch])
|
||||
table.setStyle(TableStyle([
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1f4788')),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
||||
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
||||
('FONTNAME', (0, 0), (-1, -1), self.chinese_font),
|
||||
('FONTSIZE', (0, 0), (-1, 0), 10),
|
||||
('FONTSIZE', (0, 1), (-1, -1), 9),
|
||||
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
||||
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.black)
|
||||
]))
|
||||
elements.append(table)
|
||||
elements.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# TOP股票
|
||||
if summary.get('top_stocks'):
|
||||
elements.append(Paragraph("1.2 资金净流入 TOP20 股票", styles['Heading2']))
|
||||
elements.append(Spacer(1, 0.1*inch))
|
||||
|
||||
table_data = [['排名', '股票代码', '股票名称', '净流入金额(元)']]
|
||||
for idx, stock in enumerate(summary['top_stocks'][:20], 1):
|
||||
table_data.append([
|
||||
str(idx),
|
||||
stock['code'],
|
||||
stock['name'],
|
||||
f"{stock['net_inflow']:,.2f}"
|
||||
])
|
||||
|
||||
table = Table(table_data, colWidths=[0.8*inch, 1.2*inch, 2*inch, 2.3*inch])
|
||||
table.setStyle(TableStyle([
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1f4788')),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
||||
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
||||
('FONTNAME', (0, 0), (-1, -1), self.chinese_font),
|
||||
('FONTSIZE', (0, 0), (-1, 0), 10),
|
||||
('FONTSIZE', (0, 1), (-1, -1), 8),
|
||||
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
||||
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.black)
|
||||
]))
|
||||
elements.append(table)
|
||||
elements.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# 热门概念
|
||||
if summary.get('hot_concepts'):
|
||||
elements.append(Paragraph("1.3 热门概念 TOP15", styles['Heading2']))
|
||||
elements.append(Spacer(1, 0.1*inch))
|
||||
|
||||
concepts_text = ""
|
||||
for idx, (concept, count) in enumerate(list(summary['hot_concepts'].items())[:15], 1):
|
||||
concepts_text += f"{idx}. {concept} ({count}次) "
|
||||
if idx % 3 == 0:
|
||||
concepts_text += "<br/>"
|
||||
|
||||
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"""
|
||||
<para>
|
||||
基于5位AI分析师的综合分析,系统识别出以下 <b>{len(recommended)}</b> 只潜力股票,
|
||||
这些股票在资金流向、游资关注度、题材热度等多个维度表现突出。
|
||||
</para>
|
||||
"""
|
||||
elements.append(Paragraph(intro_text, styles['Normal']))
|
||||
elements.append(Spacer(1, 0.2*inch))
|
||||
|
||||
# 推荐股票表格
|
||||
table_data = [['排名', '股票代码', '股票名称', '净流入金额', '确定性', '持有周期']]
|
||||
for stock in recommended[:10]:
|
||||
table_data.append([
|
||||
str(stock.get('rank', '-')),
|
||||
stock.get('code', '-'),
|
||||
stock.get('name', '-'),
|
||||
f"{stock.get('net_inflow', 0):,.0f}",
|
||||
stock.get('confidence', '-'),
|
||||
stock.get('hold_period', '-')
|
||||
])
|
||||
|
||||
table = Table(table_data, colWidths=[0.7*inch, 1.2*inch, 1.5*inch, 1.5*inch, 0.9*inch, 1*inch])
|
||||
table.setStyle(TableStyle([
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1f4788')),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
||||
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
||||
('FONTNAME', (0, 0), (-1, -1), self.chinese_font),
|
||||
('FONTSIZE', (0, 0), (-1, 0), 9),
|
||||
('FONTSIZE', (0, 1), (-1, -1), 8),
|
||||
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
||||
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.black)
|
||||
]))
|
||||
elements.append(table)
|
||||
elements.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# 详细推荐理由
|
||||
elements.append(Paragraph("2.1 推荐理由详解", styles['Heading2']))
|
||||
elements.append(Spacer(1, 0.1*inch))
|
||||
|
||||
for stock in recommended[:5]: # 只详细展示前5只
|
||||
stock_text = f"""
|
||||
<para>
|
||||
<b>{stock.get('rank', '-')}. {stock.get('name', '-')} ({stock.get('code', '-')})</b><br/>
|
||||
推荐理由: {stock.get('reason', '暂无')}<br/>
|
||||
确定性: {stock.get('confidence', '-')} | 持有周期: {stock.get('hold_period', '-')}
|
||||
</para>
|
||||
"""
|
||||
elements.append(Paragraph(stock_text, styles['Small']))
|
||||
elements.append(Spacer(1, 0.1*inch))
|
||||
|
||||
return elements
|
||||
|
||||
def _create_agents_analysis(self, data: dict) -> list:
|
||||
"""创建AI分析师报告部分"""
|
||||
styles = self._get_styles()
|
||||
elements = []
|
||||
|
||||
agents_analysis = data.get('agents_analysis', {})
|
||||
|
||||
if not agents_analysis:
|
||||
return elements
|
||||
|
||||
# 标题
|
||||
elements.append(Paragraph("三、AI分析师报告", styles['Heading1']))
|
||||
elements.append(Spacer(1, 0.2*inch))
|
||||
|
||||
# 分析师介绍
|
||||
intro_text = """
|
||||
<para>
|
||||
本报告由5位AI专业分析师从不同维度进行分析,综合形成投资建议:<br/>
|
||||
• <b>游资行为分析师</b> - 分析游资操作特征和意图<br/>
|
||||
• <b>个股潜力分析师</b> - 挖掘次日大概率上涨的股票<br/>
|
||||
• <b>题材追踪分析师</b> - 识别热点题材和轮动机会<br/>
|
||||
• <b>风险控制专家</b> - 识别高风险股票和市场陷阱<br/>
|
||||
• <b>首席策略师</b> - 综合研判并给出最终建议
|
||||
</para>
|
||||
"""
|
||||
elements.append(Paragraph(intro_text, styles['Normal']))
|
||||
elements.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# 各分析师报告
|
||||
agent_titles = {
|
||||
'youzi': '3.1 游资行为分析师',
|
||||
'stock': '3.2 个股潜力分析师',
|
||||
'theme': '3.3 题材追踪分析师',
|
||||
'risk': '3.4 风险控制专家',
|
||||
'chief': '3.5 首席策略师综合研判'
|
||||
}
|
||||
|
||||
for agent_key, agent_title in agent_titles.items():
|
||||
agent_data = agents_analysis.get(agent_key, {})
|
||||
if agent_data:
|
||||
elements.append(Paragraph(agent_title, styles['Heading2']))
|
||||
elements.append(Spacer(1, 0.1*inch))
|
||||
|
||||
analysis_text = agent_data.get('analysis', '暂无分析')
|
||||
# 截断过长的文本
|
||||
if len(analysis_text) > 3000:
|
||||
analysis_text = analysis_text[:3000] + "\n...(内容过长,已截断)"
|
||||
|
||||
elements.append(Paragraph(analysis_text, styles['Small']))
|
||||
elements.append(Spacer(1, 0.2*inch))
|
||||
|
||||
if agent_key != 'chief':
|
||||
elements.append(PageBreak())
|
||||
|
||||
return elements
|
||||
|
||||
|
||||
# 测试函数
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("测试智瞰龙虎PDF生成模块")
|
||||
print("=" * 60)
|
||||
|
||||
# 创建测试数据
|
||||
test_data = {
|
||||
'timestamp': '2024-01-15 18:30:00',
|
||||
'data_info': {
|
||||
'total_records': 150,
|
||||
'total_stocks': 50,
|
||||
'total_youzi': 30,
|
||||
'summary': {
|
||||
'total_buy_amount': 500000000,
|
||||
'total_sell_amount': 200000000,
|
||||
'total_net_inflow': 300000000,
|
||||
'top_youzi': {
|
||||
'92科比': 14455321,
|
||||
'赵老哥': 12000000
|
||||
},
|
||||
'top_stocks': [
|
||||
{'code': '001337', 'name': '四川黄金', 'net_inflow': 14455321}
|
||||
],
|
||||
'hot_concepts': {
|
||||
'黄金概念': 10,
|
||||
'新能源': 8
|
||||
}
|
||||
}
|
||||
},
|
||||
'recommended_stocks': [
|
||||
{
|
||||
'rank': 1,
|
||||
'code': '001337',
|
||||
'name': '四川黄金',
|
||||
'net_inflow': 14455321,
|
||||
'reason': '游资大幅买入',
|
||||
'confidence': '高',
|
||||
'hold_period': '短线'
|
||||
}
|
||||
],
|
||||
'agents_analysis': {
|
||||
'chief': {
|
||||
'analysis': '综合分析显示...'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 生成PDF
|
||||
generator = LonghubangPDFGenerator()
|
||||
pdf_path = generator.generate_pdf(test_data)
|
||||
print(f"\nPDF已生成: {pdf_path}")
|
||||
|
||||
@@ -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, timedelta
|
||||
import time
|
||||
import base64
|
||||
|
||||
from longhubang_engine import LonghubangEngine
|
||||
from longhubang_pdf import LonghubangPDFGenerator
|
||||
|
||||
|
||||
def display_longhubang():
|
||||
"""显示智瞰龙虎主界面"""
|
||||
|
||||
st.markdown("""
|
||||
<div class="top-nav">
|
||||
<h1 class="nav-title">🎯 智瞰龙虎 - AI驱动的龙虎榜分析</h1>
|
||||
<p class="nav-subtitle">Multi-Agent Dragon Tiger Analysis | 游资·个股·题材·风险多维分析</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# 功能说明
|
||||
with st.expander("💡 智瞰龙虎系统介绍", expanded=False):
|
||||
st.markdown("""
|
||||
### 🌟 系统特色
|
||||
|
||||
**智瞰龙虎**是基于多AI智能体的龙虎榜深度分析系统,通过5位专业分析师的协同工作,
|
||||
为您挖掘次日大概率上涨的潜力股票。
|
||||
|
||||
### 🤖 AI分析师团队
|
||||
|
||||
1. **🎯 游资行为分析师**
|
||||
- 识别活跃游资及其操作风格
|
||||
- 分析游资席位的进出特征
|
||||
- 研判游资对个股的态度
|
||||
|
||||
2. **📈 个股潜力分析师**
|
||||
- 从龙虎榜数据挖掘潜力股
|
||||
- 识别次日大概率上涨的股票
|
||||
- 分析资金动向和技术形态
|
||||
|
||||
3. **🔥 题材追踪分析师**
|
||||
- 识别当前热点题材和概念
|
||||
- 分析题材的炒作周期
|
||||
- 预判题材的持续性
|
||||
|
||||
4. **⚠️ 风险控制专家**
|
||||
- 识别高风险股票和陷阱
|
||||
- 分析游资出货信号
|
||||
- 提供风险管理建议
|
||||
|
||||
5. **👔 首席策略师**
|
||||
- 综合所有分析师意见
|
||||
- 给出最终推荐股票清单
|
||||
- 提供具体操作策略
|
||||
|
||||
### 📊 数据来源
|
||||
|
||||
数据来自**StockAPI龙虎榜接口**,包括:
|
||||
- 游资上榜交割单历史数据
|
||||
- 股票买卖金额和净流入
|
||||
- 热门概念和题材
|
||||
- 更新时间:交易日下午5点40
|
||||
|
||||
### 🎯 核心功能
|
||||
|
||||
- ✅ **潜力股挖掘** - AI识别次日大概率上涨股票
|
||||
- ✅ **游资追踪** - 跟踪活跃游资的操作
|
||||
- ✅ **题材识别** - 发现热点题材和龙头股
|
||||
- ✅ **风险提示** - 识别高风险股票和陷阱
|
||||
- ✅ **历史记录** - 存储所有龙虎榜数据
|
||||
- ✅ **PDF报告** - 生成专业分析报告
|
||||
""")
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# 创建标签页
|
||||
tab1, tab2, tab3 = st.tabs([
|
||||
"📊 龙虎榜分析",
|
||||
"📚 历史报告",
|
||||
"📈 数据统计"
|
||||
])
|
||||
|
||||
with tab1:
|
||||
display_analysis_tab()
|
||||
|
||||
with tab2:
|
||||
display_history_tab()
|
||||
|
||||
with tab3:
|
||||
display_statistics_tab()
|
||||
|
||||
|
||||
def display_analysis_tab():
|
||||
"""显示分析标签页"""
|
||||
|
||||
st.subheader("🔍 龙虎榜综合分析")
|
||||
|
||||
# 参数设置
|
||||
col1, col2, col3 = st.columns([2, 2, 2])
|
||||
|
||||
with col1:
|
||||
analysis_mode = st.selectbox(
|
||||
"分析模式",
|
||||
["指定日期", "最近N天"],
|
||||
help="选择分析特定日期还是最近几天的数据"
|
||||
)
|
||||
|
||||
with col2:
|
||||
if analysis_mode == "指定日期":
|
||||
selected_date = st.date_input(
|
||||
"选择日期",
|
||||
value=datetime.now() - timedelta(days=1),
|
||||
help="选择要分析的龙虎榜日期"
|
||||
)
|
||||
else:
|
||||
days = st.number_input(
|
||||
"最近天数",
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=1,
|
||||
help="分析最近N天的龙虎榜数据"
|
||||
)
|
||||
|
||||
with col3:
|
||||
selected_model = st.selectbox(
|
||||
"AI模型",
|
||||
["deepseek-chat", "deepseek-reasoner"],
|
||||
help="Reasoner模型提供更强的推理能力"
|
||||
)
|
||||
|
||||
# 分析按钮
|
||||
col1, col2, col3 = st.columns([2, 2, 2])
|
||||
|
||||
with col1:
|
||||
analyze_button = st.button("🚀 开始分析", type="primary", use_container_width=True)
|
||||
|
||||
with col2:
|
||||
if st.button("🔄 清除结果", use_container_width=True):
|
||||
if 'longhubang_result' in st.session_state:
|
||||
del st.session_state.longhubang_result
|
||||
st.success("已清除分析结果")
|
||||
st.rerun()
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# 开始分析
|
||||
if analyze_button:
|
||||
# 清除之前的结果
|
||||
if 'longhubang_result' in st.session_state:
|
||||
del st.session_state.longhubang_result
|
||||
|
||||
# 准备参数
|
||||
if analysis_mode == "指定日期":
|
||||
date_str = selected_date.strftime('%Y-%m-%d')
|
||||
run_longhubang_analysis(model=selected_model, date=date_str)
|
||||
else:
|
||||
run_longhubang_analysis(model=selected_model, days=days)
|
||||
|
||||
# 显示分析结果
|
||||
if 'longhubang_result' in st.session_state:
|
||||
result = st.session_state.longhubang_result
|
||||
|
||||
if result.get("success"):
|
||||
display_analysis_results(result)
|
||||
else:
|
||||
st.error(f"❌ 分析失败: {result.get('error', '未知错误')}")
|
||||
|
||||
|
||||
def run_longhubang_analysis(model="deepseek-chat", date=None, days=1):
|
||||
"""运行龙虎榜分析"""
|
||||
|
||||
# 进度显示
|
||||
progress_bar = st.progress(0)
|
||||
status_text = st.empty()
|
||||
|
||||
try:
|
||||
status_text.text("🚀 初始化分析引擎...")
|
||||
progress_bar.progress(5)
|
||||
|
||||
engine = LonghubangEngine(model=model)
|
||||
|
||||
status_text.text("📊 正在获取龙虎榜数据...")
|
||||
progress_bar.progress(15)
|
||||
|
||||
# 运行分析
|
||||
result = engine.run_comprehensive_analysis(date=date, days=days)
|
||||
|
||||
progress_bar.progress(90)
|
||||
|
||||
if result.get("success"):
|
||||
# 保存结果
|
||||
st.session_state.longhubang_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_analysis_results(result):
|
||||
"""显示分析结果"""
|
||||
|
||||
st.success("✅ 龙虎榜分析完成!")
|
||||
st.info(f"📅 分析时间: {result.get('timestamp', 'N/A')}")
|
||||
|
||||
# 数据概况
|
||||
data_info = result.get('data_info', {})
|
||||
col1, col2, col3, col4 = st.columns(4)
|
||||
|
||||
with col1:
|
||||
st.metric("龙虎榜记录", f"{data_info.get('total_records', 0)} 条")
|
||||
|
||||
with col2:
|
||||
st.metric("涉及股票", f"{data_info.get('total_stocks', 0)} 只")
|
||||
|
||||
with col3:
|
||||
st.metric("涉及游资", f"{data_info.get('total_youzi', 0)} 个")
|
||||
|
||||
with col4:
|
||||
recommended = result.get('recommended_stocks', [])
|
||||
st.metric("推荐股票", f"{len(recommended)} 只", delta="AI筛选")
|
||||
|
||||
# PDF导出功能
|
||||
display_pdf_export_section(result)
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# 创建子标签页
|
||||
tab1, tab2, tab3, tab4 = st.tabs([
|
||||
"🎯 推荐股票",
|
||||
"🤖 AI分析师报告",
|
||||
"📊 数据详情",
|
||||
"📈 可视化图表"
|
||||
])
|
||||
|
||||
with tab1:
|
||||
display_recommended_stocks(result)
|
||||
|
||||
with tab2:
|
||||
display_agents_reports(result)
|
||||
|
||||
with tab3:
|
||||
display_data_details(result)
|
||||
|
||||
with tab4:
|
||||
display_visualizations(result)
|
||||
|
||||
|
||||
def display_recommended_stocks(result):
|
||||
"""显示推荐股票"""
|
||||
|
||||
st.subheader("🎯 AI推荐股票")
|
||||
|
||||
recommended = result.get('recommended_stocks', [])
|
||||
|
||||
if not recommended:
|
||||
st.warning("暂无推荐股票")
|
||||
return
|
||||
|
||||
st.info(f"💡 基于5位AI分析师的综合分析,系统识别出以下 **{len(recommended)}** 只潜力股票")
|
||||
|
||||
# 创建DataFrame
|
||||
df_recommended = pd.DataFrame(recommended)
|
||||
|
||||
# 显示表格
|
||||
st.dataframe(
|
||||
df_recommended,
|
||||
column_config={
|
||||
"rank": st.column_config.NumberColumn("排名", format="%d"),
|
||||
"code": st.column_config.TextColumn("股票代码"),
|
||||
"name": st.column_config.TextColumn("股票名称"),
|
||||
"net_inflow": st.column_config.NumberColumn("净流入金额", format="%.2f"),
|
||||
"confidence": st.column_config.TextColumn("确定性"),
|
||||
"hold_period": st.column_config.TextColumn("持有周期"),
|
||||
"reason": st.column_config.TextColumn("推荐理由")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
# 详细推荐理由
|
||||
st.markdown("### 📝 详细推荐理由")
|
||||
|
||||
for stock in recommended[:5]: # 只显示前5只
|
||||
with st.expander(f"**{stock.get('rank', '-')}. {stock.get('name', '-')} ({stock.get('code', '-')})**"):
|
||||
col1, col2 = st.columns([2, 1])
|
||||
|
||||
with col1:
|
||||
st.markdown(f"**推荐理由:** {stock.get('reason', '暂无')}")
|
||||
st.markdown(f"**净流入:** {stock.get('net_inflow', 0):,.2f} 元")
|
||||
|
||||
with col2:
|
||||
st.markdown(f"**确定性:** {stock.get('confidence', '-')}")
|
||||
st.markdown(f"**持有周期:** {stock.get('hold_period', '-')}")
|
||||
|
||||
|
||||
def display_agents_reports(result):
|
||||
"""显示AI分析师报告"""
|
||||
|
||||
st.subheader("🤖 AI分析师团队报告")
|
||||
|
||||
agents_analysis = result.get('agents_analysis', {})
|
||||
|
||||
if not agents_analysis:
|
||||
st.warning("暂无分析报告")
|
||||
return
|
||||
|
||||
# 各分析师报告
|
||||
agent_info = {
|
||||
'youzi': {'title': '🎯 游资行为分析师', 'icon': '🎯'},
|
||||
'stock': {'title': '📈 个股潜力分析师', 'icon': '📈'},
|
||||
'theme': {'title': '🔥 题材追踪分析师', 'icon': '🔥'},
|
||||
'risk': {'title': '⚠️ 风险控制专家', 'icon': '⚠️'},
|
||||
'chief': {'title': '👔 首席策略师综合研判', 'icon': '👔'}
|
||||
}
|
||||
|
||||
for agent_key, info in agent_info.items():
|
||||
agent_data = agents_analysis.get(agent_key, {})
|
||||
if agent_data:
|
||||
with st.expander(f"{info['icon']} {info['title']}", expanded=(agent_key == 'chief')):
|
||||
analysis = agent_data.get('analysis', '暂无分析')
|
||||
st.markdown(analysis)
|
||||
|
||||
st.markdown(f"*{agent_data.get('agent_role', '')}*")
|
||||
st.caption(f"分析时间: {agent_data.get('timestamp', 'N/A')}")
|
||||
|
||||
|
||||
def display_data_details(result):
|
||||
"""显示数据详情"""
|
||||
|
||||
st.subheader("📊 龙虎榜数据详情")
|
||||
|
||||
data_info = result.get('data_info', {})
|
||||
summary = data_info.get('summary', {})
|
||||
|
||||
# TOP游资
|
||||
if summary.get('top_youzi'):
|
||||
st.markdown("### 🏆 活跃游资 TOP10")
|
||||
|
||||
youzi_data = [
|
||||
{'排名': idx, '游资名称': name, '净流入金额': amount}
|
||||
for idx, (name, amount) in enumerate(list(summary['top_youzi'].items())[:10], 1)
|
||||
]
|
||||
df_youzi = pd.DataFrame(youzi_data)
|
||||
|
||||
st.dataframe(
|
||||
df_youzi,
|
||||
column_config={
|
||||
"排名": st.column_config.NumberColumn("排名", format="%d"),
|
||||
"游资名称": st.column_config.TextColumn("游资名称"),
|
||||
"净流入金额": st.column_config.NumberColumn("净流入金额(元)", format="%.2f")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
# TOP股票
|
||||
if summary.get('top_stocks'):
|
||||
st.markdown("### 📈 资金净流入 TOP20 股票")
|
||||
|
||||
df_stocks = pd.DataFrame(summary['top_stocks'][:20])
|
||||
|
||||
st.dataframe(
|
||||
df_stocks,
|
||||
column_config={
|
||||
"code": st.column_config.TextColumn("股票代码"),
|
||||
"name": st.column_config.TextColumn("股票名称"),
|
||||
"net_inflow": st.column_config.NumberColumn("净流入金额(元)", format="%.2f")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
# 热门概念
|
||||
if summary.get('hot_concepts'):
|
||||
st.markdown("### 🔥 热门概念 TOP20")
|
||||
|
||||
concepts_data = [
|
||||
{'排名': idx, '概念名称': concept, '出现次数': count}
|
||||
for idx, (concept, count) in enumerate(list(summary['hot_concepts'].items())[:20], 1)
|
||||
]
|
||||
df_concepts = pd.DataFrame(concepts_data)
|
||||
|
||||
st.dataframe(
|
||||
df_concepts,
|
||||
column_config={
|
||||
"排名": st.column_config.NumberColumn("排名", format="%d"),
|
||||
"概念名称": st.column_config.TextColumn("概念名称"),
|
||||
"出现次数": st.column_config.NumberColumn("出现次数", format="%d")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
|
||||
def display_visualizations(result):
|
||||
"""显示可视化图表"""
|
||||
|
||||
st.subheader("📈 数据可视化")
|
||||
|
||||
data_info = result.get('data_info', {})
|
||||
summary = data_info.get('summary', {})
|
||||
|
||||
# 资金流向图表
|
||||
if summary.get('top_stocks'):
|
||||
st.markdown("### 💰 TOP20 股票资金净流入")
|
||||
|
||||
stocks = summary['top_stocks'][:20]
|
||||
df_chart = pd.DataFrame(stocks)
|
||||
|
||||
fig = px.bar(
|
||||
df_chart,
|
||||
x='name',
|
||||
y='net_inflow',
|
||||
title='TOP20 股票资金净流入金额',
|
||||
labels={'name': '股票名称', 'net_inflow': '净流入金额(元)'}
|
||||
)
|
||||
fig.update_layout(xaxis_tickangle=-45)
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
# 热门概念图表
|
||||
if summary.get('hot_concepts'):
|
||||
st.markdown("### 🔥 热门概念分布")
|
||||
|
||||
concepts = list(summary['hot_concepts'].items())[:15]
|
||||
df_concepts = pd.DataFrame(concepts, columns=['概念', '次数'])
|
||||
|
||||
fig = px.pie(
|
||||
df_concepts,
|
||||
values='次数',
|
||||
names='概念',
|
||||
title='热门概念出现次数分布'
|
||||
)
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
|
||||
def display_pdf_export_section(result):
|
||||
"""显示PDF导出功能"""
|
||||
|
||||
st.markdown("### 📄 导出PDF报告")
|
||||
|
||||
col1, col2 = st.columns([3, 1])
|
||||
|
||||
with col1:
|
||||
st.info("💡 点击按钮生成并下载专业的PDF分析报告")
|
||||
|
||||
with col2:
|
||||
if st.button("📥 生成PDF", type="primary", use_container_width=True):
|
||||
with st.spinner("正在生成PDF报告..."):
|
||||
try:
|
||||
generator = LonghubangPDFGenerator()
|
||||
pdf_path = generator.generate_pdf(result)
|
||||
|
||||
# 读取PDF文件
|
||||
with open(pdf_path, "rb") as f:
|
||||
pdf_bytes = f.read()
|
||||
|
||||
# 提供下载
|
||||
st.download_button(
|
||||
label="📥 下载PDF报告",
|
||||
data=pdf_bytes,
|
||||
file_name=f"智瞰龙虎报告_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
|
||||
mime="application/pdf",
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
st.success("✅ PDF报告生成成功!")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ PDF生成失败: {str(e)}")
|
||||
|
||||
|
||||
def display_history_tab():
|
||||
"""显示历史报告标签页"""
|
||||
|
||||
st.subheader("📚 历史分析报告")
|
||||
|
||||
try:
|
||||
engine = LonghubangEngine()
|
||||
reports_df = engine.get_historical_reports(limit=20)
|
||||
|
||||
if reports_df.empty:
|
||||
st.info("暂无历史报告")
|
||||
return
|
||||
|
||||
st.dataframe(
|
||||
reports_df,
|
||||
column_config={
|
||||
"id": st.column_config.NumberColumn("ID", format="%d"),
|
||||
"analysis_date": st.column_config.TextColumn("分析时间"),
|
||||
"data_date_range": st.column_config.TextColumn("数据日期范围"),
|
||||
"summary": st.column_config.TextColumn("摘要")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ 加载历史报告失败: {str(e)}")
|
||||
|
||||
|
||||
def display_statistics_tab():
|
||||
"""显示数据统计标签页"""
|
||||
|
||||
st.subheader("📈 数据统计")
|
||||
|
||||
try:
|
||||
engine = LonghubangEngine()
|
||||
stats = engine.get_statistics()
|
||||
|
||||
# 基本统计
|
||||
col1, col2, col3, col4 = st.columns(4)
|
||||
|
||||
with col1:
|
||||
st.metric("总记录数", f"{stats.get('total_records', 0):,}")
|
||||
|
||||
with col2:
|
||||
st.metric("股票总数", f"{stats.get('total_stocks', 0):,}")
|
||||
|
||||
with col3:
|
||||
st.metric("游资总数", f"{stats.get('total_youzi', 0):,}")
|
||||
|
||||
with col4:
|
||||
st.metric("分析报告", f"{stats.get('total_reports', 0):,}")
|
||||
|
||||
# 日期范围
|
||||
date_range = stats.get('date_range', {})
|
||||
if date_range:
|
||||
st.info(f"📅 数据日期范围: {date_range.get('start', 'N/A')} 至 {date_range.get('end', 'N/A')}")
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# 活跃游资排名
|
||||
st.markdown("### 🏆 历史活跃游资排名 (近30天)")
|
||||
|
||||
end_date = datetime.now().strftime('%Y-%m-%d')
|
||||
start_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d')
|
||||
|
||||
top_youzi_df = engine.get_top_youzi(start_date, end_date, limit=20)
|
||||
|
||||
if not top_youzi_df.empty:
|
||||
st.dataframe(
|
||||
top_youzi_df,
|
||||
column_config={
|
||||
"youzi_name": st.column_config.TextColumn("游资名称"),
|
||||
"trade_count": st.column_config.NumberColumn("交易次数", format="%d"),
|
||||
"total_net_inflow": st.column_config.NumberColumn("总净流入(元)", format="%.2f")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# 热门股票排名
|
||||
st.markdown("### 📈 历史热门股票排名 (近30天)")
|
||||
|
||||
top_stocks_df = engine.get_top_stocks(start_date, end_date, limit=20)
|
||||
|
||||
if not top_stocks_df.empty:
|
||||
st.dataframe(
|
||||
top_stocks_df,
|
||||
column_config={
|
||||
"stock_code": st.column_config.TextColumn("股票代码"),
|
||||
"stock_name": st.column_config.TextColumn("股票名称"),
|
||||
"youzi_count": st.column_config.NumberColumn("游资数量", format="%d"),
|
||||
"total_net_inflow": st.column_config.NumberColumn("总净流入(元)", format="%.2f")
|
||||
},
|
||||
hide_index=True,
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ 加载统计数据失败: {str(e)}")
|
||||
|
||||
|
||||
# 测试函数
|
||||
if __name__ == "__main__":
|
||||
st.set_page_config(
|
||||
page_title="智瞰龙虎",
|
||||
page_icon="🎯",
|
||||
layout="wide"
|
||||
)
|
||||
|
||||
display_longhubang()
|
||||
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
# 智瞰龙虎功能说明
|
||||
|
||||
## 📋 功能概述
|
||||
|
||||
**智瞰龙虎**是基于多AI智能体的龙虎榜深度分析系统,通过5位专业分析师的协同工作,为您挖掘次日大概率上涨的潜力股票。
|
||||
|
||||
## 🎯 核心特性
|
||||
|
||||
### 1. 数据来源
|
||||
- **数据接口**: StockAPI龙虎榜接口
|
||||
- **数据内容**: 全量游资上榜交割单历史数据
|
||||
- **更新时间**: 交易日下午5点40
|
||||
- **请求频率**: 40次/秒
|
||||
- **免费额度**: 每日1000次
|
||||
|
||||
### 2. AI分析师团队
|
||||
|
||||
#### 🎯 游资行为分析师
|
||||
- 识别活跃游资及其操作风格
|
||||
- 分析游资席位的进出特征
|
||||
- 研判游资对个股的态度
|
||||
- 识别知名"牛散"和"游资大佬"
|
||||
|
||||
#### 📈 个股潜力分析师(核心)
|
||||
- 从龙虎榜数据挖掘潜力股
|
||||
- **识别次日大概率上涨的股票**
|
||||
- 分析资金动向和技术形态
|
||||
- 提供买入价位、目标价位、止损位
|
||||
|
||||
#### 🔥 题材追踪分析师
|
||||
- 识别当前热点题材和概念
|
||||
- 分析题材的炒作周期
|
||||
- 预判题材的持续性
|
||||
- 找出题材龙头和低位补涨股
|
||||
|
||||
#### ⚠️ 风险控制专家
|
||||
- 识别高风险股票和陷阱
|
||||
- 分析游资出货信号
|
||||
- 提供风险管理建议
|
||||
- 识别"拉高出货"等陷阱手法
|
||||
|
||||
#### 👔 首席策略师
|
||||
- 综合所有分析师意见
|
||||
- 给出最终推荐股票清单(TOP5-8)
|
||||
- 提供具体操作策略
|
||||
- 给出仓位管理和持有周期建议
|
||||
|
||||
## 📊 主要功能
|
||||
|
||||
### 1. 龙虎榜综合分析
|
||||
- **指定日期分析**: 分析特定日期的龙虎榜数据
|
||||
- **最近N天分析**: 分析最近几天的数据(1-10天)
|
||||
- **AI多维度分析**: 5位分析师从不同角度深度分析
|
||||
- **推荐股票清单**: 自动筛选次日大概率上涨的股票
|
||||
|
||||
### 2. 数据可视化
|
||||
- **资金净流入图表**: TOP20股票资金流向
|
||||
- **热门概念分布**: 概念出现频次统计
|
||||
- **活跃游资排名**: 游资净流入排行
|
||||
- **详细数据表格**: 完整的龙虎榜数据展示
|
||||
|
||||
### 3. 历史记录管理
|
||||
- **自动存储**: 所有龙虎榜数据自动保存到数据库
|
||||
- **历史报告**: 查看历史分析报告
|
||||
- **数据统计**: 统计总记录数、股票数、游资数
|
||||
- **趋势分析**: 分析历史活跃游资和热门股票
|
||||
|
||||
### 4. PDF报告生成
|
||||
- **专业报告**: 生成完整的PDF分析报告
|
||||
- **包含内容**:
|
||||
- 数据概况统计
|
||||
- AI推荐股票清单
|
||||
- 5位分析师的详细报告
|
||||
- 可视化图表
|
||||
- 免责声明
|
||||
|
||||
## 🚀 使用指南
|
||||
|
||||
### 1. 启动系统
|
||||
```bash
|
||||
streamlit run app.py
|
||||
```
|
||||
|
||||
### 2. 进入智瞰龙虎
|
||||
- 点击侧边栏的 **🎯 智瞰龙虎** 按钮
|
||||
|
||||
### 3. 设置分析参数
|
||||
- **分析模式**: 选择"指定日期"或"最近N天"
|
||||
- **日期选择**: 选择要分析的龙虎榜日期(建议选择昨日)
|
||||
- **AI模型**: 选择deepseek-chat或deepseek-reasoner
|
||||
|
||||
### 4. 开始分析
|
||||
- 点击 **🚀 开始分析** 按钮
|
||||
- 系统会自动:
|
||||
1. 获取龙虎榜数据
|
||||
2. 保存到数据库
|
||||
3. 进行数据统计
|
||||
4. AI分析师团队分析(约10分钟)
|
||||
5. 生成推荐股票清单
|
||||
6. 保存分析报告
|
||||
|
||||
### 5. 查看结果
|
||||
- **🎯 推荐股票**: 查看AI筛选的潜力股
|
||||
- **🤖 AI分析师报告**: 查看5位分析师的详细分析
|
||||
- **📊 数据详情**: 查看龙虎榜原始数据
|
||||
- **📈 可视化图表**: 查看数据图表
|
||||
|
||||
### 6. 导出报告
|
||||
- 点击 **📥 生成PDF** 按钮
|
||||
- 下载专业的PDF分析报告
|
||||
|
||||
## 📁 文件结构
|
||||
|
||||
```
|
||||
智瞰龙虎模块/
|
||||
├── longhubang_data.py # 数据获取模块
|
||||
├── longhubang_db.py # 数据库管理模块
|
||||
├── longhubang_agents.py # AI分析师模块
|
||||
├── longhubang_engine.py # 综合分析引擎
|
||||
├── longhubang_pdf.py # PDF报告生成模块
|
||||
├── longhubang_ui.py # UI界面模块
|
||||
└── longhubang.db # SQLite数据库(自动创建)
|
||||
```
|
||||
|
||||
## 🗄️ 数据库结构
|
||||
|
||||
### 1. longhubang_records(龙虎榜记录表)
|
||||
- 存储所有龙虎榜原始数据
|
||||
- 包含字段:日期、股票代码、股票名称、游资名称、营业部、买入金额、卖出金额、净流入金额、概念等
|
||||
- 创建了日期、股票代码、游资名称、净流入金额的索引
|
||||
|
||||
### 2. longhubang_analysis(分析报告表)
|
||||
- 存储AI分析报告
|
||||
- 包含字段:分析日期、数据日期范围、分析内容、推荐股票、摘要等
|
||||
|
||||
### 3. stock_tracking(股票追踪表)
|
||||
- 记录推荐股票的后续表现
|
||||
- 用于跟踪AI推荐的准确性
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
### API配置
|
||||
龙虎榜数据使用StockAPI接口,普通请求每日免费1000次,无需额外配置。
|
||||
|
||||
如需提高请求限额,可以在系统中配置API密钥(可选)。
|
||||
|
||||
### AI模型配置
|
||||
系统使用DeepSeek AI模型,需要在环境配置中设置:
|
||||
- `DEEPSEEK_API_KEY`: DeepSeek API密钥
|
||||
- `DEEPSEEK_BASE_URL`: API地址(默认:https://api.deepseek.com/v1)
|
||||
|
||||
## 💡 使用建议
|
||||
|
||||
### 1. 最佳分析时间
|
||||
- 建议在**交易日晚上6点后**进行分析
|
||||
- 此时龙虎榜数据已更新完成
|
||||
|
||||
### 2. 推荐股票使用
|
||||
- 重点关注**首席策略师**推荐的TOP5-8只股票
|
||||
- 参考**确定性评级**:高>中>低
|
||||
- 注意查看**风险控制专家**的警示
|
||||
- 严格执行**止损位**,控制风险
|
||||
|
||||
### 3. 题材把握
|
||||
- 关注**题材追踪分析师**识别的热点题材
|
||||
- 优先选择处于**萌芽期或爆发期**的题材
|
||||
- 避免**高潮期或退潮期**的题材
|
||||
|
||||
### 4. 游资跟踪
|
||||
- 关注**知名游资**(如赵老哥、章盟主等)的动向
|
||||
- 多席位联合买入的股票往往更强势
|
||||
- 警惕游资"一日游"后快速撤离的股票
|
||||
|
||||
### 5. 资金分配
|
||||
- **高确定性股票**:可以重仓(30-40%)
|
||||
- **中等确定性股票**:中等仓位(20-30%)
|
||||
- **低确定性股票**:轻仓试探(10-15%)
|
||||
- 保留一定现金应对突发情况
|
||||
|
||||
## ⚠️ 风险提示
|
||||
|
||||
1. **市场风险**:股票市场存在风险,投资需谨慎
|
||||
2. **AI局限**:AI分析仅供参考,不构成投资建议
|
||||
3. **数据延迟**:龙虎榜数据为T日数据,存在时间差
|
||||
4. **游资风险**:游资操作灵活,可能快速撤离
|
||||
5. **题材风险**:题材炒作存在泡沫,注意及时止盈
|
||||
|
||||
## 🔧 技术支持
|
||||
|
||||
如遇到问题,请检查:
|
||||
1. 网络连接是否正常
|
||||
2. DeepSeek API密钥是否正确
|
||||
3. 数据库文件是否有写入权限
|
||||
4. Python依赖包是否完整安装
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.0 (2024-10-17)
|
||||
- ✅ 完成智瞰龙虎功能开发
|
||||
- ✅ 实现龙虎榜数据获取(StockAPI接口)
|
||||
- ✅ 实现5位AI分析师多维度分析
|
||||
- ✅ 实现数据库存储和历史记录
|
||||
- ✅ 实现数据可视化和图表展示
|
||||
- ✅ 实现PDF报告生成
|
||||
- ✅ 集成到主应用
|
||||
|
||||
## 📚 参考资料
|
||||
|
||||
- [StockAPI龙虎榜接口文档](https://www.stockapi.com.cn/)
|
||||
- [龙虎榜基础知识](https://baike.baidu.com/item/龙虎榜)
|
||||
- [游资操作手法解析](https://www.zhihu.com/topic/19571608)
|
||||
|
||||
---
|
||||
|
||||
**注意**: 本系统由AI自动生成分析报告,仅供学习和参考,不构成投资建议。市场有风险,投资需谨慎!
|
||||
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
# 智瞰龙虎 - 快速开始指南
|
||||
|
||||
## 🚀 5分钟快速上手
|
||||
|
||||
### 第一步:启动系统
|
||||
```bash
|
||||
# 确保已安装依赖
|
||||
pip install requests pandas streamlit plotly reportlab
|
||||
|
||||
# 启动应用
|
||||
streamlit run app.py
|
||||
```
|
||||
|
||||
### 第二步:进入智瞰龙虎
|
||||
1. 在浏览器中打开应用(通常是 http://localhost:8501)
|
||||
2. 点击左侧边栏的 **🎯 智瞰龙虎** 按钮
|
||||
|
||||
### 第三步:运行分析
|
||||
1. 选择**分析模式**:建议选择"指定日期"
|
||||
2. 选择**日期**:选择昨天的日期(龙虎榜数据T日更新)
|
||||
3. 选择**AI模型**:
|
||||
- `deepseek-chat`:速度快,适合日常使用
|
||||
- `deepseek-reasoner`:推理能力强,分析更深入
|
||||
4. 点击 **🚀 开始分析** 按钮
|
||||
|
||||
### 第四步:等待分析完成
|
||||
- 数据获取:约10-30秒
|
||||
- AI分析:约8-15分钟(5位分析师工作)
|
||||
- 请耐心等待,系统会显示进度
|
||||
|
||||
### 第五步:查看结果
|
||||
|
||||
#### 1. 推荐股票(最重要)
|
||||
- 查看**首席策略师**综合推荐的TOP5-8只股票
|
||||
- 重点关注:
|
||||
- ✅ 确定性评级(高/中/低)
|
||||
- 📈 推荐理由
|
||||
- 💰 买入价位、目标价位、止损位
|
||||
- ⏰ 持有周期
|
||||
|
||||
#### 2. AI分析师报告
|
||||
- 🎯 **游资行为分析师**:看游资在买什么
|
||||
- 📈 **个股潜力分析师**:看哪些股票最有潜力
|
||||
- 🔥 **题材追踪分析师**:看当前热门题材
|
||||
- ⚠️ **风险控制专家**:看哪些股票要规避
|
||||
- 👔 **首席策略师**:看最终综合建议
|
||||
|
||||
#### 3. 数据详情
|
||||
- 活跃游资TOP10
|
||||
- 资金净流入TOP20股票
|
||||
- 热门概念TOP20
|
||||
|
||||
#### 4. 可视化图表
|
||||
- 资金流向柱状图
|
||||
- 概念分布饼图
|
||||
|
||||
### 第六步:导出报告(可选)
|
||||
- 点击 **📥 生成PDF** 按钮
|
||||
- 下载完整的PDF分析报告
|
||||
- 可以打印或保存
|
||||
|
||||
## 📊 典型使用场景
|
||||
|
||||
### 场景1:寻找次日短线机会
|
||||
1. 每天交易结束后(18:00后)运行分析
|
||||
2. 重点看**个股潜力分析师**和**首席策略师**推荐
|
||||
3. 选择确定性评级为"高"的股票
|
||||
4. 第二天开盘后找机会介入
|
||||
|
||||
### 场景2:跟踪活跃游资
|
||||
1. 查看"数据详情"中的活跃游资TOP10
|
||||
2. 看他们买入了哪些股票
|
||||
3. 关注多席位联合买入的股票
|
||||
4. 避免游资集体卖出的股票
|
||||
|
||||
### 场景3:把握热点题材
|
||||
1. 查看**题材追踪分析师**的分析
|
||||
2. 识别当前最热门的题材
|
||||
3. 找出题材龙头股和补涨股
|
||||
4. 判断题材所处的炒作周期
|
||||
|
||||
### 场景4:风险控制
|
||||
1. 查看**风险控制专家**的警示
|
||||
2. 识别高风险股票并避开
|
||||
3. 对持仓股票进行风险评估
|
||||
4. 设置止损位,严格执行
|
||||
|
||||
## 💡 实战技巧
|
||||
|
||||
### 技巧1:最佳分析时间
|
||||
- ⏰ **18:00-21:00**:龙虎榜数据更新完成,适合分析
|
||||
- 🌙 **21:00-23:00**:整理分析结果,制定次日计划
|
||||
|
||||
### 技巧2:股票选择策略
|
||||
1. **优先级1**:确定性高 + 多席位买入 + 热门题材
|
||||
2. **优先级2**:确定性中 + 知名游资买入 + 题材龙头
|
||||
3. **优先级3**:确定性低 + 单席位买入 + 题材跟风
|
||||
|
||||
### 技巧3:仓位管理
|
||||
```
|
||||
总资金 = 100%
|
||||
├── 高确定性股票 (30-40%)
|
||||
├── 中确定性股票 (20-30%)
|
||||
├── 低确定性股票 (10-15%)
|
||||
└── 现金储备 (15-20%)
|
||||
```
|
||||
|
||||
### 技巧4:买卖时机
|
||||
- **买入时机**:
|
||||
- 开盘后观察5-15分钟
|
||||
- 回调至支撑位时介入
|
||||
- 突破前高时追涨(谨慎)
|
||||
|
||||
- **卖出时机**:
|
||||
- 到达目标价位及时止盈
|
||||
- 跌破止损位果断止损
|
||||
- 题材退潮信号出现时离场
|
||||
|
||||
### 技巧5:风险控制
|
||||
- ✅ 永远设置止损位(建议5-8%)
|
||||
- ✅ 不要满仓单只股票
|
||||
- ✅ 避免追高站岗
|
||||
- ✅ 题材炒作后期不参与
|
||||
- ✅ 游资分歧加大时减仓
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### ❌ 常见错误
|
||||
1. **过度追高**:看到推荐就追涨,容易站岗
|
||||
2. **不设止损**:侥幸心理,小亏变大亏
|
||||
3. **重仓单股**:押注单只股票,风险过高
|
||||
4. **忽视风险**:只看推荐不看风险提示
|
||||
5. **盲目跟风**:不分析直接照搬操作
|
||||
|
||||
### ✅ 正确做法
|
||||
1. **理性分析**:结合AI建议和自己判断
|
||||
2. **分批建仓**:不要一次性买入
|
||||
3. **严格止损**:设定止损位并执行
|
||||
4. **及时止盈**:有利润及时兑现
|
||||
5. **持续学习**:总结经验,提高胜率
|
||||
|
||||
## 📈 提高成功率的方法
|
||||
|
||||
### 方法1:历史验证
|
||||
- 定期查看"历史报告"
|
||||
- 统计AI推荐的准确率
|
||||
- 总结成功案例的共性
|
||||
- 分析失败案例的原因
|
||||
|
||||
### 方法2:结合其他工具
|
||||
- 使用"智策板块"分析板块趋势
|
||||
- 使用"主力选股"分析主力资金
|
||||
- 使用"实时监测"跟踪推荐股票
|
||||
|
||||
### 方法3:建立交易日志
|
||||
记录每次操作:
|
||||
- 买入理由(AI推荐+自己判断)
|
||||
- 买入价格、目标价、止损价
|
||||
- 实际卖出价格和原因
|
||||
- 盈亏情况和心得体会
|
||||
|
||||
### 方法4:持续优化策略
|
||||
- 每周复盘:统计胜率、盈亏比
|
||||
- 每月总结:找出最有效的策略
|
||||
- 每季度调整:优化选股和仓位管理
|
||||
|
||||
## 🔧 常见问题
|
||||
|
||||
### Q1:为什么没有获取到数据?
|
||||
**A1**:可能的原因:
|
||||
- 网络连接问题
|
||||
- StockAPI接口繁忙
|
||||
- 选择的日期非交易日
|
||||
- 解决方法:检查网络,重试,或换个日期
|
||||
|
||||
### Q2:AI分析需要多长时间?
|
||||
**A2**:通常需要8-15分钟,因为:
|
||||
- 5位AI分析师依次工作
|
||||
- 每位分析师需要2-3分钟
|
||||
- 首席策略师综合需要3-5分钟
|
||||
|
||||
### Q3:推荐的股票一定会涨吗?
|
||||
**A3**:不一定!
|
||||
- AI分析基于历史数据和当前信息
|
||||
- 市场存在不确定性
|
||||
- 需要结合市场环境和个人判断
|
||||
- 务必设置止损控制风险
|
||||
|
||||
### Q4:可以用于港股吗?
|
||||
**A4**:目前仅支持A股龙虎榜数据
|
||||
|
||||
### Q5:历史数据会保存多久?
|
||||
**A5**:永久保存在本地数据库(longhubang.db)中
|
||||
|
||||
## 📚 进阶学习
|
||||
|
||||
### 推荐阅读
|
||||
1. 龙虎榜基础知识
|
||||
2. 游资操作手法解析
|
||||
3. 题材炒作周期理论
|
||||
4. 短线交易技巧
|
||||
|
||||
### 实战练习
|
||||
1. 先用小资金试验(1-2万)
|
||||
2. 记录每次操作和结果
|
||||
3. 总结经验,优化策略
|
||||
4. 逐步提高仓位
|
||||
|
||||
## 📞 获取帮助
|
||||
|
||||
如有问题,可以:
|
||||
1. 查看"智瞰龙虎功能说明.md"
|
||||
2. 查看系统内的功能介绍
|
||||
3. 参考AI分析师的详细报告
|
||||
|
||||
---
|
||||
|
||||
**祝您投资顺利!** 🎉
|
||||
|
||||
记住:AI是辅助工具,最终决策由您自己做出。理性投资,风险自担!
|
||||
|
||||
Reference in New Issue
Block a user