一、升级概览
2025 年 10 月 28 日,TradingAgents-CN 完成了一次重要的 系统架构升级。
本次更新通过 25 个提交,围绕 多数据源隔离存储、实时 PE/PB 计算优化、K 线图实时数据支持、实时行情同步状态追踪 等核心能力展开,进一步提升了系统的 数据完整性、实时性和可靠性。
核心改进
- 多数据源隔离存储架构:解决 Tushare、AKShare、BaoStock 数据互相覆盖和索引冲突问题。
- 实时 PE/PB 计算优化:引入实时计算、数据库缓存、历史数据三层回退策略。
- K 线图实时数据支持:日线图可自动融合当天实时行情。
- 实时行情同步状态追踪:前端展示同步状态、最后同步时间和错误信息。
- 基本面快照增强:新增动态 PS、市销率、TTM 收入、净利润、净资产、ROE 等指标。
- 导出文件名统一:所有报告导出文件采用统一命名格式。
二、多数据源隔离存储架构
2.1 问题背景
相关提交:
279937659:实现 多数据源隔离存储设计。253d60346:修复多数据源同步的 MongoDB 连接和索引冲突问题。08bbee6eb:修复多数据源同步的数据一致性问题。86e67b49a:行业列表接口支持数据源优先级。
系统支持 Tushare、AKShare、BaoStock 三个数据源,但此前存在严重的数据覆盖和索引冲突问题。
主要问题
1. 数据互相覆盖
此前 stock_basic_info 使用 code 作为唯一索引。
同一只股票如果分别从 Tushare、AKShare、BaoStock 同步,后同步的数据会覆盖先同步的数据。
这会导致:
- 不同数据源无法独立保存。
- 数据源之间互相污染。
- 无法比较不同数据源的数据差异。
2. 数据源优先级不统一
不同模块可能使用不同数据源,导致查询结果不一致。
例如:
- 股票详情页使用 Tushare。
- 筛选页使用 AKShare。
- 行业列表使用 BaoStock。
用户看到的数据就会出现混乱。
3. MongoDB 索引冲突
多数据源同步时,容易出现类似错误:
E11000 duplicate key error collection: tradingagents.stock_basic_info
index: code_1 dup key: { code: "000001" }
根本原因是 code 唯一索引无法支持同一股票在多个数据源中分别存储。
2.2 解决方案
核心思路是:在同一个集合中,通过 (code, source) 联合唯一索引 实现数据源隔离。
db.stock_basic_info.createIndex(
{ "code": 1, "source": 1 },
{ unique: true }
)
db.stock_basic_info.createIndex({ "code": 1 })
db.stock_basic_info.createIndex({ "source": 1 })
新的数据结构如下:
{
"code": "000001",
"source": "tushare",
"name": "平安银行",
"industry": "银行",
"list_date": "19910403"
}
这样,同一只股票可以同时存在多条记录:
000001 + tushare000001 + akshare000001 + baostock
彼此不会覆盖。
2.3 索引迁移
新增迁移脚本:
scripts/migrations/migrate_stock_basic_info_add_source_index.py
迁移逻辑包括:
- 删除旧的
code_1唯一索引。 - 创建新的
(code, source)联合唯一索引。 - 创建
code和source辅助索引。 - 保证旧数据可以平滑迁移。
2.4 数据源优先级查询
系统在未指定数据源时,按优先级自动查询。
默认优先级为:
source_priority = ["tushare", "multi_source", "akshare", "baostock"]
示例逻辑:
if source:
query = {"code": symbol6, "source": source}
doc = await db["stock_basic_info"].find_one(query, {"_id": 0})
else:
source_priority = ["tushare", "multi_source", "akshare", "baostock"]
doc = None
for src in source_priority:
query = {"code": symbol6, "source": src}
doc = await db["stock_basic_info"].find_one(query, {"_id": 0})
if doc:
break
2.5 多数据源同步修复
同步时使用 (code, source) 作为更新条件。
UpdateOne(
{"code": stock["code"], "source": source},
{"$set": stock},
upsert=True
)
2.6 优化效果
- 同一股票可以保留多个数据源版本。
- 彻底解决 MongoDB 唯一索引冲突。
- 支持指定数据源查询,也支持按优先级自动查询。
- 避免不同数据源互相覆盖。
- 为后续数据源对比和质量评估打下基础。
三、实时 PE/PB 计算优化
3.1 问题背景
相关提交:
f42fc1f61:修复 实时市值和 PE/PB 计算逻辑。18727ef3c:完善实时 PE/PB 计算的回退策略。2460f47dc:添加实时 PE/PB 计算与回退策略博文。
此前实时估值指标存在几个问题:
- 实时股价可能为空。
- 财务数据可能未同步。
- 总股本数据可能缺失。
- 单位转换容易出错。
- 计算失败后直接返回空值,用户看不到任何数据。
3.2 三层回退策略
新的实时 PE/PB 计算采用 三层回退策略:
- 优先使用实时股价计算。
- 如果失败,使用数据库缓存值。
- 如果仍失败,使用历史数据兜底。
result = {
"pe": None,
"pb": None,
"total_mv": None,
"data_source": None
}
当实时计算成功时:
result.update({
"pe": pe,
"pb": pb,
"total_mv": total_mv,
"data_source": "realtime_calculated"
})
如果实时计算失败,则依次尝试:
database_cachedhistorical_data
3.3 实时市值计算修复
实时市值计算逻辑:
total_mv = (total_share * current_price) / 10000
其中:
total_share单位为 万股。current_price单位为 元。total_mv最终单位为 亿元。
PE 计算:
net_profit_billion = net_profit / 100000000
pe = total_mv / net_profit_billion
PB 计算:
net_assets_billion = net_assets / 100000000
pb = total_mv / net_assets_billion
3.4 优化效果
- 实时市值计算更准确。
- PE/PB 单位转换更清晰。
- 计算失败时不会直接空白,而是自动回退。
- 每个结果都有明确的数据来源标识。
- 用户在前端看到的估值指标更稳定。
四、K 线图实时数据支持
4.1 功能背景
相关提交:
389e7ddea:K 线图支持当天实时数据,并修复同步时间时区显示。
此前 K 线图主要依赖历史数据。如果当天历史数据尚未同步,用户在交易时间内无法看到最新 K 线。
这会导致:
- 盘中 K 线不更新。
- 收盘后当天数据可能缺失。
- 用户需要等待历史同步完成。
4.2 实现方案
日线图在返回历史 K 线时,会额外检查 market_quotes 中是否有当天实时行情。
核心逻辑:
if period == "day" and items:
today_str = now.strftime("%Y%m%d")
has_today_data = any(
item.get("time") == today_str
for item in items
)
is_trading_time = (
dtime(9, 30) <= current_time <= dtime(15, 0)
and now.weekday() < 5
)
should_fetch_realtime = is_trading_time or not has_today_data
如果需要实时数据,则从 market_quotes 构造当天 K 线:
today_kline = {
"time": today_str,
"open": float(realtime_quote.get("open", 0)),
"high": float(realtime_quote.get("high", 0)),
"low": float(realtime_quote.get("low", 0)),
"close": float(realtime_quote.get("close", 0)),
"volume": float(realtime_quote.get("volume", 0)),
"amount": float(realtime_quote.get("amount", 0))
}
如果历史数据中已经有当天记录,则替换;如果没有,则追加并重新排序。
4.3 优化效果
- 交易时间内可以显示实时日 K 数据。
- 收盘后可自动补充当天数据。
- 无需等待历史数据同步完成。
- K 线图体验更接近实时行情软件。
五、实时行情同步状态追踪
5.1 功能背景
相关提交:
7fa9fd1af:实时行情同步状态追踪和收盘后缓冲期。375a4eaca:前端个股详情页显示实时行情同步状态。a7a0f5cba:修复实时行情同步状态 API 路由冲突。
用户需要知道行情数据是否已经同步、什么时候同步、同步是否失败。
因此系统新增 实时行情同步状态追踪。
5.2 后端状态追踪
后端维护以下状态:
self.last_sync_time = None
self.sync_status = "idle" # idle, syncing, success, error
self.sync_error = None
同步成功后记录:
self.last_sync_time = datetime.now(ZoneInfo("Asia/Shanghai"))
self.sync_status = "success"
同步失败则记录:
self.sync_status = "error"
self.sync_error = str(e)
5.3 收盘后 30 分钟缓冲期
同步时间范围为:
- 交易时间:9:30 - 15:00
- 收盘缓冲期:15:00 - 15:30
- 周末不自动同步
return dtime(9, 30) <= current_time <= dtime(15, 30)
这样可以覆盖收盘后行情数据延迟更新的情况。
5.4 前端状态显示
个股详情页新增同步状态标签,展示:
- 同步中
- 已同步
- 同步失败
- 空闲
- 最后同步时间
并且每 30 秒自动刷新一次状态。
5.5 优化效果
- 用户可以看到实时行情同步状态。
- 可以看到最后同步时间。
- 同步失败时更容易定位问题。
- 收盘后 30 分钟缓冲期提升数据完整性。
- 前端状态自动刷新,体验更清晰。
六、其他功能优化
6.1 为 stock_basic_info 添加 symbol 字段
相关提交:
7bcc6d08e:为stock_basic_info集合添加symbol字段。c0a3aadc2:修复迁移脚本并验证601899股票信息。
新增字段示例:
{
"code": "000001",
"symbol": "sz000001",
"source": "tushare"
}
其中:
code是 6 位股票代码。symbol是带市场前缀的完整代码。
这有助于适配不同数据源的代码格式。
6.2 基本面快照接口增强
相关提交:
41f5d7fdd:增强基本面快照接口,添加市销率和财务指标。c68539e63:基本面快照接口使用动态计算 PS。
新增能力包括:
- 动态计算 PS 市销率。
- 新增 营业收入 TTM。
- 新增 净利润 TTM。
- 新增 净资产。
- 新增 ROE 净资产收益率。
动态 PS 计算逻辑:
ps = total_mv / revenue_ttm if revenue_ttm else None
6.3 统一导出报告文件名格式
相关提交:
65c88a29f:统一所有页面的导出报告文件名格式。
统一格式:
TradingAgents_报告类型_股票代码_日期时间.pdf
示例:
TradingAgents_分析报告_000001_20251028_143052.pdf
TradingAgents_批量分析_20251028_143052.pdf
6.4 股票名称获取增强
相关提交:
b7838214:增强股票名称获取的错误处理和降级逻辑。
股票名称获取采用多层降级:
- 从
stock_basic_info获取。 - 从
market_quotes获取。 - 如果都失败,则使用股票代码作为后备。
七、统计数据
7.1 提交统计
| 指标 | 数量 |
|---|---|
| 总提交数 | 25 |
| 修改文件数 | 60+ |
| 新增代码 | 3500+ 行 |
| 删除代码 | 500+ 行 |
| 净增代码 | 3000+ 行 |
7.2 功能分类
| 分类 | 数量 |
|---|---|
| 多数据源架构 | 6 项改进 |
| 实时数据 | 8 项增强 |
| PE/PB 计算 | 3 项优化 |
| K 线图 | 1 项新功能 |
| 其他优化 | 7 项改进 |
八、技术亮点
8.1 多数据源隔离存储设计
核心设计:
db.stock_basic_info.createIndex(
{ "code": 1, "source": 1 },
{ unique: true }
)
优势:
- 同一股票可保留多个数据源版本。
- 数据不会互相覆盖。
- 查询时可指定数据源,也可按优先级自动选择。
8.2 实时 PE/PB 三层回退策略
回退顺序:
- 实时股价计算,最准确。
- 数据库缓存值,作为次优选择。
- 历史数据,作为保底方案。
8.3 K 线图实时数据融合
策略:
- 交易时间内:从
market_quotes获取实时数据。 - 收盘后:如果历史数据未同步,则补充当天数据。
- 非交易日:只展示历史数据。
8.4 同步状态追踪
能力:
- 记录同步状态。
- 记录最后同步时间。
- 支持错误信息展示。
- 前端自动刷新。
- 支持收盘后 30 分钟缓冲期。
九、总结
本次更新通过 25 个提交,完成了 多数据源架构 与 实时数据能力 的重要升级。
主要成果包括:
- 多数据源隔离存储:通过
(code, source)联合唯一索引,解决数据覆盖和索引冲突。 - 数据源优先级查询:未指定数据源时,按 Tushare、multi_source、AKShare、BaoStock 的顺序自动查询。
- 实时 PE/PB 优化:引入实时计算、缓存值、历史数据三层回退策略。
- K 线图实时数据支持:日线图自动融合当天
market_quotes实时行情。 - 实时行情同步状态追踪:前端展示同步状态、最后同步时间和错误信息。
- 基本面快照增强:新增 PS、营业收入 TTM、净利润 TTM、净资产、ROE 等指标。
- 导出文件名统一:所有报告导出命名更加规范。
- 股票名称获取增强:通过多层降级提高显示稳定性。
这些改进显著提升了 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 刀测试是否契合自身需求,满意了再小额充值上车,理性消费不盲目。
文章评论