全系统key配对升级 bug12
配对维度优化后系统缺陷与不足分析
当前架构概览
- PairKey 定义:
src/trading/models.py中PairKey = tuple[str, str],即(symbol, base_symbol),全系统交易/仓位/策略状态均按此维度存储。 - 配置层配对键:黑名单与策略覆盖使用字符串格式:币种级
"PURR"、配对级"PURR|HYPE"(由 symbol/base_symbol 解析出 asset 部分后拼接),见config.py的is_symbol_allowed、is_close_disabled、get_strategy_params。 - 服务层配对键:分析黑名单与 pair cache 使用 tuple
(symbol, base_symbol)或 symbol 字符串(K 线/任务 key),见realtime_kline_service_base.py。
flowchart LR
subgraph trading [交易层]
PM[PositionManager]
RM[RiskManager]
Strat[Strategy]
Orch[Orchestrator]
end
subgraph config [配置]
BL[黑名单/close_disabled]
SP[策略参数覆盖]
end
subgraph service [分析服务]
PairCache[pair_cache]
AnaBL[_blacklist_cache]
end
PM --> PairKey
Strat --> PairKey
Orch --> BL
BL --> "ALT|BASE 字符串"
PairCache --> "alt_symbol 字符串"
AnaBL --> "tuple(symbol,base)"
PairKey["PairKey = (symbol, base_symbol)"]
一、已做对的部分(无缺陷)
- 仓位/策略/风控:
PositionManager、AdaptiveBollingerStrategy、RiskManager均按(symbol, base_symbol)做重复仓位检查、状态存储、止损/超时参数查找,与配置的get_strategy_params(symbol, base_symbol)一致。 - DB 与恢复:
pair_positions的 symbol/base_symbol、恢复时key = (symbol, base_symbol)、get_positions_by_symbols返回dict[PairKey, dict],与内存一致。 - 编排器:
process_analysis强制要求base_symbol存在、黑名单与策略参数均按配对维度调用,入场/退场与has_position(symbol, base_symbol)一致。 - 孤儿与同步:
sync_with_exchange返回的closed_pairs/adopted_pairs/base_lost_failed_pairs均为list[PairKey],编排器据此同步策略层;base 腿残留收纳为(orphan_symbol, "")单腿仓位,逻辑自洽。
二、缺陷与不一致
1. 双黑名单未统一,可能浪费算力且语义割裂
- 交易黑名单(config):
TRADING_SYMBOL_BLACKLIST,格式"PURR"或"PURR|HYPE",仅在 orchestrator.process_analysis 中用于拒绝开仓。 - 分析黑名单(DB + 服务内存):
symbol_blacklist表 +_blacklist_cache,key 为(symbol, base_symbol),用于跳过分析与拉黑保护(有持仓则拒绝写入 DB 黑名单)。
问题:若只在 config 中配置了配对级黑名单(如 PURR|HYPE),分析层仍会对该配对做完整分析与策略计算,仅到执行前被交易黑名单拒绝,造成 CPU/IO 浪费;反之若只加分析黑名单而未加 config,理论上仍可能对该配对产生信号并尝试开仓(取决于分析是否先被 DB 黑名单过滤)。两套黑名单来源、生命周期、键格式均不同,运维与预期行为容易混淆。
建议:在分析入口(如 _analyze_and_alert 或调度处)增加对交易黑名单的查询(需注入 config 或提供 is_symbol_allowed(symbol, base_symbol)),使被交易黑名单禁止的配对直接跳过分析;和/或提供文档/配置说明,明确“分析黑名单 vs 交易黑名单”的职责与推荐用法。
2. 配对关系缓存键与 K 线 symbol 格式需明确约定
- pair_cache:来自
cointegrated_pairs,_pair_cache[alt_symbol] = [base_symbol, ...],键为alt_symbol。 - 分析任务:K 线到达后以
symbol(如PURR/USDC:USDC)入队,工作线程用base_symbols = self._pair_cache.get(symbol, [])解析要分析的配对。
若 cointegrated_pairs 中存的是全合约符号(如 PURR/USDC:USDC),与 K 线 symbol 一致,则查找正确;若存的是资产名(如 PURR),则 _pair_cache.get("PURR/USDC:USDC", []) 会落空,仅能依赖 self.base_symbol,导致多 base 配对发现依赖回测/导入的符号格式。
建议:在文档或代码注释中明确规定 cointegrated_pairs.alt_symbol / base_symbol 必须与实时 K 线/交易使用的 symbol 格式一致(推荐全合约);或在加载 pair_cache 时统一做 normalize(如都转为全合约),避免隐式依赖。
3. 孤儿收纳时 close_disabled 仅按币种级过滤
- 逻辑:
position_manager.py中_collect_orphan_candidates仅调用is_close_disabled(coin_to_symbol(coin)),即base_symbol="",只做币种级禁止平仓检查。 - 影响:若仅配置了配对级 close_disabled(如
PURR|HYPE),则交易所上残留的 PURR 单腿(例如原 PURR|HYPE 配对中 base 腿已平)仍会被收纳为孤儿;收纳后该仓位 key 为(PURR/USDC:USDC, ""),平仓时仍不会命中PURR|HYPE,因此不会被 close_disabled 禁止平仓。从“配对级仅禁止以该配对身份平仓”的语义看,单腿孤儿不再属于该配对,当前行为可接受,但若希望“凡涉及 PURR|HYPE 的腿一律不自动收纳/不自动平仓”,则需要在孤儿候选阶段也能考虑配对级 close_disabled(例如已知 pair 关系时用 (alt, base) 查一次)。
建议:若产品上希望“配对级 close 禁止也影响孤儿”,可在 _collect_orphan_candidates 或 _build_orphan_positions 中,对能解析出配对关系的孤儿用 is_close_disabled(symbol, base_symbol) 再滤一次;否则在文档中说明“close_disabled 配对级仅作用于显式配对仓位,不作用于单腿孤儿”。
三、可改进点(非致命)
4. 策略引擎与配置的 pair_key 展示格式不统一
- 配置的
pair_strategy_overrides的 key 为字符串"ALT|BASE"(如PURR|HYPE),日志中策略引擎也按pair_key打印。 - 策略内部全部使用
PairKey元组(symbol, base_symbol)。日志中若混用"PURR|HYPE"与(symbol, base_symbol)会略不利于排查。
建议:在日志/告警中统一使用一种人类可读格式(例如统一为 symbol|base_symbol 或 f"{symbol}|{base_symbol or '单币'}"),并在策略初始化等处与 config 的 pair 覆盖键格式保持一致,便于对照配置与行为。
5. 单币模式与空 base_symbol 的传递一致性
- 全链路已统一用
base_symbol or ""作为 PairKey 的第二元组,单币模式为(symbol, "")。 - 配置侧
get_strategy_params(symbol, "")会正确回退到币种级/全局,不会误用配对级覆盖。暂无发现遗漏,仅建议在对外接口(如 HTTP/CLI)或文档中明确“单币模式即 base_symbol 为空字符串”,避免后续扩展时引入不一致。
6. 数据自愈与配对维度
realtime_kline_service_base.py中数据自愈逻辑会查询“已有 zscore 数据的配对”并与活跃 symbol 取交集,再对heal_pairs做补点。若自愈或历史数据中存在 symbol/base_symbol 格式与当前 pair_cache 或 config 不一致(如历史为资产名、当前为全合约),可能漏补或重复键。建议自愈使用的配对列表与 pair_cache/config 使用同一套符号规范化逻辑。
四、总结表
| 类别 | 描述 | 严重程度 |
|---|---|---|
| 双黑名单未统一 | 分析层不读交易黑名单,可能对已禁止交易的配对继续做分析;两套黑名单语义与运维割裂 | 中 |
| pair_cache 键格式 | alt_symbol 与 K 线 symbol 格式未强制约定,依赖回测/导入写法,易出现“查不到多 base” | 中 |
| 孤儿与配对级 close_disabled | 孤儿收纳只按币种级 close_disabled 过滤,配对级仅作用于显式配对仓位 | 低 |
| 日志/展示格式 | 配置用 "ALT|BASE",策略用 tuple,可统一为同一可读格式 | 低 |
| 自愈与符号规范 | 自愈配对列表与 pair_cache/config 的符号格式若不一致可能影响补数 | 低 |
建议优先:在分析入口增加对交易黑名单的检查(1);明确并统一 cointegrated_pairs 与实时 symbol 的格式约定或 normalize(2)。其余为体验与可维护性改进。