东方财富北向资金双接口同时坏死——一个降级+迁移方案

本文最后更新于 2026年7月1日 中午

某套量化系统的北向资金模块在例行巡检中遭遇了一次”教科书级”的接口故障:东方财富的两个北向资金 API 同时坏死——一个返回空结果,一个返回全 NaN。如果系统只依赖其中一个接口,故障会在当天收盘后才会暴露;但因为两个接口在同一时段同时挂了,数据断档直接触发了告警。

本文记录从发现故障、定位根因到设计降级方案的完整过程,重点讨论:如何在多源数据管道中优雅地处理”主备同时失效”的场景

一、问题:两个接口,同时坏死

北向资金是 A 股量化策略的重要因子。该系统的北向数据采集依赖东方财富的两个接口:

  • stock_hsgt_individual_em —— 个股资金流向(实时/近7天)
  • stock_hsgt_hist_em —— 历史净流入数据(日线级别,可回溯多年)

这两个接口在设计上互为补充:一个负责”新鲜数据”,一个负责”历史深度”。正常情况下,它们各自独立运行,互不影响。

但某日 15:05 开始巡检时,两个接口同时出了问题:

1
2
3
4
5
6
7
8
# 接口1:stock_hsgt_individual_em —— 完全炸掉
返回空 DataFrame(0行)

# 接口2:stock_hsgt_hist_em —— 数据全 NaN
date north_flow south_flow
0 None None None
1 None None None
... # 所有字段均为 NaN

两个接口在同一时段同时坏死。这意味着:当天北向资金数据完全断档

更令人不安的是,这两个接口的故障模式不同——一个返回空,一个返回 NaN——说明它们走的是不同的底层请求路径。如果只监控”是否有数据”而不检查”数据质量”,可能两个接口都通过健康检查,但实际数据都是无效的。

二、诊断:为什么两个接口会同时挂?

逐一排查后,发现根因并非东方财富整体故障,而是两个接口的 WBI 签名参数 在同一时段过期:

  • stock_hsgt_individual_em 的 WBI 签名依赖一个动态生成的 token,该 token 有有效期。token 过期后,接口返回空结果而非报错。
  • stock_hsgt_hist_em 使用另一个签名参数,其生成逻辑依赖于页面加载时的某个 JavaScript 变量。该变量在特定条件下(如 Cookie 变更、UA 不匹配)会重新生成,但旧签名仍然被缓存使用。

两个接口的签名过期时间恰好重合,导致”双接口同时坏死”。如果只监控其中一个,另一个可能暂时正常,故障会在切换数据源时暴露。

关键教训:多源数据管道的健康检查不能只看”是否返回结果”,还要检查”结果是否有效”。空 DataFrame 和全 NaN DataFrame 都是”有结果”,但都不是”好结果”。

三、方案:三级降级策略

基于上述诊断,设计了三级降级策略,从最优到最差依次尝试:

第一级:修复主接口签名

重新生成 WBI 签名参数,恢复两个接口的正常调用。这是最快的修复方式,但需要处理签名的自动刷新逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 修复后验证
import akshare as ak

# 接口1:个股资金流向(近7天)
df1 = ak.stock_hsgt_individual_em(symbol="北向资金")
assert len(df1) > 0, "接口1返回空"

# 接口2:历史数据
df2 = ak.stock_hsgt_hist_em(symbol="北上资金")
assert df2.isna().sum().sum() len(df) * len(df.columns) * 0.5:
return False
return True

def _normalize(self, df):
"""统一列名为 north_flow / south_flow"""
# ... 列名映射逻辑
pass

五、验证:docker restart 后全链路测试

修改完成后,通过 docker restart 重启服务,并运行端到端测试:

  • 主接口正常时:返回正确的北向资金数据,列名标准化无误。
  • 模拟签名过期:强制让 WBI 签名失效,验证自动切换到备用接口。
  • 备用接口异常:模拟备用接口返回空,验证切换到 yfinance。
  • yfinance 不可用:断网测试,验证正确标记数据为”缺失”。

全部测试通过。系统日志显示:

1
2
3
4
5
[INFO] 2026-07-01 03:00:01 NorthboundPipeline started
[WARN] Primary interface returned empty (WBI signature expired)
[INFO] Switched to fallback source: fund_flow_summary_em
[INFO] Data normalized: north_flow=OK, south_flow=OK
[INFO] Pipeline completed successfully in 2.3s

验证结果:三级降级策略全部通过。系统在签名过期场景下自动切换到备用接口,数据完整性和列名标准化均正常。

六、回头看:从这次故障中学到了什么

这次”双接口同时坏死”的故障暴露了数据采集管道中的几个关键问题:

  • 健康检查不够细粒度:”返回结果”不等于”返回有效数据”。空 DataFrame 和全 NaN DataFrame 需要通过内容检查才能识别。
  • 签名过期是静默故障:与 HTTP 500 不同,签名过期通常不会报错,而是返回空结果或错误数据。这种故障更难发现。
  • **多源管道的价值在于”不重叠的失效模式”**:如果两个接口的失效原因相同(如同一个 WBI token),它们就不是真正的冗余。设计降级策略时,需要确保各层使用不同的数据源和签名机制。

最终,这套三级降级策略不仅解决了北向资金采集的问题,其”主接口→备用接口→兜底方案→标记缺失”的模式也被复用到其他数据采集模块(QFII、产业链数据等)。
总结:多源数据管道的健壮性不在于接口的数量,而在于各层失效模式的独立性。签名过期这类”静默故障”是最大威胁,需要内容级健康检查 + 自动降级 + 明确标记三重保障。


东方财富北向资金双接口同时坏死——一个降级+迁移方案
https://www.normdist.com/2026/07/01/ND-20260701-001-eastmoney-northbound-failover/
作者
小瑞
发布于
2026年7月1日
许可协议