全系统key配对升级 bug3
配对维度优化后系统缺陷与不足分析
分析日期:2026-02-19
分析范围:全系统 Key 改为 (symbol, base_symbol) 配对维度后的代码质量审查与现状核实
结论:核心路径(交易、策略、配置、自愈、新币黑名单)的配对维度与文档中记录的 Bug 已修复;仍存在脚本/工具一致性、配对缓存刷新与文档澄清等不足。
一、文档中记录且当前代码已修复的部分
以下问题在 docs/bug-analysis-pair-key-refactor.md 与 docs/pairkey-optimization-defect-analysis.md 中有记录,当前代码已修复,无需再改:
| 项目 | 文档描述 | 当前代码状态 |
|---|---|---|
| Bug #1 平仓失败路径无锁 | position_manager 527 行恢复 OPEN 未持锁 | src/trading/position_manager.py 526-528 已使用 with self._lock |
| Bug #2 配对级参数不继承币种级 | _load_pair_strategy_overrides 未接 symbol_overrides | src/trading/config.py 362-403 已接收 symbol_overrides 并以 base_cfg 回退;501 行传入 _sym_overrides |
| Bug #3 is_ready 25% 阈值 | 仅 25% 即就绪,统计不可靠 | src/trading/strategy.py 134、141、386 行已改为 // 2(50%) |
| 数据自愈 _load_zscore_history | 查询仅 WHERE symbol,未 base_symbol | src/utils/data_healing/orchestrator.py 460-474 已包含 AND base_symbol = %s 及 self.base_symbol 入参 |
| new_coin_blacklist 维度 | 原为 symbol 维度误伤多 base | src/services/realtime_kline_service_base.py 244 为 set[tuple[str, str]],1115-1122、1500 使用 (symbol, base_symbol) |
| 自愈触发列表 | 仅按 symbol 枚举 | 同文件 1688-1703 已改为 SELECT DISTINCT symbol, base_symbol 并与 (s, self.base_symbol) 取交 |
结论:核心交易、策略、配置、自愈、新币黑名单的配对维度实现已对齐且上述 Bug 已闭合。
二、仍存在的缺陷与不足(按优先级)
1. 脚本/工具查询 analysis_results 未带 base_symbol(一致性 + 多配对风险)
位置与问题:以下脚本在查询 analysis_results 时仅使用 WHERE symbol = %s,与生产逻辑(orchestrator、DB 表语义)的配对维度不一致;在多 base 或后续多配对扩展下会混用不同配对数据。
| 文件 | 说明 |
|---|---|
src/scripts/query_analyze_result/check_buffer_continuity.py |
约 34 行:模拟启动加载逻辑,应与 orchestrator 一致带 base_symbol |
src/scripts/fix_buffer_loading.py |
SOLUTION_1_SQL 中约 19 行:仅 WHERE symbol = %s |
src/scripts/query_analyze_result/check_missing_purr_zscore.py |
约 35 行 |
src/scripts/query_analyze_result/query_purr_zscore.py |
约 58 行 |
src/scripts/query_analyze_result/query_eth_zscore.py |
约 63 行 |
src/scripts/query_analyze_result/query_purr_zscore_beyond2_5.py |
约 56 行 |
src/scripts/optimize_adaptive_zscore.py / optimize_adaptive_zscore_v2.py |
约 101/138、111/148 行从 analysis_results 取数仅按 symbol |
src/scripts/backfill_analysis_results.py |
约 90 行 get_existing_kline_times 仅 symbol;脚本内 SYMBOL/BASE_SYMBOL 为常量,单配对可接受但建议显式带 base_symbol |
src/scripts/backfill_all_data.py |
约 204 行 WHERE symbol = %s |
建议:凡涉及「某一配对」的启动模拟、连续性检查、回填、优化脚本,查询应带 AND base_symbol = %s,并由脚本参数或常量传入 base_symbol,与生产及 PairKey 维度一致。
2. 配对缓存无定期刷新(设计改进)
位置:src/services/realtime_kline_service_base.py 中 _load_pair_cache() 仅在初始化时调用;_monitor_queue_health(约 1786-1869 行)仅做队列健康、黑名单清理、入队去重清理,未调用 _load_pair_cache()。
影响:运行中若在 DB 新增配对,当前进程不会加载新配对,需重启才能生效。
建议:在 _monitor_queue_health 循环中增加「每 5 分钟(或可配置间隔)调用一次 _load_pair_cache()」,与黑名单清理类似用时间戳控制频率。优先级可定为低(运维便利性)。
3. 历史压缩 Chunk 与新区间压缩维度不一致(运维/文档)
位置:database/migrations/20260219_fix_pairkey_indexes.sql 已将 analysis_results 压缩分段改为 (symbol, base_symbol),注释 44-46 行说明:已压缩的历史 chunk 仍为旧分段(仅 symbol)。
影响:同一表中存在两种压缩分段方式;对历史区间的按配对查询/压缩效果与新区间不一致。
建议:在运维/架构文档中明确:(1)是否接受「仅新数据按配对压缩」;(2)若需一致,可在维护窗口对历史 chunk 执行 decompress_chunk + recompress_chunk 的步骤或链接到 TimescaleDB 文档。
4. 配置与文档澄清(非代码缺陷)
- config.symbol_blacklist:静态配置的「币种黑名单」(按币种名禁止交易),与 DB 的「配对维度 24h 校验黑名单」是两套机制,建议在配置说明或架构文档中区分二者职责与使用场景。
- backfill / 自愈:若 backfill 或自愈长期只支持「单 base」或「单配对」,建议在 README 或脚本 docstring 中写明,避免多配对场景下误用。
5. 新币 4H 不足时的取消订阅语义(可选澄清)
位置:src/services/realtime_kline_service_base.py 约 1125-1132 行:当某配对 (symbol, base_symbol) 的 4H 数据不足时,将 pair_key 加入 new_coin_blacklist,但取消订阅是按 coin = symbol.split('/')[0] 移除该币种的全部 candle 订阅。
含义:同一 symbol 若对多个 base 存在多个配对,只要有一个配对因 4H 不足进黑名单,该 symbol 的订阅会被整体移除,其它 base 的配对也不再收到 K 线。若产品意图是「该 symbol 对任一 base 数据不足则不再监控该 symbol」则合理;若意图是「仅禁用该配对、其它配对照常」则需考虑只禁用该配对分析而不取消整个 symbol 订阅,并在文档中说明当前行为。
三、小结(建议修复/改进优先级)
- 高(一致性):脚本与工具中凡「按配对」使用
analysis_results的查询,统一增加base_symbol条件或参数(尤其是 check_buffer_continuity、fix_buffer_loading、backfill、optimize_adaptive_zscore 等)。 - 中(运维):配对缓存定期刷新(如每 5 分钟在健康监控中调用
_load_pair_cache())。 - 低(文档):历史压缩 chunk 的处置方式、两套黑名单的区分、backfill/自愈的单配对假设、新币取消订阅语义,在文档或注释中写清。
当前核心路径(交易、策略、配置、自愈、新币黑名单)的配对维度与已知 Bug 已修复;剩余问题主要集中在脚本/工具一致性、配对缓存刷新和文档/运维澄清三方面。