数据自愈BUG Cursor 2

数据自愈模块启动期 BUG 分析报告(Cursor 2)

基于 realtime_kline_service 启动日志与代码阅读的根因归纳。


1. 「尝试更大范围」未真正扩大窗口

现象(日志)

  • 出现「数据不足: 1 条(24h 窗口),尝试更大范围」后,没有再出现「加载历史数据: N 条(48h/72h 窗口)」。
  • 直接进入「第 1 轮检查...」,最终「无法确定修复目标」。

根因(代码)

orchestrator.py_load_zscore_history 的时间窗口是写死三档

needed_hours = (required_count * self.interval_minutes) / 60
time_ranges_hours = [
    math.ceil(needed_hours),           # 12
    math.ceil(needed_hours * 1.3),     # 16
    math.ceil(needed_hours * 2),       # 24
]
time_ranges_hours = sorted(set(time_ranges_hours))  # [12, 16, 24]

对 4h、要 3 条时,最大只尝试 24h。24h 仍只有 1 条时循环结束,没有 48h/72h 等更大窗口,「尝试更大范围」只是日志文案,没有对应逻辑。

涉及文件src/utils/data_healing/orchestrator.py(约 L417–425)。


2. 仅 1 条数据时不生成任何修复目标

现象(日志)

SEI、XAI、IOTA、CAKE、SUPER、FARTCOIN(vs BTC)、PEOPLE、ATOM 等出现:

  • 「数量不足(1/3), 已过时1284min」
  • 「无法确定修复目标,终止修复」

根因(代码)

  • _diagnose 里,shortfall_targets 只在「连续且无缺口且数量不足」时生成:
# 3. 数量不足检查
shortfall_targets: List[datetime] = []
if is_continuous and not gap_times and len(records) < required_count:
    shortfall_targets = self._generate_shortfall_targets(records, required_count)
  • continuity_checker少于 2 条 时直接返回 is_continuous=False
if len(records) < 2:
    logger.debug(f"数据点不足({len(records)}条),无法判断连续性")
    return False, [], completeness_pct

因此:当只有 1 条时,is_continuous 恒为 False,shortfall_targets 永远为空_merge_repair_targets 得到空列表 → 打印「无法确定修复目标」。
即:恰恰在「只有 1 条、最需要补数」的场景下,自愈逻辑不生成任何补数目标。

涉及文件src/utils/data_healing/orchestrator.py(L235–238)、src/utils/data_healing/continuity_checker.py(L55–57)。


3. 加载「时间窗」与修复「向更早补」语义不一致

(与 docs/数据自愈BUG Cursor 1.md 中的根因一致。)

  • 加载kline_time >= NOW() - N 小时,只看「最近 N 小时内」的数据。
  • 数量不足时的修复:在当前最早一根之前向更早补点(_generate_shortfall_targetsearliest_time - i * interval)。

结果:补进去的 bar 若早于当前 12h/16h/24h 窗,重载时仍用同一套时间窗,看不到刚补的那条,出现「修了也白修」、多轮修复无效。
当前日志里多数在「只有 1 条」就终止,尚未进入多轮修复;一旦修复 1 条场景,仍会撞上「补了重载看不见」的问题。

涉及文件src/utils/data_healing/orchestrator.py_load_zscore_history_generate_shortfall_targets)。


4. 同一标的在不同配对下表现不一致

现象(日志)

  • FARTCOIN vs kNEIRO:12h 窗即拿到 3 条,自愈 ready。
  • FARTCOIN vs BTC:24h 窗仍只有 1 条,自愈 failed。

说明

自愈是按 (symbol, base_symbol)analysis_results 里查的,每个配对独立。有的配对历史上只写过很少的 zscore(例如只有 1 根 4h),所以即使用 24h 窗也只有 1 条。
这不是实现错误,但说明:「数据不足」往往对应该配对历史数据本身就极少;若 1 条时还不生成修复目标(见第 2 点),这些配对就会一直 failed。


5. 「已过时 1284/1285min」与单条数据

「已过时1284min」约 21.4 小时,说明那唯一一条是约一天前的 4h bar。
对 4h 来说,新鲜度阈值是 interval_minutes * FRESHNESS_MULTIPLIER(约 600 分钟),因此会被判为过时。

问题在于:过时 + 只有 1 条 时,既没有生成 shortfall_targets(因为 is_continuous=False),stale_targets 又只在 len(records) >= required_count 时生成,因此既不会按「数量不足」补更早的 bar,也不会按「过时」补更新的 bar,结果就是直接放弃。

涉及逻辑_diagnose 中 shortfall 与 stale 的生成条件。


小结(BUG 清单)

类型 表现 根因
虚假的「尝试更大范围」 24h 仍不足就结束,没有 48h/72h time_ranges_hours 最大只到 24h,没有更大窗口
1 条数据不修 数量不足(1/3) → 无法确定修复目标 1 条时 is_continuous=False,shortfall 从不生成
修了也看不见 多轮修复后条数仍不增加 加载「时间窗内」与修复「向更早扩展」不一致,重载窗不变
过时 + 不足 3 条 已过时但无修复目标 stale 只在 record_count≥required 时生成,1 条时 shortfall 也不生成

建议修复方向(与 Cursor 1 文档一致)

  1. 1 条/0 条也生成修复目标
    len(records) < required_count 时,即使 is_continuous=False(例如只有 1 条),也生成 shortfall_targets(从当前最早一根向前补足到 required_count),或对 0 条沿用 full_timeline。

  2. 真正扩大窗口或改为「最近 N 条」

    • 要么在 _load_zscore_history 中增加更大窗口(如 48h、72h、168h);
    • 要么改为「按 ORDER BY kline_time DESC LIMIT required_count(可加最大时间范围)」的「最近 N 条」语义(推荐,见 Cursor 1 方案 A)。
  3. 修复后重载语义与「补更早」一致
    若保留时间窗,则修复后重载至少应扩大窗口以包含本次 shortfall 目标时间;或采用「最近 N 条」使补写条在重载时可见。

  4. 可选:缩小启动自愈范围 / 提前终止无效轮次
    见 Cursor 1 方案 C,减少启动耗时与无效 3 轮。


涉及文件一览

  • src/utils/data_healing/orchestrator.py:加载、诊断、shortfall/stale 生成、重载
  • src/utils/data_healing/continuity_checker.pylen(records)<2 时返回 is_continuous=False
  • src/utils/data_healing/config.pyLOAD_TIME_MARGIN
  • 参考:docs/数据自愈BUG Cursor 1.md(完整因果链与方案 A/B/C)

Read more

数据自愈模块提速3

数据自愈并发优化设计方案 一、现状分析 当前流程 _run_data_healing(realtime_kline_service_base.py:1807): for (symbol, base_symbol) in heal_pairs: # ~50+ 配对,串行 DataHealingOrchestrator(...) # → RepairExecutor.__init__ │ # → KlineDataFiller.__init__ │ # → Info(MAINNET_API_URL) HTTP 握手 ~0.85s │ # ← 第 2-50 个握手完成后才被 shared_executor 覆盖,全部浪费! _load_zscore_history()

By SHI XIAOLONG

数据自愈模块提速2

数据自愈并发优化设计方案 一、现状分析 当前流程 _run_data_healing(realtime_kline_service_base.py:1807): for (symbol, base_symbol) in heal_pairs: # ~50+ 配对,串行 DataHealingOrchestrator(...) # → RepairExecutor.__init__ │ # → KlineDataFiller.__init__ │ # → Info(MAINNET_API_URL) HTTP 握手 ~0.85s │ # ← 第 2-50 个握手完成后才被 shared_executor 覆盖,全部浪费! _load_zscore_history()

By SHI XIAOLONG

数据自愈模块综合问题分析报告2

数据自愈模块优化设计文档 版本:v1.0 日期:2026-02-23 范围:src/utils/data_healing/ + src/services/realtime_kline_service_base.py(_run_data_healing 部分) 目录 1. 问题全景与优先级总表 2. BUG-01:加载语义与修复语义不一致 3. BUG-02/03:单条/少量记录无法生成修复目标 4. BUG-04:日志误导性 5. BUG-05:重复写入(BUG-01 副作用) 6. BUG-06:test_basic.py 与 Diagnosis 定义失同步 7.

By SHI XIAOLONG