diff --git a/README.md b/README.md
index 30a932b..eb033cd 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,18 @@
# 🤖 复合多AI智能体股票团队分析系统
-- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤枉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),结合跟踪主力资金玩法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,形成了自己的交易系统,近1一个月来,账户也慢慢在扭亏为盈。开源此软件的目的,就是为了使像我一样的一些小散,不再迷茫,也许这个软件不能让你发财,但是他能给你信心。希望能帮到你!欢迎加微信群讨论
+- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤枉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),结合跟踪主力资金玩法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,形成了自己的交易系统,近1一个月来,账户也慢慢在扭亏为盈。开源此软件的目的,就是为了使像我一样的一些小散,不再迷茫,也许这个软件不能让你发财,但是他能给你信心。
+- 希望能帮到你!欢迎加微信群讨论
### 基于Python + Streamlit + DeepSeek的智能股票分析系统,模拟证券公司分析师团队,提供全方位的股票投资分析和决策建议。
+# 注意!!!右侧官方测试网站,请在环境配置中设置deepseek临时apikey,测试结束后请尽快删除或禁用!!否则会有泄露风险
+
## ✨ 更新说明
-### 增加股票监测功能,增加历史记录中个股导入到监测板块
+### 1006增加跟踪主力资金mcp,增加环境配置功能
+### 1005增加股票监测功能,增加历史记录中个股导入到监测板块
## ✨ 功能特色
diff --git a/app.py b/app.py
index dadafbb..79555b1 100644
--- a/app.py
+++ b/app.py
@@ -15,6 +15,7 @@ from database import db
from monitor_manager import display_monitor_manager, get_monitor_summary
from monitor_service import monitor_service
from notification_service import notification_service
+from config_manager import config_manager
# 页面配置
st.set_page_config(
@@ -301,6 +302,15 @@ def main():
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 st.button("⚙️ 环境配置", use_container_width=True, key="nav_config"):
+ st.session_state.show_config = 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
st.markdown("---")
@@ -383,6 +393,11 @@ def main():
display_monitor_manager()
return
+ # 检查是否显示环境配置
+ if 'show_config' in st.session_state and st.session_state.show_config:
+ display_config_manager()
+ return
+
# 主界面
col1, col2, col3 = st.columns([2, 1, 1])
@@ -1333,5 +1348,216 @@ def display_record_detail(record_id):
del st.session_state.add_to_monitor_id
st.rerun()
+def display_config_manager():
+ """显示环境配置管理界面"""
+ st.subheader("⚙️ 环境配置管理")
+
+ st.markdown("""
+
+
在这里可以配置系统的环境变量,包括API密钥、数据源配置、量化交易配置等。
+
注意:配置修改后需要重启应用才能生效。
+
+ """, unsafe_allow_html=True)
+
+ # 获取当前配置
+ config_info = config_manager.get_config_info()
+
+ # 创建标签页
+ tab1, tab2, tab3 = st.tabs(["📝 基本配置", "📊 数据源配置", "🤖 量化交易配置"])
+
+ # 使用session_state保存临时配置
+ if 'temp_config' not in st.session_state:
+ st.session_state.temp_config = {key: info["value"] for key, info in config_info.items()}
+
+ with tab1:
+ st.markdown("### DeepSeek API配置")
+ st.markdown("DeepSeek是系统的核心AI引擎,必须配置才能使用分析功能。")
+
+ # DeepSeek API Key
+ api_key_info = config_info["DEEPSEEK_API_KEY"]
+ current_api_key = st.session_state.temp_config.get("DEEPSEEK_API_KEY", "")
+
+ new_api_key = st.text_input(
+ f"🔑 {api_key_info['description']} {'*' if api_key_info['required'] else ''}",
+ value=current_api_key,
+ type="password",
+ help="从 https://platform.deepseek.com 获取API密钥",
+ key="input_deepseek_api_key"
+ )
+ st.session_state.temp_config["DEEPSEEK_API_KEY"] = new_api_key
+
+ # 显示当前状态
+ if new_api_key:
+ masked_key = new_api_key[:8] + "*" * (len(new_api_key) - 12) + new_api_key[-4:] if len(new_api_key) > 12 else "***"
+ st.success(f"✅ API密钥已设置: {masked_key}")
+ else:
+ st.warning("⚠️ 未设置API密钥,系统无法使用AI分析功能")
+
+ st.markdown("---")
+
+ # DeepSeek Base URL
+ base_url_info = config_info["DEEPSEEK_BASE_URL"]
+ current_base_url = st.session_state.temp_config.get("DEEPSEEK_BASE_URL", "")
+
+ new_base_url = st.text_input(
+ f"🌐 {base_url_info['description']}",
+ value=current_base_url,
+ help="一般无需修改,保持默认即可",
+ key="input_deepseek_base_url"
+ )
+ st.session_state.temp_config["DEEPSEEK_BASE_URL"] = new_base_url
+
+ st.info("💡 如何获取DeepSeek API密钥?\n\n1. 访问 https://platform.deepseek.com\n2. 注册/登录账号\n3. 进入API密钥管理页面\n4. 创建新的API密钥\n5. 复制密钥并粘贴到上方输入框")
+
+ with tab2:
+ st.markdown("### Tushare数据接口(可选)")
+ st.markdown("Tushare提供更丰富的A股财务数据,配置后可以获取更详细的财务分析。")
+
+ tushare_info = config_info["TUSHARE_TOKEN"]
+ current_tushare = st.session_state.temp_config.get("TUSHARE_TOKEN", "")
+
+ new_tushare = st.text_input(
+ f"🎫 {tushare_info['description']}",
+ value=current_tushare,
+ type="password",
+ help="从 https://tushare.pro 获取Token",
+ key="input_tushare_token"
+ )
+ st.session_state.temp_config["TUSHARE_TOKEN"] = new_tushare
+
+ if new_tushare:
+ st.success("✅ Tushare Token已设置")
+ else:
+ st.info("ℹ️ 未设置Tushare Token,系统将使用其他数据源")
+
+ st.info("💡 如何获取Tushare Token?\n\n1. 访问 https://tushare.pro\n2. 注册账号\n3. 进入个人中心\n4. 获取Token\n5. 复制并粘贴到上方输入框")
+
+ with tab3:
+ st.markdown("### MiniQMT量化交易配置(可选)")
+ st.markdown("配置后可以使用量化交易功能,自动执行交易策略。")
+
+ # 启用开关
+ miniqmt_enabled_info = config_info["MINIQMT_ENABLED"]
+ current_enabled = st.session_state.temp_config.get("MINIQMT_ENABLED", "false") == "true"
+
+ new_enabled = st.checkbox(
+ "启用MiniQMT量化交易",
+ value=current_enabled,
+ help="开启后可以使用量化交易功能",
+ key="input_miniqmt_enabled"
+ )
+ st.session_state.temp_config["MINIQMT_ENABLED"] = "true" if new_enabled else "false"
+
+ # 其他配置
+ col1, col2 = st.columns(2)
+
+ with col1:
+ account_id_info = config_info["MINIQMT_ACCOUNT_ID"]
+ current_account_id = st.session_state.temp_config.get("MINIQMT_ACCOUNT_ID", "")
+
+ new_account_id = st.text_input(
+ f"🆔 {account_id_info['description']}",
+ value=current_account_id,
+ disabled=not new_enabled,
+ key="input_miniqmt_account_id"
+ )
+ st.session_state.temp_config["MINIQMT_ACCOUNT_ID"] = new_account_id
+
+ host_info = config_info["MINIQMT_HOST"]
+ current_host = st.session_state.temp_config.get("MINIQMT_HOST", "")
+
+ new_host = st.text_input(
+ f"🖥️ {host_info['description']}",
+ value=current_host,
+ disabled=not new_enabled,
+ key="input_miniqmt_host"
+ )
+ st.session_state.temp_config["MINIQMT_HOST"] = new_host
+
+ with col2:
+ port_info = config_info["MINIQMT_PORT"]
+ current_port = st.session_state.temp_config.get("MINIQMT_PORT", "")
+
+ new_port = st.text_input(
+ f"🔌 {port_info['description']}",
+ value=current_port,
+ disabled=not new_enabled,
+ key="input_miniqmt_port"
+ )
+ st.session_state.temp_config["MINIQMT_PORT"] = new_port
+
+ if new_enabled:
+ st.success("✅ MiniQMT已启用")
+ else:
+ st.info("ℹ️ MiniQMT未启用")
+
+ st.warning("⚠️ 警告:量化交易涉及真实资金操作,请谨慎配置和使用!")
+
+ # 操作按钮
+ st.markdown("---")
+ col1, col2, col3, col4 = st.columns([1, 1, 1, 2])
+
+ with col1:
+ if st.button("💾 保存配置", type="primary", use_container_width=True):
+ # 验证配置
+ is_valid, message = config_manager.validate_config(st.session_state.temp_config)
+
+ if is_valid:
+ # 保存配置
+ if config_manager.write_env(st.session_state.temp_config):
+ st.success("✅ 配置已保存到 .env 文件")
+ st.info("ℹ️ 请重启应用使配置生效")
+
+ # 尝试重新加载配置
+ try:
+ config_manager.reload_config()
+ st.success("✅ 配置已重新加载")
+ except Exception as e:
+ st.warning(f"⚠️ 配置重新加载失败: {e}")
+
+ time.sleep(2)
+ st.rerun()
+ else:
+ st.error("❌ 保存配置失败")
+ else:
+ st.error(f"❌ 配置验证失败: {message}")
+
+ with col2:
+ if st.button("🔄 重置", use_container_width=True):
+ # 重置为当前文件中的值
+ st.session_state.temp_config = {key: info["value"] for key, info in config_info.items()}
+ st.success("✅ 已重置为当前配置")
+ st.rerun()
+
+ with col3:
+ if st.button("⬅️ 返回", use_container_width=True):
+ if 'show_config' in st.session_state:
+ del st.session_state.show_config
+ if 'temp_config' in st.session_state:
+ del st.session_state.temp_config
+ st.rerun()
+
+ # 显示当前.env文件内容
+ st.markdown("---")
+ with st.expander("📄 查看当前 .env 文件内容"):
+ current_config = config_manager.read_env()
+
+ st.code(f"""# AI股票分析系统环境配置
+# 由系统自动生成和管理
+
+# ========== DeepSeek API配置 ==========
+DEEPSEEK_API_KEY="{current_config.get('DEEPSEEK_API_KEY', '')}"
+DEEPSEEK_BASE_URL="{current_config.get('DEEPSEEK_BASE_URL', '')}"
+
+# ========== Tushare数据接口(可选)==========
+TUSHARE_TOKEN="{current_config.get('TUSHARE_TOKEN', '')}"
+
+# ========== MiniQMT量化交易配置(可选)==========
+MINIQMT_ENABLED="{current_config.get('MINIQMT_ENABLED', 'false')}"
+MINIQMT_ACCOUNT_ID="{current_config.get('MINIQMT_ACCOUNT_ID', '')}"
+MINIQMT_HOST="{current_config.get('MINIQMT_HOST', '127.0.0.1')}"
+MINIQMT_PORT="{current_config.get('MINIQMT_PORT', '58610')}"
+""", language="bash")
+
if __name__ == "__main__":
main()
\ No newline at end of file
diff --git a/config_manager.py b/config_manager.py
new file mode 100644
index 0000000..47c6304
--- /dev/null
+++ b/config_manager.py
@@ -0,0 +1,174 @@
+"""
+环境配置管理模块
+用于读取和保存.env配置文件
+"""
+
+import os
+from pathlib import Path
+from typing import Dict, Any
+
+
+class ConfigManager:
+ """配置管理器"""
+
+ def __init__(self, env_file: str = ".env"):
+ self.env_file = Path(env_file)
+ self.default_config = {
+ "DEEPSEEK_API_KEY": {
+ "value": "",
+ "description": "DeepSeek API密钥",
+ "required": True,
+ "type": "password"
+ },
+ "DEEPSEEK_BASE_URL": {
+ "value": "https://api.deepseek.com/v1",
+ "description": "DeepSeek API地址",
+ "required": False,
+ "type": "text"
+ },
+ "TUSHARE_TOKEN": {
+ "value": "",
+ "description": "Tushare数据接口Token(可选)",
+ "required": False,
+ "type": "password"
+ },
+ "MINIQMT_ENABLED": {
+ "value": "false",
+ "description": "启用MiniQMT量化交易",
+ "required": False,
+ "type": "boolean"
+ },
+ "MINIQMT_ACCOUNT_ID": {
+ "value": "",
+ "description": "MiniQMT账户ID",
+ "required": False,
+ "type": "text"
+ },
+ "MINIQMT_HOST": {
+ "value": "127.0.0.1",
+ "description": "MiniQMT服务器地址",
+ "required": False,
+ "type": "text"
+ },
+ "MINIQMT_PORT": {
+ "value": "58610",
+ "description": "MiniQMT服务器端口",
+ "required": False,
+ "type": "text"
+ },
+ }
+
+ def read_env(self) -> Dict[str, str]:
+ """读取.env文件"""
+ config = {}
+
+ if not self.env_file.exists():
+ # 如果文件不存在,返回默认配置的值
+ for key, info in self.default_config.items():
+ config[key] = info["value"]
+ return config
+
+ try:
+ with open(self.env_file, 'r', encoding='utf-8') as f:
+ for line in f:
+ line = line.strip()
+ # 跳过空行和注释
+ if not line or line.startswith('#'):
+ continue
+
+ # 解析键值对
+ if '=' in line:
+ key, value = line.split('=', 1)
+ key = key.strip()
+ value = value.strip()
+
+ # 移除引号
+ if value.startswith('"') and value.endswith('"'):
+ value = value[1:-1]
+ elif value.startswith("'") and value.endswith("'"):
+ value = value[1:-1]
+
+ config[key] = value
+ except Exception as e:
+ print(f"读取.env文件失败: {e}")
+
+ # 确保所有默认配置项都存在
+ for key, info in self.default_config.items():
+ if key not in config:
+ config[key] = info["value"]
+
+ return config
+
+ def write_env(self, config: Dict[str, str]) -> bool:
+ """保存配置到.env文件"""
+ try:
+ lines = []
+ lines.append("# AI股票分析系统环境配置")
+ lines.append("# 由系统自动生成和管理")
+ lines.append("")
+
+ # DeepSeek配置
+ lines.append("# ========== DeepSeek API配置 ==========")
+ lines.append(f'DEEPSEEK_API_KEY="{config.get("DEEPSEEK_API_KEY", "")}"')
+ lines.append(f'DEEPSEEK_BASE_URL="{config.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com/v1")}"')
+ lines.append("")
+
+ # Tushare配置
+ lines.append("# ========== Tushare数据接口(可选)==========")
+ lines.append(f'TUSHARE_TOKEN="{config.get("TUSHARE_TOKEN", "")}"')
+ lines.append("")
+
+ # MiniQMT配置
+ lines.append("# ========== MiniQMT量化交易配置(可选)==========")
+ lines.append(f'MINIQMT_ENABLED="{config.get("MINIQMT_ENABLED", "false")}"')
+ lines.append(f'MINIQMT_ACCOUNT_ID="{config.get("MINIQMT_ACCOUNT_ID", "")}"')
+ lines.append(f'MINIQMT_HOST="{config.get("MINIQMT_HOST", "127.0.0.1")}"')
+ lines.append(f'MINIQMT_PORT="{config.get("MINIQMT_PORT", "58610")}"')
+
+ with open(self.env_file, 'w', encoding='utf-8') as f:
+ f.write('\n'.join(lines))
+
+ return True
+ except Exception as e:
+ print(f"保存.env文件失败: {e}")
+ return False
+
+ def get_config_info(self) -> Dict[str, Dict[str, Any]]:
+ """获取配置信息(包含描述、类型等)"""
+ current_values = self.read_env()
+
+ config_info = {}
+ for key, info in self.default_config.items():
+ config_info[key] = {
+ "value": current_values.get(key, info["value"]),
+ "description": info["description"],
+ "required": info["required"],
+ "type": info["type"]
+ }
+
+ return config_info
+
+ def validate_config(self, config: Dict[str, str]) -> tuple[bool, str]:
+ """验证配置"""
+ # 检查必填项
+ for key, info in self.default_config.items():
+ if info["required"] and not config.get(key):
+ return False, f"必填项 {info['description']} 不能为空"
+
+ # 验证API Key格式(简单检查长度)
+ if config.get("DEEPSEEK_API_KEY"):
+ api_key = config.get("DEEPSEEK_API_KEY", "")
+ if len(api_key) < 20:
+ return False, "DeepSeek API Key格式不正确(长度太短)"
+
+ return True, "配置验证通过"
+
+ def reload_config(self):
+ """重新加载配置(重新加载.env文件)"""
+ from dotenv import load_dotenv
+ load_dotenv(override=True)
+
+
+# 全局配置管理器实例
+config_manager = ConfigManager()
+
diff --git a/环境配置功能说明.md b/环境配置功能说明.md
new file mode 100644
index 0000000..c386e59
--- /dev/null
+++ b/环境配置功能说明.md
@@ -0,0 +1,193 @@
+# 环境配置功能说明
+
+## 功能概述
+
+新增了可视化的环境配置管理界面,用户可以通过UI界面配置系统的所有环境变量,无需手动编辑 `.env` 文件。
+
+## 访问方式
+
+在侧栏的"快捷导航"区域,点击 **⚙️ 环境配置** 按钮即可进入配置界面。
+
+## 配置项说明
+
+### 1. 基本配置(必需)
+
+#### DeepSeek API配置
+- **API密钥** (必填)
+ - 描述:DeepSeek AI引擎的API密钥
+ - 获取方式:访问 https://platform.deepseek.com
+ - 注意:这是系统核心功能,必须配置才能使用AI分析
+
+- **API地址** (可选)
+ - 描述:DeepSeek API服务器地址
+ - 默认值:`https://api.deepseek.com/v1`
+ - 注意:一般无需修改
+
+### 2. 数据源配置(可选)
+
+#### Tushare数据接口
+- **Token** (可选)
+ - 描述:Tushare数据接口令牌
+ - 获取方式:访问 https://tushare.pro
+ - 作用:提供更丰富的A股财务数据
+ - 注意:未配置时系统使用其他数据源
+
+### 3. 量化交易配置(可选)
+
+#### MiniQMT量化交易
+- **启用开关**
+ - 描述:是否启用MiniQMT量化交易功能
+ - 默认:关闭
+
+- **账户ID**
+ - 描述:MiniQMT交易账户ID
+ - 注意:仅在启用时需要配置
+
+- **服务器地址**
+ - 描述:MiniQMT服务器地址
+ - 默认:`127.0.0.1`
+
+- **服务器端口**
+ - 描述:MiniQMT服务器端口
+ - 默认:`58610`
+
+- **⚠️ 警告**:量化交易涉及真实资金操作,请谨慎配置和使用!
+
+## 使用流程
+
+1. **进入配置页面**
+ - 点击侧栏的"⚙️ 环境配置"按钮
+
+2. **修改配置**
+ - 在相应标签页中填写或修改配置项
+ - 必填项会有 `*` 标记
+ - 密码类型的配置会以 `****` 显示
+
+3. **保存配置**
+ - 点击"💾 保存配置"按钮
+ - 系统会验证配置的有效性
+ - 验证通过后保存到 `.env` 文件
+
+4. **生效配置**
+ - 配置保存后会自动尝试重新加载
+ - 建议重启应用以确保所有配置生效
+
+## 功能特性
+
+### ✅ 可视化配置
+- 友好的UI界面
+- 分类标签页组织
+- 字段说明和帮助信息
+
+### ✅ 安全性
+- 密码字段自动隐藏
+- API密钥部分隐藏显示
+- 配置验证功能
+
+### ✅ 便捷操作
+- 实时配置预览
+- 一键保存
+- 一键重置
+- 查看当前配置文件
+
+### ✅ 智能提示
+- 配置状态实时显示
+- 获取API密钥的详细步骤
+- 字段帮助信息
+
+## 配置文件位置
+
+配置保存在项目根目录的 `.env` 文件中:
+```
+D:\web\agentsstock1\.env
+```
+
+## 配置示例
+
+```bash
+# AI股票分析系统环境配置
+# 由系统自动生成和管理
+
+# ========== DeepSeek API配置 ==========
+DEEPSEEK_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
+DEEPSEEK_BASE_URL="https://api.deepseek.com/v1"
+
+# ========== Tushare数据接口(可选)==========
+TUSHARE_TOKEN=""
+
+# ========== MiniQMT量化交易配置(可选)==========
+MINIQMT_ENABLED="false"
+MINIQMT_ACCOUNT_ID=""
+MINIQMT_HOST="127.0.0.1"
+MINIQMT_PORT="58610"
+```
+
+## 注意事项
+
+1. **API密钥安全**
+ - 不要将 `.env` 文件提交到Git仓库
+ - 不要分享你的API密钥给他人
+ - 定期更换API密钥
+
+2. **配置生效**
+ - 修改配置后建议重启应用
+ - 某些配置可能需要重新加载才能生效
+
+3. **必填项**
+ - DeepSeek API密钥是必填项
+ - 其他配置项都是可选的
+
+4. **量化交易**
+ - 量化交易功能涉及真实资金
+ - 使用前请充分测试
+ - 谨慎配置交易参数
+
+## 故障排查
+
+### 问题1:保存配置失败
+
+**解决方案**:
+- 检查文件权限
+- 确保项目目录可写
+- 检查配置格式是否正确
+
+### 问题2:配置不生效
+
+**解决方案**:
+- 重启应用
+- 检查 `.env` 文件是否存在
+- 查看控制台错误信息
+
+### 问题3:API密钥验证失败
+
+**解决方案**:
+- 确认API密钥正确
+- 检查API密钥是否过期
+- 确认网络连接正常
+
+## 技术实现
+
+### 核心文件
+
+1. **config_manager.py**
+ - 配置管理器
+ - 读取/保存 `.env` 文件
+ - 配置验证
+
+2. **app.py**
+ - 配置界面
+ - 用户交互
+ - 状态管理
+
+3. **config.py**
+ - 加载环境变量
+ - 提供配置访问接口
+
+## 更新日期
+
+2025年10月6日
+
+## 作者
+
+AI股票分析系统开发团队
+
diff --git a/资金流向功能说明.md b/资金流向功能说明.md
index 1dcdeb9..91660bd 100644
--- a/资金流向功能说明.md
+++ b/资金流向功能说明.md
@@ -233,6 +233,7 @@ streamlit run app.py
#### 3. 提示 "未能获取问财资金流向数据"
**原因**:
+- 系统未安装node.js,需要node版本>16
- 问财API访问限制
- 股票代码不存在或停牌
- 数据暂时不可用