一、升级概览
2025 年 11 月 11 日,TradingAgents-CN 完成了一次重要的 美股数据源架构升级 和 缓存系统优化。
本次升级通过 22 个提交,实现了 美股多数据源支持、集成缓存策略、数据库导入导出功能完善、配置管理优化 和多项 Bug 修复,显著提升了系统的 灵活性、性能和数据管理能力。
核心改进
- 美股数据源架构升级:支持 yfinance、Alpha Vantage、Finnhub 多数据源,并从数据库读取配置和优先级。
- 集成缓存策略:默认启用 Redis/MongoDB/File 三层缓存,大幅提升数据访问速度。
- 数据库导入导出优化:修复集合名称错误、日期格式转换、参数传递等问题。
- 配置管理优化:统一从数据库读取 API Key 和 数据源优先级。
- Bug 修复:修复缓存查找逻辑、数据源映射、导入格式识别等问题。
二、美股数据源架构升级
2.1 多数据源支持
相关提交:
ec79cf1:为美股添加 yfinance 和 Alpha Vantage 数据源支持。33e554d:实现 美股数据源管理器 和配置机制。cb2d991:统一美股数据源管理到data_source_manager.py。
本次升级后,系统支持三类美股数据源:
| 数据源 | 特点 | 适用场景 |
|---|---|---|
| yfinance | 免费,无需 API Key | 适合获取历史行情数据 |
| Alpha Vantage | 需要 API Key | 支持基本面数据和新闻 |
| Finnhub | 需要 API Key | 支持实时行情和新闻 |
2.2 数据源管理器
系统新增 USDataSourceManager 美股数据源管理器,用于统一管理美股数据源。
# tradingagents/dataflows/providers/us/data_source_manager.py
class USDataSourceManager:
"""美股数据源管理器"""
def get_priority_order(self) -> List[DataSourceCode]:
"""从数据库读取数据源优先级"""
# 查询 datasource_groupings 集合
# 按 priority 字段排序
# 返回优先级列表
该管理器主要负责:
- 从数据库读取 数据源配置。
- 管理 数据源优先级。
- 获取对应的数据源实例。
- 在数据源不可用时执行 自动降级。
2.3 从数据库读取配置
相关提交:
578dd5f:Alpha Vantage 从数据库读取 API Key。6355d2a:修复从数据库配置读取数据源 API Key。58c7aae:A 股数据源也从数据库配置读取 API Key,并补充架构重构文档。
升级前存在几个问题:
- API Key 硬编码在环境变量中,不便于统一管理。
- 数据源优先级 硬编码在代码中,无法动态调整。
- 配置分散在多个地方,维护成本较高。
升级后,系统统一从 system_configs 集合读取 API Key。
# 从 system_configs 集合读取 API Key
config = await db.system_configs.find_one({
"config_key": "alpha_vantage_api_key",
"is_active": True
})
api_key = config["config_value"]
同时,数据源优先级从 datasource_groupings 集合读取。
# 从 datasource_groupings 集合读取优先级
groupings = await db.datasource_groupings.find({
"market_category": "us_stock",
"is_active": True
}).sort("priority", -1).to_list(None)
2.4 自动创建市场分类关系
相关提交:
85aefd9:添加数据源配置时自动创建市场分类关系。
新增数据源时,系统会自动创建该数据源与市场分类之间的关联,并分配默认优先级,减少手动配置工作。
2.5 修复的数据源问题
相关提交:
7e12986:修复美股数据源优先级问题,从数据库读取配置。246303b:修复数据源配置读取中的集合名错误和激活状态检查。8cc4510:修复美股数据源优先级映射,使用字符串键替代枚举键。
| 问题 | 表现 | 解决方案 |
|---|---|---|
| 集合名错误 | system_config 写成错误集合名 | 修正为 system_configs |
| 缺少激活状态检查 | 读取了未激活配置 | 添加 is_active: True 过滤 |
| 枚举键映射错误 | 字典键使用枚举对象而非字符串 | 改用字符串键,如 "alpha_vantage" |
| 硬编码 Finnhub | 始终使用 Finnhub 数据源 | 改为从数据库读取优先级 |
三、集成缓存策略优化
3.1 默认启用集成缓存
相关提交:
048fcb7:默认启用 集成缓存策略。3c9f360:添加IntegratedCacheManager缺失方法。359cb49:修复缓存查找逻辑,按数据库配置的优先级查找缓存。
系统现在默认启用 Redis/MongoDB/File 三层缓存架构。
Redis(内存缓存)
↓ 未命中
MongoDB(持久化缓存)
↓ 未命中
File(降级缓存)
三层缓存各自定位如下:
- Redis 缓存:速度最快,微秒级访问,支持 TTL 自动过期。
- MongoDB 缓存:速度较快,毫秒级访问,数据可持久化。
- File 缓存:作为降级缓存,不依赖外部服务,保证系统可用性。
当 Redis 不可用时,系统会自动使用 MongoDB;当 MongoDB 不可用时,则降级到 File 缓存,确保数据访问链路保持可用。
3.2 修复缓存查找逻辑
用户反馈第二次分析时缓存未命中,系统重新调用 API。
日志示例:
2025-11-11 19:19:50,349 | agents | ERROR | 未找到有效的美股历史数据缓存: TSLA
2025-11-11 19:19:50,357 | agents | INFO | [数据来源: API调用-ALPHA_VANTAGE] 尝试从 ALPHA_VANTAGE 获取数据: TSLA
原因是缓存查找逻辑只查找 finnhub 和 yfinance,但数据实际是用 alpha_vantage 保存的,导致缓存无法命中。
修复后,系统会 按数据库配置的数据源优先级查找缓存。
# tradingagents/dataflows/providers/us/optimized.py
def get_stock_data(self, symbol: str, start_date: str, end_date: str):
"""获取美股数据,按数据库配置的优先级查找缓存"""
# 1. 从数据库读取数据源优先级
priority_order = self.data_source_manager.get_priority_order()
# 2. 按优先级顺序查找缓存
for source in priority_order:
cache_key = self.cache.find_cached_stock_data(
symbol=symbol,
start_date=start_date,
end_date=end_date,
data_source=source.value
)
if cache_key:
cached_data = self.cache.load_stock_data(cache_key)
if cached_data:
logger.info(f"从缓存加载美股数据: {symbol}")
return cached_data
# 3. 缓存未命中,按优先级调用 API
for source in priority_order:
try:
data = self._fetch_from_source(source, symbol, start_date, end_date)
if data:
self.cache.save_stock_data(data, source=source.value)
return data
except Exception as e:
logger.warning(f"{source.value} 获取失败: {e}")
continue
修复效果:
- 第一次分析:从 API 获取数据,并保存到缓存。
- 第二次分析:直接从缓存加载数据,无需再次调用 API。
- 缓存命中率提升,响应速度明显加快。
3.3 添加缺失的缓存方法
相关提交:
3c9f360:添加IntegratedCacheManager缺失的方法。
此前系统报错:
AttributeError: 'IntegratedCacheManager' object has no attribute 'find_cached_fundamentals_data'
本次补充了基本面数据缓存查找和有效性检查方法。
class IntegratedCacheManager:
"""集成缓存管理器"""
def find_cached_fundamentals_data(self, symbol: str, data_source: str = None):
"""查找缓存的基本面数据"""
if self.redis_cache:
cache_key = self.redis_cache.find_cached_fundamentals_data(symbol, data_source)
if cache_key:
return cache_key
if self.mongodb_cache:
cache_key = self.mongodb_cache.find_cached_fundamentals_data(symbol, data_source)
if cache_key:
return cache_key
return self.file_cache.find_cached_fundamentals_data(symbol, data_source)
def is_fundamentals_cache_valid(self, cache_key: str, max_age_days: int = 7):
"""检查基本面数据缓存是否有效"""
# 基本面数据更新频率较低,默认 7 天有效期
四、数据库导入导出功能完善
4.1 修复集合名称错误
修复文件:
frontend/src/views/System/DatabaseManagement.vue
用户反馈导出的分析报告为空:
{
"export_info": {
"created_at": "2025-11-11T11:56:07.776033",
"collections": ["system_configs", "users", "analysis_results"]
},
"data": {
"analysis_results": [],
"analysis_tasks": []
}
}
原因是数据库中的实际集合名为 analysis_reports,但前端硬编码了错误的 analysis_results,导致导出的报告数据为空。
修复后:
// frontend/src/views/System/DatabaseManagement.vue
const reportCollections = [
'analysis_reports',
'analysis_tasks'
]
修复效果:
- 正确导出 analysis_reports 集合。
- 分析报告与分析任务可以完整迁移。
- 移除了数据库中不存在的
debate_records集合。
4.2 修复日期字段格式转换
相关提交:
582a697:导入数据时自动转换日期字段格式。
用户导入数据后,报告列表 API 报错:
获取报告列表失败: 'str' object has no attribute 'tzinfo'
原因是导出数据中的日期字段是字符串格式,但代码期望的是 datetime 对象。to_config_tz() 函数访问字符串的 tzinfo 属性时触发异常。
修复方案是在导入时自动将常见日期字段从字符串转换为 datetime。
# app/services/database/backups.py
def _convert_date_fields(doc: dict) -> dict:
"""
转换文档中的日期字段:字符串 → datetime
"""
from dateutil import parser
date_fields = [
"created_at", "updated_at", "completed_at",
"started_at", "finished_at", "deleted_at",
"last_login", "last_modified", "timestamp"
]
for field in date_fields:
if field in doc and isinstance(doc[field], str):
try:
doc[field] = parser.parse(doc[field])
except Exception as e:
logger.warning(f"无法解析日期字段 {field}: {doc[field]}, 错误: {e}")
return doc
修复效果:
- 导入后日期字段自动转换为
datetime对象。 - 报告列表 API 不再报错。
- 导入数据格式与直接写入数据库的数据格式保持一致。
4.3 修复导入参数传递
相关提交:
8d2c6f0:修复数据库导入功能中的参数传递方式。
用户在数据库管理页面导入 6.6MB 文件后,数据库几乎没有变化,后端日志显示只插入 1 条文档。
原因是导出文件包含 export_info 和 data 两层结构,但导入检测逻辑没有识别新版格式,导致系统将整个文件当作单集合的一条文档插入。
修复后,系统可以正确识别新版多集合导出格式。
# app/services/database/backups.py
async def import_data(...):
"""导入数据到数据库"""
# 新格式:包含 export_info 和 data 的字典
if isinstance(data, dict) and "export_info" in data and "data" in data:
logger.info("检测到新版多集合导出文件")
export_info = data.get("export_info", {})
# 提取实际数据
data = data["data"]
logger.info(f"包含 {len(data)} 个集合: {list(data.keys())}")
# 旧格式:直接是集合名到文档列表的映射
if isinstance(data, dict) and all(
isinstance(k, str) and isinstance(v, list)
for k, v in data.items()
):
logger.info(f"确认为多集合导入模式,包含 {len(data)} 个集合")
修复效果:
- 正确识别新版导出格式。
- 完整导入所有集合数据。
- 导入成功后,数据库统计可以正确更新。
五、数据统计
5.1 提交统计
| 类型 | 数量 | 占比 |
|---|---|---|
| 功能新增,feat | 8 | 36% |
| Bug 修复,fix | 12 | 55% |
| 重构,refactor | 2 | 9% |
| 总计 | 22 | 100% |
5.2 文件修改统计
| 类别 | 文件数 | 主要文件 |
|---|---|---|
| 数据源管理 | 8 | data_source_manager.py、optimized.py、alpha_vantage_*.py |
| 缓存系统 | 4 | integrated.py、adaptive.py、mongodb_cache_adapter.py |
| 数据库管理 | 3 | backups.py、database.py、DatabaseManagement.vue |
| 配置管理 | 2 | database_manager.py、config_manager.py |
| 文档和脚本 | 5 | 架构文档、测试脚本、诊断工具 |
六、用户体验改进
6.1 数据获取速度提升
升级前:
第一次分析 TSLA:
- 从 Alpha Vantage API 获取数据:约 2 秒
第二次分析 TSLA:
- 缓存未命中
- 重新从 API 获取数据:约 2 秒
升级后:
第一次分析 TSLA:
- 从 Alpha Vantage API 获取数据:约 2 秒
- 保存到 Redis 缓存
第二次分析 TSLA:
- 从 Redis 缓存加载:约 10ms
- 速度提升约 200 倍
6.2 数据源灵活性提升
升级前:
- 硬编码使用 Finnhub 数据源。
- API Key 依赖环境变量。
- 无法动态调整数据源优先级。
升级后:
- 支持 yfinance、Alpha Vantage、Finnhub 三个数据源。
- API Key 可在数据库中配置,支持在线修改。
- 数据源优先级可在系统设置中调整。
- 数据源不可用时,自动降级到下一个可用数据源。
6.3 数据迁移便利性提升
升级前:
- 导出的集合名称错误,分析报告为空。
- 导入后日期格式错误,API 报错。
- 导入格式识别失败,可能造成数据丢失。
升级后:
- 导出正确集合,包含完整分析报告。
- 导入时自动转换日期格式。
- 正确识别导出格式,完整导入所有数据。
七、技术亮点
7.1 数据源管理器设计
class USDataSourceManager:
"""美股数据源管理器
职责:
1. 从数据库读取数据源配置
2. 管理数据源优先级
3. 提供数据源实例
4. 处理数据源降级
"""
def get_priority_order(self) -> List[DataSourceCode]:
"""获取数据源优先级顺序,从数据库读取"""
def get_data_source(self, source_code: DataSourceCode):
"""获取数据源实例,并自动从数据库读取 API Key"""
7.2 集成缓存策略
class IntegratedCacheManager:
"""集成缓存管理器
三层缓存架构:
1. Redis:内存缓存,速度最快
2. MongoDB:持久化缓存,数据不丢失
3. File:降级缓存,不依赖外部服务
"""
def save_stock_data(self, data, source: str):
"""保存数据到缓存,按优先级降级"""
if self.redis_cache:
self.redis_cache.save_stock_data(data, source)
return
if self.mongodb_cache:
self.mongodb_cache.save_stock_data(data, source)
return
self.file_cache.save_stock_data(data, source)
7.3 日期字段自动转换
def _convert_date_fields(doc: dict) -> dict:
"""转换文档中的日期字段:字符串 → datetime
优点:
1. 自动识别常见日期字段
2. 使用 dateutil.parser 智能解析
3. 异常处理,不影响其他字段
4. 在导入时转换,一次性解决问题
"""
这一设计让数据迁移更加稳定,也避免导入后由于字段类型不一致导致接口异常。
八、本次升级的价值
本次升级围绕 美股数据源、缓存系统、配置管理和数据库迁移 四个方向展开,解决了多个影响实际使用体验的问题。
核心价值包括:
- 更灵活:美股数据源不再硬编码,可通过数据库动态配置。
- 更快速:Redis/MongoDB/File 三层缓存显著提高二次访问速度。
- 更稳定:缓存、导入导出和日期字段处理更加健壮。
- 更易维护:API Key、数据源优先级和市场分类关系统一管理。
- 更便于迁移:数据库备份与恢复流程更加可靠。
九、致谢
感谢所有参与本次升级的开发者和测试用户。特别感谢用户反馈的缓存未命中、导入导出异常和数据源配置问题,这些反馈帮助 TradingAgents-CN 持续改进系统架构和使用体验。
✅ 官方唯一渠道:📦 GitHub 仓库:https://github.com/hsliuping/TradingAgents-CN
Aekor AI-API 中转站,让全球顶尖 AI 大模型“触手可及”!你是否曾为这些烦恼头疼?
🔹 人在国内,却总被海外官网 API 的高延迟、掉线、甚至无法访问困扰?
🔹 想用最强的 GPT、Claude 等模型,却卡在海外信用卡、支付审核等重重阻碍?
🔹 官方 API 太贵?Aekor 为你打通“网络-支付-成本”的任督二脉!
💡 Aekor 核心价值:好用、便宜、快 💡
🚀 高速稳定,告别掉线国内专线加速,API 响应低延迟,告别「转圈圈」的焦虑,开发效率瞬间拉满!
🧠 顶尖模型,随需而调涵盖 GPT 系列、Claude 系列等全球主流大厂模型,一次接入,轻松调用!
🎁 免费白嫖,诚意拉满!
注册即送 20 美元体验额度,够你狠狠测试一轮模型质量与线路稳定性了!
⚠️ 温馨提示:API 中转市场虽多但良莠不齐(甚至有些会偷工减料换小模型糊弄事儿)。Aekor 坚持提供正版稳定的服务,但还是建议:先用免费的 20 刀测试是否契合自身需求,满意了再小额充值上车,理性消费不盲目。
文章评论