全系统key配对升级 bug8
配对维度优化后系统缺陷与不足分析
当前已对齐配对维度的部分
- 配置层
src/trading/config.py:黑名单、禁止平仓、策略参数均支持配对级(ALT|BASE)与币种级;get_strategy_params(symbol, base_symbol)优先级为配对 > 币种 > 全局。 - 仓位与策略状态:
src/trading/position_manager.py:_positions: dict[PairKey, PairPosition],开/平仓、恢复、同步、孤儿收纳均按(symbol, base_symbol)。src/trading/strategy.py:_baselines、_positions、_exit_pending、_last_trade_time等全部按PairKey;prime_buffer、sync_position、on_position_closed、cleanup_pair均按配对。
- 编排与风控
src/trading/orchestrator.py、src/trading/risk_manager.py:入场/退场匹配、重复仓位检查、止损/同步线程均按(symbol, base_symbol)。 - 持久化
src/trading/trade_repository.py:get_open_positions、get_positions_by_symbols返回/键为 PairKey;get_known_pair_relations返回list[PairKey]。 - 数据库
database/migrations/20260219_fix_pairkey_indexes.sql:trading_signals、pair_positions、analysis_results的索引与压缩分段已改为(symbol, base_symbol)。 - 服务层
src/services/realtime_kline_service_base.py:_has_open_position(symbol, base_symbol)与 DB 查询均按配对 + network。
缺陷与不足
1. 告警限流/去重未按配对维度(建议修复)
- 位置:
src/utils/monitoring/alert_sender.py的限流与去重 key;src/trading/orchestrator.py中_send_entry_alert(..., pair_name=signal.symbol)。 - 问题:
pair_name仅传signal.symbol,同一 alt 多配对(如 PURR|HYPE 与 PURR|BTC)共享同一限流桶,一个配对的告警可能压制另一配对的正常告警。 - 建议:在 pair 模式或当
signal.base_symbol非空时,使用配对维度作为告警 key,例如
pair_name = f"{signal.symbol}|{signal.base_symbol}" if signal.base_symbol else signal.symbol,并在_send_entry_alert中传入该值。
2. cleanup_symbol 未被使用且与“仅按配对清理”策略不一致(建议明确或收敛)
- 位置:
src/trading/strategy.py中cleanup_symbol(symbol)(约 347–362 行)。 - 问题:
- 当前仅
cleanup_pair(symbol, base_symbol)被调用(退场/同步/止损后),没有任何地方调用cleanup_symbol。 cleanup_symbol(symbol)会按k[0] == symbol清除该 symbol 下所有配对的状态;若将来被误用(例如只传 symbol),会误清同 symbol 其他配对的状态。
- 当前仅
- 建议:二选一:
- 收敛:若业务上不需要“按币种整批清理”,可删除
cleanup_symbol,避免后续误用; - 保留:则仅在明确“禁用某币种并清理其所有配对”的入口调用,并在注释/文档中说明与
cleanup_pair的差异及调用场景。
- 收敛:若业务上不需要“按币种整批清理”,可删除
3. allow_duplicate_position 与当前内存结构不兼容(设计限制)
- 位置:
src/trading/position_manager.py中_positions: dict[PairKey, PairPosition]。 - 问题:当
allow_duplicate_position=True时,同一(symbol, base_symbol)可能有多条仓位,但_positions为 PairKey → 单条 PairPosition,后写入会覆盖先前的仓位,导致漏管或错误平仓。 - 建议:
- 短期:在配置说明或代码注释中明确“当前实现下 allow_duplicate_position 仅允许不同配对多仓,同一配对仅支持单仓”;若需同配对多仓,需先改结构。
- 中长期:若产品确需同配对多仓,可将
_positions改为dict[PairKey, list[PairPosition]]或按position_id索引(例如dict[str, PairPosition]),并同步修改开仓/平仓/恢复/同步的查找与更新逻辑。
4. 部分告警/日志未体现 base(可改进)
- 位置:例如
src/trading/orchestrator.py中平仓重试全部失败告警(约 439 行)使用symbol_to_coin(pos.symbol),未带 base。 - 问题:pair 模式下多配对时,仅看 alt 难以区分是哪一个配对失败。
- 建议:在关键告警标题或内容中,pair 模式下增加
pos.base_symbol,例如
f"{pos.symbol}|{pos.base_symbol or ''}"或symbol_to_coin(pos.symbol)+ 注明 base,便于排查。
5. 历史已压缩 chunk 与新区块分段不一致(运维已知,可选处理)
- 位置:
database/migrations/20260219_fix_pairkey_indexes.sql注释已说明。 - 问题:已压缩的
analysis_results/trading_signals历史 chunk 仍为旧分段方式;新数据才按(symbol, base_symbol)分段压缩,查询与压缩策略在历史数据上不一致。 - 建议:若需全量一致,可对历史 chunk 执行
decompress_chunk+recompress_chunk(需在低峰期执行);否则保持现状,仅新数据使用 PairKey 分段。
6. 其他一致性检查(无问题)
- 策略 signal 去重:
signal_key = f"{symbol}:{base_symbol}:{direction}:{timestamp}"已是配对维度,正确。 - 配置 key 格式:黑名单/策略覆盖统一为
ALT|BASE,环境变量用__解析为|,一致。 - daily_trading_stats:按 (stat_date, network) 汇总,无配对维度,符合当前“按日按网统计”的设计,无需为配对维度改动。
建议优先级
| 优先级 | 项 | 说明 |
|---|---|---|
| 高 | 告警 pair_name 按配对维度 | 小改,避免多配对时告警互相压制 |
| 中 | cleanup_symbol 删除或明确用法 | 避免误用导致误清其他配对状态 |
| 中 | allow_duplicate_position 文档/注释 | 明确“同配对仅单仓”的设计限制 |
| 低 | 告警/日志中体现 base_symbol | 便于 pair 模式排查 |
| 低 | 历史 chunk 重压缩 | 按需在运维窗口执行 |
小结
全系统 Key 改为配对维度后,核心路径(仓位、策略、持久化、DB 索引与压缩、服务层持仓判断)已一致使用 (symbol, base_symbol)。剩余问题主要集中在:告警限流 key 未按配对、未使用的 cleanup_symbol 的语义风险、以及 allow_duplicate_position 与当前一对一 PairKey 结构的限制。按上表优先级逐步处理即可进一步消除缺陷与歧义。