增加龙虎榜批量分析功能,修复一些小bug

This commit is contained in:
oficcejo
2025-10-20 15:40:14 +08:00
parent 1bddf393e0
commit b7a8bb10b3
60 changed files with 3579 additions and 883 deletions
+272
View File
@@ -0,0 +1,272 @@
# 统一股票分析调用规范
## 📌 核心原则
**所有涉及股票分析的功能必须使用统一的分析函数和数据结构!**
---
## 🎯 适用场景
✅ 以下所有场景必须遵循此规范:
- 首页单股分析
- 首页批量分析
- 持仓批量分析(UI触发)
- 持仓定时分析(自动触发)
- 智策板块中的个股分析
- 智瞰龙虎中的个股分析
- 主力选股中的个股分析
- **任何未来新增的股票分析功能**
---
## ✅ 正确做法
### 1. 调用统一分析函数
```python
from app import analyze_single_stock_for_batch
result = analyze_single_stock_for_batch(
symbol="600519.SH",
period="1y",
enabled_analysts_config={
'technical': True,
'fundamental': True,
'fund_flow': True,
'risk': True,
'sentiment': False,
'news': False
},
selected_model="deepseek-chat"
)
```
### 2. 使用统一字段名
```python
# 提取分析结果
final_decision = result["final_decision"]
stock_info = result["stock_info"]
# 使用正确的字段名
rating = final_decision.get("rating", "未知") # ✅
confidence = final_decision.get("confidence_level", "N/A") # ✅
entry_range = final_decision.get("entry_range", "N/A") # ✅
take_profit = final_decision.get("take_profit", "N/A") # ✅
stop_loss = final_decision.get("stop_loss", "N/A") # ✅
target_price = final_decision.get("target_price", "N/A") # ✅
advice = final_decision.get("advice", "") # ✅
```
### 3. 统一数据解析
```python
import re
# 解析进场区间(格式如"10.5-12.3"
entry_range = final_decision.get("entry_range", "")
entry_min, entry_max = None, None
if entry_range and isinstance(entry_range, str) and "-" in entry_range:
try:
parts = entry_range.split("-")
entry_min = float(parts[0].strip())
entry_max = float(parts[1].strip())
except:
pass
# 解析止盈止损(提取数字,如"15.8元" → 15.8
take_profit_str = final_decision.get("take_profit", "")
take_profit = None
if take_profit_str:
try:
numbers = re.findall(r'\d+\.?\d*', str(take_profit_str))
if numbers:
take_profit = float(numbers[0])
except:
pass
# 止损位同理
stop_loss_str = final_decision.get("stop_loss", "")
stop_loss = None
if stop_loss_str:
try:
numbers = re.findall(r'\d+\.?\d*', str(stop_loss_str))
if numbers:
stop_loss = float(numbers[0])
except:
pass
```
### 4. 统一结果展示
```python
# 评级颜色标识
if "强烈买入" in rating or "买入" in rating:
rating_color = "🟢"
elif "卖出" in rating:
rating_color = "🔴"
else:
rating_color = "🟡"
# UI展示(Streamlit示例)
with st.expander(f"{rating_color} {code} - {rating} (信心度: {confidence})"):
col1, col2 = st.columns(2)
with col1:
st.markdown("**进出场位置**")
st.write(f"进场区间: {entry_range}")
st.write(f"目标价: {target_price}")
with col2:
st.markdown("**风控位置**")
st.write(f"止盈位: {take_profit}")
st.write(f"止损位: {stop_loss}")
if advice:
st.markdown("**投资建议**")
st.info(advice)
```
---
## ❌ 禁止行为
### 1. 不要直接调用 ai_agents
```python
# ❌ 错误做法
from ai_agents import StockAnalysisAgents
agents = StockAnalysisAgents()
result = agents.technical_analyst_agent(...) # 禁止!
```
### 2. 不要使用废弃字段名
```python
# ❌ 错误的字段名
rating = final_decision.get("investment_rating") # 已废弃
confidence = final_decision.get("confidence") # 已废弃
positions = final_decision.get("entry_exit_positions") # 已废弃
entry_min = positions.get("entry_zone_min") # 已废弃
```
### 3. 不要重复实现分析逻辑
```python
# ❌ 错误做法
from stock_data import StockDataFetcher
from ai_agents import StockAnalysisAgents
fetcher = StockDataFetcher()
agents = StockAnalysisAgents()
# 自己获取数据
stock_data = fetcher.get_stock_data(symbol)
indicators = fetcher.calculate_technical_indicators(stock_data)
# 自己调用分析师
result = agents.technical_analyst_agent(...) # 禁止!
```
---
## 📋 字段对照表
| 正确字段名 | 废弃字段名 | 数据类型 | 示例值 |
|-----------|-----------|---------|-------|
| `rating` | `investment_rating` | string | "买入", "持有", "卖出" |
| `confidence_level` | `confidence` | string/number | "8/10", "N/A" |
| `entry_range` | `entry_exit_positions["entry_zone_min/max"]` | string | "10.5-12.3" |
| `take_profit` | `entry_exit_positions["take_profit"]` | string | "止盈: 15.8元" |
| `stop_loss` | `entry_exit_positions["stop_loss"]` | string | "止损: 9.2元" |
| `target_price` | - | string | "目标价: 18.5元" |
| `advice` | `summary` | string | "建议买入..." |
---
## 🔍 代码审查检查清单
提交涉及股票分析的代码时,请确认:
- [ ] 使用了 `app.analyze_single_stock_for_batch()` 而非直接调用 `ai_agents`
- [ ] 使用了正确的字段名(`rating`, `confidence_level`, `entry_range`等)
- [ ] 没有使用废弃字段名(`investment_rating`, `entry_exit_positions`等)
- [ ] 数据解析逻辑与规范一致(split("-"), re.findall()
- [ ] UI展示格式与其他模块保持一致
- [ ] 通知推送使用相同的数据结构
---
## 📚 参考代码
### 推荐参考
1. **`portfolio_manager.py`** - 完整的分析调用和数据保存示例
2. **`portfolio_ui.py`** - UI展示和数据解析示例
3. **`portfolio_scheduler.py`** - 监测同步和通知推送示例
4. **`notification_service.py`** - 通知内容构建示例
### 设计文档
- **`openspec/changes/add-portfolio-scheduled-analysis/design.md`** - Decision 4: 统一股票分析调用规范
- **`openspec/changes/add-portfolio-scheduled-analysis/specs/stock-analysis/spec.md`** - Requirement: 统一股票分析调用规范
---
## 💡 好处
遵循此规范可以获得:
1.**维护成本降低**:只需维护一个分析函数
2.**测试成本降低**:只需测试一个分析流程
3.**Bug修复效率**:一处修复,全局生效
4.**新功能快速开发**:直接复用,无需重写
5.**用户体验一致**:所有场景看到的结果格式一致
6.**代码复用最大化**:避免重复代码
7.**自动兼容优化**:首页分析的优化自动应用到所有场景
---
## ⚠️ 违规后果
不遵循此规范可能导致:
- ❌ 字段名不一致,UI显示"未知"或错误
- ❌ 数据解析失败,监测同步失败
- ❌ 通知推送格式错误
- ❌ 代码重复,维护困难
- ❌ Bug修复需要改多处
- ❌ 用户体验不一致
---
## 🆘 常见问题
### Q: 为什么必须使用统一函数?
A: 确保所有场景使用相同的AI模型、数据源、分析流程,避免结果不一致。首页分析的任何优化都会自动应用到所有场景。
### Q: 为什么不能直接调用 ai_agents?
A: `app.analyze_single_stock_for_batch()` 已经封装了完整的数据获取、分析、错误处理流程。直接调用 ai_agents 会导致代码重复和逻辑不一致。
### Q: 旧代码使用了废弃字段怎么办?
A: 必须修改!参考 `portfolio_manager.py` 中的正确用法,使用新的字段名。
### Q: 如何解析字符串字段(如进场区间)?
A: 参考本文档"统一数据解析"章节的代码示例,使用 `split("-")` 和正则表达式。
### Q: 新功能可以不遵循此规范吗?
A: **不可以!** 所有涉及股票分析的功能都必须遵循此规范,这是强制要求。
---
## 📝 更新日志
- **2024-10-20**: 初始版本,基于持仓定时分析功能的实践总结
- **规范来源**: OpenSpec - `add-portfolio-scheduled-analysis` - Decision 4
---
**遵循规范,代码更优!** 🎉