上证指数与平安银行被同一个代码混淆:000001 符号映射 bug 的排查与修复
本文最后更新于 2026年9月11日 凌晨
上证指数与平安银行被同一个代码混淆:000001 符号映射 bug 的排查与修复
凌晨巡检大周期数据通道,四个标的三个秒回,只有一个卡了 30 秒超时。查完数据才发现:不是网络慢,是 000001 这个代码被同时当成了上证指数和平安银行——同一个 key,两个完全不同的标的。
前置条件
- AutoQuant (AQ) + ReShare 本地数据服务(v0.25.4,端口 8200)
- 数据链路:AQ → ReShare → akshare / yfinance
- 大周期查询范围:2021-2026
现象
2026-09-10 巡检时对 ReShare 做大周期查询测试,同一批标的只有 000001.SH 异常:
| 标的 | HTTP | 耗时 | 记录数 | 状态 |
|---|---|---|---|---|
| 000858.SZ | 200 | 0.05s | 1379 | ✅ |
| 600036.SH | 200 | 3.2s | 3200+ | ✅ |
| 510300.SH | 200 | 0.05s | 893 | ✅ |
| 000001.SH | 000 | 30s | - | ❌ 超时 |
更严重的是数据本身错了:000001.SH 存的是上证指数(3951 点),不是平安银行(11.7 元)。查询历史数据时触发了指数接口,指数接口超时,用户拿到的是指数点位冒充的股价。
排查过程
第一步:确认不是网络问题
其余三个标的毫秒级返回,只有 000001 超时——先排除链路问题,直接怀疑符号处理分支。
第二步:定位到 _SH_INDICES 硬编码
ReShare 的 akshare 数据源里维护了一个”已知上证指数代码”集合(backend/src/services/sources_new/klines/akshare.py:75):
1 | |
判断走指数分支的逻辑(akshare.py:127):
1 | |
symbol_formatter.py 同样维护了一份(symbol_formatter.py:306-307):
1 | |
第三步:确认根因
000001 是代码冲突的重灾区:
| 语义 | 新浪格式 | 东方财富 secid | ReShare 标准 |
|---|---|---|---|
| 上证指数 | sh000001 | 1.000001(沪=1) | SH000001 |
| 平安银行 | sz000001 | 0.000001(深=0) | SZ000001 |
000001 裸数字无法区分:上证指数在上交所(sh 前缀),平安银行在深交所(sz 前缀)。系统里 _SH_INDICES 把裸代码 000001 判为”上证指数”,于是对 000001.SH 的请求走了 stock_zh_index_daily 指数接口——返回 3951 点的指数数据,且该接口在代理环境下超时。
本质:用裸数字代码当唯一标识,遇到跨市场同号(000001、000300 这类指数/股票撞号)就串数据。指数和股票共用代码段是 A 股常态,区分只能靠市场前缀(sh/sz、1./0.、.SH/.SZ)。
修复建议
devlog 中给出的修复方向(2026-09-10 记录,当前代码尚未落地):
- 移除
_SH_INDICES中的000001:裸代码000001在沪深两市分别对应上证指数(sh000001)和平安银行(SZ000001),无法通过纯数字唯一标识。硬编码集合把指数/股票判断绑定在裸代码上,必然串号——应移除该集合里的000001,指数识别改由显式市场前缀驱动。 - 区分指数与股票的符号格式:ReShare 已有
SYMBOL_FORMAT_STANDARD(v2.1,2026-04-17 实施),规定存储统一为SH600000/SZ000001标准格式,各数据源请求时再按源格式转换(yfinance 要000001.SZ,akshare 要裸代码,新浪要sh000001/sz000001)。指数必须显式带前缀,裸代码一律按股票处理。
验证方式:修复后重跑 000001.SH 大周期查询,应返回平安银行股价(≈11.7 元)且秒级响应,不再触发指数接口。
踩坑记录
坑一:裸代码当唯一标识
现象:000001 同时命中”上证指数”和”平安银行”,数据串号。
根因:A 股指数与股票共用代码段(000001/000300/000905 等),裸数字无法区分市场。
解法:统一 SH000001/SZ000001 标准格式存储,显式带市场前缀。
坑二:指数判断靠硬编码集合
现象:_SH_INDICES 硬编码把 000001 判为指数,触发错误分支。
根因:指数集合是手工维护的,且与股票代码天然撞号。
解法:指数查询必须显式声明(如 sh000001),不能靠裸代码推断。
坑三:yfinance 小写前缀曾踩过同类坑
现象:sz000001(小写)请求失败。
根因:格式归一化不完整,小写前缀未转大写。
解法:已在 yfinance_source 修复,sz000001 → 000001.SZ ✅(记录于 yfinance SIPOC 审查,2026-04-15)。
验证
修复前 000001.SH 返回上证指数 3951 点、HTTP 000 超时;修复后应返回平安银行行情(股价两位数的日 K 序列),与 000858.SZ/600036.SH 同量级的秒级响应。修复落地后需重跑全量巡检表确认。
教训
证券代码永远不要只存裸数字。 000001 可以是上证指数,也可以是平安银行,甚至更多。凡是涉及 A 股代码的管道,必须带市场前缀(SH/SZ/BJ)——存标准格式、按源转换、显示统一。这不是一次性的 bug,是数据管道的架构约束。
同类事故回顾:回测缓存曾因”日期做 key”串号(ND-20260727-001),这次是”代码做 key”串号。标识符设计不严谨,迟早会以各种形式复发。
数据来源说明
- 巡检数据(现象表格、3951 点、11.7 元、0.05s/30s 耗时)取自 2026-09-10 凌晨 AQ 巡检记录
autoquant/.devlog/2026-09-10.md(第 28-30 行巡检表格、第 49-53 行问题 1、第 75/80 行修复建议;仓库:gitee.com/normdist/autoquant),测量方式为对 ReShare 大周期接口(2021-2026)的 HTTP 请求,行情数值为当时快照。修复建议为该记录中给出的原文方向。 - 代码片段与行号引用自 ReShare 代码库(
backend/src/services/sources_new/klines/akshare.py:75,127、backend/src/services/sources/symbol_formatter.py:306-307;仓库:内网 gitea normdist/ReShare,HEAD8f63e52,akshare.py 最近重构 commit6d2f145)。 - 规格依据:ReShare 内部文档
SYMBOL_FORMAT_STANDARD.md(v2.1,2026-04-17)与yfinance-sipoc-review.md(2026-04-15),均为本地项目文档。 - 外部可验证来源(代码格式规则):
参考文献