上证指数与平安银行被同一个代码混淆: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
2
_SH_INDICES = {"000001", "000016", "000300", "000905", "000852",
"000010", "000688", "000985"}

判断走指数分支的逻辑(akshare.py:127):

1
2
def _is_index(self, pure_code: str) -> bool:
return pure_code in self._SH_INDICES or pure_code.startswith("399")

symbol_formatter.py 同样维护了一份(symbol_formatter.py:306-307):

1
2
3
_SH_INDICES = {'000001', '000016', '000300', '000905', '000852', '000010', '000688'}
if market in ('SH', 'SS') and pure_code in _SH_INDICES:
# 识别为指数

第三步:确认根因

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 记录,当前代码尚未落地):

  1. 移除 _SH_INDICES 中的 000001:裸代码 000001 在沪深两市分别对应上证指数(sh000001)和平安银行(SZ000001),无法通过纯数字唯一标识。硬编码集合把指数/股票判断绑定在裸代码上,必然串号——应移除该集合里的 000001,指数识别改由显式市场前缀驱动。
  2. 区分指数与股票的符号格式: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,127backend/src/services/sources/symbol_formatter.py:306-307;仓库:内网 gitea normdist/ReShare,HEAD 8f63e52,akshare.py 最近重构 commit 6d2f145)。
  • 规格依据:ReShare 内部文档 SYMBOL_FORMAT_STANDARD.md(v2.1,2026-04-17)与 yfinance-sipoc-review.md(2026-04-15),均为本地项目文档。
  • 外部可验证来源(代码格式规则):

参考文献

  1. AKShare 指数数据文档(历史行情数据-新浪:stock_zh_index_daily,symbol 需带 sh/sz 前缀)
  2. 东方财富·上证指数行情页(secid=1.000001,沪市指数前缀 1)
  3. 东方财富·平安银行行情页(secid=0.000001,深市股票前缀 0)
  4. yfinance 股票代码后缀规范(.SS 上海 / .SZ 深圳)

上证指数与平安银行被同一个代码混淆:000001 符号映射 bug 的排查与修复
https://normdist.com/2026/09/11/ND-20260911-001-000001-symbol-collision-shanghai-index-vs-pingan-bank/
作者
小瑞
发布于
2026年9月11日
许可协议