CADRSTECH BLOG
首页关于
CADRS TECH BLOG

探索技术世界的思考与实践,记录编程之旅的点滴感悟

© 2026 CADRS. 琼ICP备19000754号-1

首页2026-04-22:比接口报错更糟的,是历史数据被“成功”改坏
工作日志

2026-04-22:比接口报错更糟的,是历史数据被“成功”改坏

2026年4月22日 14:006 min read0

2026-04-22:比接口报错更糟的,是历史数据被“成功”改坏

今天最值钱的发现,不是数据接口又断了,而是它在断开之前已经把历史行写进去了。对量化系统来说,明确失败其实还好处理;真正麻烦的是 日志告诉你 saved=1, merged=1,网络却同时抛 RemoteDisconnected,最后仓库只剩一个 dirty working tree。这不是“成功”或“失败”,这是最难排查的中间态。

今天确认的模式:回补窗口是成功的,数据质量不是

/root/Alpha 今天没有新 commit,但 15:10 左右有 3 个关键文件被持续改写:data/csv/sz002594.csv、logs/getData.log、workspaces/t_strategy/sz002594_比亚迪/reports/pre_strategy_summary.md。git diff --stat 显示总计 183 行新增、19 行删除,其中仅 getData.log 就新增了 160 行。

这次新增日志里,至少能还原出 6 个连续滑动回补窗口:

  • 20260412 -> 20260417
  • 20260413 -> 20260418
  • 20260414 -> 20260419
  • 20260415 -> 20260420
  • 20260416 -> 20260421
  • 20260417 -> 20260422

问题在于,这 6 轮的结尾模式完全一致:每轮都是 saved=1、failed=0、merged=1,然后马上抛出 RemoteDisconnected('Remote end closed connection without response')。这说明现在的数据链路有一个很糟糕的边界:本地写盘和远端确认不是原子操作。接口失败并不代表“什么都没发生”,恰恰相反——它已经发生了一半。

真正危险的不是漏一根 K 线,而是历史行被重写

今天最值得盯住的是 2026-04-13 这行历史数据。更新前后对比如下:

更新前: sz002594,比亚迪,2026-04-13,...,104.25,104.25,66313598.0,6887089022.0,...
更新后: sz002594,比亚迪,2026-04-13,...,104.25,101.67,663136.0,6887089022.36,...

这里至少有两个硬伤:

  1. 成交量从 66,313,598 股直接掉到 663,136 股,缩小了接近两个数量级。
  2. 成交额却几乎没变,仍然约 68.87 亿元,于是隐含成交均价被抬到 10385.64 元/股。

这已经不是“数据有点噪声”,而是字段之间失去自洽。更麻烦的是,pre_close 还从 104.25 被改成了 101.67,直接破坏了相邻交易日之间最基本的连续性。量化回测最怕这种问题——新数据没来齐还能等,历史数据被静默篡改会把因子、收益、风险统计一起带偏。

摘要指标已经开始漂移,而且漂得不正常

pre_strategy_summary.md 已经把这批变更吸收进去了。单看样本推进,好像只是多了几天数据;但一旦把前后指标摆在一起,问题就很明显:

指标修改前修改后变化
全区间样本天数35803584+4
全区间涨跌304.83%298.94%-5.89pp
近60日区间涨跌6.01%5.55%-0.46pp
近120日区间涨跌-1.34%-2.08%-0.74pp
近250日区间涨跌-71.18%-69.82%+1.36pp

如果只是补了 2026-04-16 到 2026-04-21 这几天,全区间收益一下子回撤 5.89 个百分点 并不合理。更可信的解释是:新增样本只是表面现象,真正拉动统计漂移的是历史行被改写。

今天的教训:merged=1 只能证明“写过”,不能证明“写对”

我今天最大的误判,是还在把 merged=1 当成一个偏正面的信号。现在看,它最多只能证明 CSV 确实被覆盖过,完全不能证明这份覆盖后的数据仍然可信。另一个问题是让 pre_strategy_summary.md 直接吃刚合并的原始 CSV——这等于把脏数据的影响立刻广播到后续策略生成环节。

明天要先补的不是更多历史数据,而是更严格的写入闸门:

avg_price = amount / volume
assert low * 0.8 <= avg_price <= high * 1.2
assert abs(next_pre_close - close) < 0.01

除此之外,还需要把流程改成:先拉取到临时区、做行级校验、再决定是否 merge 到正式 CSV;只要出现网络异常,就禁止刷新摘要。 如果历史行被改写,还应该强制输出 diff 给人工复核,而不是悄悄吞进仓库。

今天没有产出新 commit,但确认了一件更重要的事:当前 ingest 流水线最大的风险不是“接口会报错”,而是它会在报错前先把你的历史数据改坏。这比单纯失败危险得多,因为它会让整个回测系统带着错数据继续往前跑。

返回文章列表