diff --git a/.env.example b/.env.example
index 5529c41..bfeeb47 100644
--- a/.env.example
+++ b/.env.example
@@ -15,6 +15,8 @@ DEEPSEEK_API_KEY=your_actual_deepseek_api_key_here
# DeepSeek API基础URL(可选,使用默认值即可)
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
+# DeepSeek 模型名称,为空时取默认值 deepseek-chat
+DEEPSEEK_MODEL_NAME=deepseek-chat
# ========== Tushare数据接口(可选)==========
# Tushare Token(可选,用于获取更多金融数据)
diff --git a/.gitignore b/.gitignore
index 1dfa6a0..98fb92c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,22 @@
.env
/.cursor
/openspec
-TradEnv/
\ No newline at end of file
+TradEnv/
+/.idea/inspectionProfiles/profiles_settings.xml
+/.idea/inspectionProfiles/Project_Default.xml
+/.idea/.gitignore
+/.idea/aiagents-stock.iml
+/.idea/misc.xml
+/.idea/modules.xml
+/.idea/vcs.xml
+/data/longhubang.db
+/data/low_price_bull_monitor.db
+/data/main_force_batch.db
+/data/portfolio_stocks.db
+/data/profit_growth_monitor.db
+/data/sector_strategy.db
+/data/smart_monitor.db
+/data/stock_analysis.db
+/data/stock_monitor.db
+/migrate_databases.sh
+/migrate_databases_by_size.sh
diff --git "a/AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md" "b/AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..ccd0e32
--- /dev/null
+++ "b/AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md"
@@ -0,0 +1,258 @@
+# AI模型选择机制说明
+
+## 📋 问题回答
+
+### 1. 左侧的AI模型选择会全局默认生效吗?
+
+**答案:部分生效,但不完全全局**
+
+**当前状态**:
+- ✅ 模型选择器会保存到 `st.session_state.selected_model`
+- ❌ 但很多功能模块**强制使用** `config.DEEPSEEK_MODEL_NAME`(从 `.env` 文件读取),**忽略**了 `session_state` 中的选择
+- ✅ 只有部分页面(如"主力选股")会使用页面内的模型选择
+
+**具体表现**:
+- **股票分析页面**:强制使用 `config.DEEPSEEK_MODEL_NAME`,忽略侧边栏选择
+- **批量分析功能**:强制使用 `config.DEEPSEEK_MODEL_NAME`,忽略侧边栏选择
+- **主力选股页面**:使用页面内的模型选择(不是侧边栏的)
+- **智策板块页面**:强制使用 `config.DEEPSEEK_MODEL_NAME`
+
+### 2. 如果选择其他模型,模型信息在哪里配置?
+
+**答案:两个地方**
+
+#### 位置1:模型选项列表 - `model_config.py`
+
+**文件路径**:`model_config.py`
+
+**作用**:定义所有可用的AI模型选项
+
+**内容示例**:
+```python
+model_options = {
+ "deepseek-chat": "DeepSeek Chat (默认)",
+ "deepseek-reasoner": "DeepSeek Reasoner (推理增强)",
+ "qwen-plus": "qwen-plus (阿里百炼)",
+ # ... 更多模型
+}
+```
+
+**如何添加新模型**:
+1. 在 `model_config.py` 的 `model_options` 字典中添加新项
+2. 格式:`"模型ID": "显示名称"`
+
+#### 位置2:默认模型配置 - `.env` 文件
+
+**文件路径**:`.env`(项目根目录)
+
+**作用**:设置系统默认使用的模型
+
+**配置项**:
+```bash
+DEEPSEEK_MODEL_NAME=deepseek-chat
+```
+
+**如何修改默认模型**:
+1. 编辑 `.env` 文件
+2. 修改 `DEEPSEEK_MODEL_NAME` 的值
+3. 值必须是 `model_config.py` 中 `model_options` 的键之一
+
+---
+
+## 🔍 代码实现分析
+
+### 模型选择器(侧边栏)
+
+**位置**:`app.py` 的 `model_selector()` 函数
+
+**代码**:
+```python
+def model_selector():
+ """模型选择器"""
+ st.sidebar.subheader("🤖 AI模型选择")
+
+ # 获取配置文件中的默认模型
+ default_model = config.DEEPSEEK_MODEL_NAME
+
+ # 从 session_state 获取当前选择
+ current_model = st.session_state.get('selected_model', default_model)
+
+ # 显示选择框
+ selected_model = st.sidebar.selectbox(
+ "选择AI模型",
+ options=list(model_options.keys()),
+ ...
+ )
+
+ return selected_model
+```
+
+**问题**:虽然保存到 `session_state`,但很多地方不使用它
+
+### 实际使用情况
+
+#### ❌ 不生效的地方(强制使用配置文件)
+
+**1. 股票分析页面** (`app.py` 的 `run_stock_analysis`)
+```python
+# 强制使用配置文件中的默认模型(忽略 session_state 中的旧值)
+config_model = config.DEEPSEEK_MODEL_NAME
+if config_model in model_options:
+ selected_model = config_model
+else:
+ selected_model = list(model_options.keys())[0]
+
+agents = StockAnalysisAgents(model=selected_model) # 使用配置文件的值
+```
+
+**2. 批量分析功能** (`app.py` 的 `run_batch_analysis`)
+```python
+# 强制使用配置文件中的默认模型
+config_model = config.DEEPSEEK_MODEL_NAME
+if config_model in model_options:
+ selected_model = config_model
+else:
+ selected_model = list(model_options.keys())[0]
+```
+
+**3. 批量分析中的单个股票分析** (`app.py` 的 `analyze_single_stock_for_batch`)
+```python
+# 强制使用配置文件中的默认模型(忽略传入的旧值)
+config_model = config.DEEPSEEK_MODEL_NAME
+if selected_model is None or selected_model == "" or selected_model == "deepseek-chat":
+ selected_model = config_model
+```
+
+#### ✅ 生效的地方
+
+**1. 主力选股页面** (`main_force_ui.py`)
+```python
+# 页面内有自己的模型选择
+model = st.selectbox(
+ "选择AI模型",
+ list(app_model_options.keys()),
+ ...
+)
+
+analyzer = MainForceAnalyzer(model=model) # 使用页面选择的值
+```
+
+---
+
+## 🔧 如何让侧边栏选择全局生效?
+
+### 方案1:修改代码使用 session_state(推荐)
+
+修改所有强制使用 `config.DEEPSEEK_MODEL_NAME` 的地方,改为优先使用 `session_state.selected_model`:
+
+```python
+# 修改前
+config_model = config.DEEPSEEK_MODEL_NAME
+selected_model = config_model
+
+# 修改后
+selected_model = st.session_state.get('selected_model', config.DEEPSEEK_MODEL_NAME)
+if selected_model not in model_options:
+ selected_model = config.DEEPSEEK_MODEL_NAME
+```
+
+**需要修改的文件**:
+1. `app.py` - `run_stock_analysis()` 函数
+2. `app.py` - `run_batch_analysis()` 函数
+3. `app.py` - `analyze_single_stock_for_batch()` 函数
+
+### 方案2:保持现状,使用配置文件
+
+**优点**:
+- 配置持久化(重启后仍然有效)
+- 不依赖 Streamlit session
+
+**缺点**:
+- 需要修改 `.env` 文件才能改变模型
+- 不能通过UI快速切换
+
+---
+
+## 📝 模型配置详细说明
+
+### model_config.py 结构
+
+```python
+model_options = {
+ # 键:模型ID(用于API调用)
+ # 值:显示名称(在UI中显示)
+ "deepseek-chat": "DeepSeek Chat (默认)",
+ "deepseek-reasoner": "DeepSeek Reasoner (推理增强)",
+ # ...
+}
+```
+
+### 添加新模型的步骤
+
+1. **确定模型ID**:从API文档获取模型标识符
+2. **添加到 model_config.py**:
+ ```python
+ model_options = {
+ # ... 现有模型
+ "new-model-id": "新模型显示名称",
+ }
+ ```
+3. **(可选)设置为默认**:在 `.env` 文件中设置
+ ```bash
+ DEEPSEEK_MODEL_NAME=new-model-id
+ ```
+
+### 当前可用的模型
+
+根据 `model_config.py`,当前支持以下模型:
+
+| 模型ID | 显示名称 | 说明 |
+|--------|----------|------|
+| `deepseek-chat` | DeepSeek Chat (默认) | 默认模型 |
+| `deepseek-reasoner` | DeepSeek Reasoner (推理增强) | 推理能力更强 |
+| `qwen-plus` | qwen-plus (阿里百炼) | 阿里云模型 |
+| `qwen-plus-latest` | qwen-plus-latest (阿里百炼) | 最新版本 |
+| `qwen-flash` | qwen-flash (阿里百炼) | 快速版本 |
+| `qwen-turbo` | qwen-turbo (阿里百炼) | 加速版本 |
+| `qwen3-max` | qwen-max (阿里百炼) | 最大版本 |
+| `qwen-long` | qwen-long (阿里百炼) | 长文本版本 |
+| `deepseek-ai/DeepSeek-R1-0528-Qwen3-8B` | DeepSeek-R1 免费(硅基流动) | 免费模型 |
+| `Qwen/Qwen2.5-7B-Instruct` | Qwen 免费(硅基流动) | 免费模型 |
+| `Pro/deepseek-ai/DeepSeek-V3.1-Terminus` | DeepSeek-V3.1-Terminus (硅基流动) | 专业版 |
+| `deepseek-ai/DeepSeek-R1` | DeepSeek-R1 (硅基流动) | R1版本 |
+| `Qwen/Qwen3-235B-A22B-Thinking-2507` | Qwen3-235B (硅基流动) | 大模型 |
+| `zai-org/GLM-4.6` | 智谱(硅基流动) | 智谱模型 |
+| `moonshotai/Kimi-K2-Instruct-0905` | Kimi (硅基流动) | Kimi模型 |
+| `Ring-1T` | 蚂蚁百灵 (硅基流动) | 蚂蚁模型 |
+| `step3` | 阶跃星辰(硅基流动) | 阶跃模型 |
+
+---
+
+## 🎯 建议
+
+### 短期方案(保持现状)
+
+1. **修改默认模型**:编辑 `.env` 文件,修改 `DEEPSEEK_MODEL_NAME`
+2. **主力选股页面**:使用页面内的模型选择(已生效)
+
+### 长期方案(推荐)
+
+修改代码,让侧边栏的模型选择真正全局生效:
+
+1. 修改 `app.py` 中所有使用模型的地方
+2. 优先使用 `st.session_state.selected_model`
+3. 如果不存在或无效,回退到 `config.DEEPSEEK_MODEL_NAME`
+
+这样可以:
+- ✅ 通过UI快速切换模型
+- ✅ 配置持久化(通过 `.env`)
+- ✅ 用户体验更好
+
+---
+
+## 📚 相关文件
+
+- **模型选项定义**:`model_config.py`
+- **默认模型配置**:`.env` 文件中的 `DEEPSEEK_MODEL_NAME`
+- **模型选择器**:`app.py` 的 `model_selector()` 函数
+- **配置文件加载**:`config.py`
diff --git a/README.md b/README.md
index 756dc13..f75cbc6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,10 @@
# 🤖 复合多AI智能体股票团队分析系统
-- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎!
+- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎!欢迎加入qq群聊,群号:1059277514
+
+
+**点击zread图标,查看详细文档**
+[](https://zread.ai/oficcejo/aiagents-stock)
## ⭐ 1214更新 - 净利增长策略 📈
diff --git a/ai_agents.py b/ai_agents.py
index 75ea06e..c6efe57 100644
--- a/ai_agents.py
+++ b/ai_agents.py
@@ -1,13 +1,30 @@
from deepseek_client import DeepSeekClient
from typing import Dict, Any
import time
+import config
class StockAnalysisAgents:
"""股票分析AI智能体集合"""
- def __init__(self, model="deepseek-chat"):
- self.model = model
- self.deepseek_client = DeepSeekClient(model=model)
+ def __init__(self, model=None):
+ # 调试:打印传入的参数和配置
+ print(f"[StockAnalysisAgents.__init__] 传入参数: model={model}")
+ print(f"[StockAnalysisAgents.__init__] 配置文件中的 DEEPSEEK_MODEL_NAME: {config.DEEPSEEK_MODEL_NAME}")
+
+ # 强制使用配置文件中的默认模型
+ # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值
+ if model is None or model == "" or model == "deepseek-chat":
+ self.model = config.DEEPSEEK_MODEL_NAME
+ if model == "deepseek-chat":
+ print(f"[StockAnalysisAgents.__init__] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}")
+ else:
+ print(f"[StockAnalysisAgents.__init__] 使用配置文件中的默认模型: {self.model}")
+ else:
+ self.model = model
+ print(f"[StockAnalysisAgents.__init__] 使用传入的模型参数: {self.model}")
+
+ print(f"[StockAnalysisAgents.__init__] ✅ 最终使用的模型: {self.model}")
+ self.deepseek_client = DeepSeekClient(model=self.model)
def technical_analyst_agent(self, stock_info: Dict, stock_data: Any, indicators: Dict) -> Dict[str, Any]:
"""技术面分析智能体"""
diff --git a/app.py b/app.py
index f030097..609fec7 100644
--- a/app.py
+++ b/app.py
@@ -18,6 +18,7 @@
from monitor_service import monitor_service
from notification_service import notification_service
from config_manager import config_manager
+import config
from main_force_ui import display_main_force_selector
from sector_strategy_ui import display_sector_strategy
from longhubang_ui import display_longhubang
@@ -37,17 +38,52 @@ def model_selector():
st.sidebar.markdown("---")
st.sidebar.subheader("🤖 AI模型选择")
-
+ # 获取配置文件中的默认模型
+ default_model = config.DEEPSEEK_MODEL_NAME
+
+ # 如果配置的模型不在选项中,使用列表第一个
+ if default_model not in model_options:
+ default_model = list(model_options.keys())[0]
+
+ # 如果 session_state 中已有值,且该值在选项中,使用它;否则使用配置的默认值
+ current_model = st.session_state.get('selected_model', default_model)
+ if current_model not in model_options:
+ current_model = default_model
selected_model = st.sidebar.selectbox(
"选择AI模型",
options=list(model_options.keys()),
+ index=list(model_options.keys()).index(current_model) if current_model in model_options else 0,
format_func=lambda x: model_options[x],
help="DeepSeek Reasoner提供更强的推理能力,但响应时间可能更长"
)
return selected_model
+
+def get_selected_model():
+ """
+ 获取当前选择的AI模型
+ 优先使用session_state中的选择,如果不存在或无效,则使用配置文件中的默认值
+
+ Returns:
+ str: 模型ID
+ """
+ # 优先使用session_state中的选择
+ selected_model = st.session_state.get('selected_model')
+
+ # 如果session_state中有值且在有效选项中,使用它
+ if selected_model and selected_model in model_options:
+ return selected_model
+
+ # 否则使用配置文件中的默认值
+ default_model = config.DEEPSEEK_MODEL_NAME
+ if default_model in model_options:
+ return default_model
+
+ # 如果配置文件的值也不在选项中,使用第一个选项
+ return list(model_options.keys())[0]
+
# 自定义CSS样式 - 专业版
st.markdown("""