全系统key配对升级 bug17

配对维度优化后 — 缺陷与隐患分析报告

分析范围:全系统 Key 改为配对维度 (symbol, base_symbol) 后的当前状态
日期:2026-02-20


一、已正确落地的部分(简要)

  • 内存状态PositionManager._positionsAdaptiveBollingerStrategy._baselines / _positions / _last_adaptive_z 等均按 PairKey = (symbol, base_symbol) 存储。
  • 配置与风控get_strategy_params(symbol, base_symbol)is_symbol_allowed / is_close_disabled 支持币种级与配对级。
  • 持久化trading_signalspair_positionsanalysis_resultssymbol_blacklist 均含 base_symbol;迁移脚本已把索引/压缩分段改为 PairKey。
  • 策略与编排:入场/退场、止损、仓位同步、信号去重键 symbol:base_symbol:direction:ts 均按配对维度处理。
  • 分析层:黑名单、新币黑名单的 key 均为 (symbol, base_symbol);分析结果写入带 base_symbol;历史 z4h 灌入按 (symbol, base_symbol) 分组。

二、缺陷(建议修复)

缺陷 1:新币黑名单与取消订阅的维度不一致【高优先级 — 运行时 Bug】

位置src/services/realtime_kline_service_base.py(约 1116–1148 行)

现象
new_coin_blacklist配对存储 pair_key = (symbol, base_symbol)。但"数据不足"时对**整个币种(coin)**取消 K 线订阅:

coin = symbol.split('/')[0]
subscriptions_to_remove = [
    {"type": "candle", "coin": coin, "interval": "5m"},
    ...
]
self.ws_manager.remove_subscriptions(subscriptions_to_remove)

问题
例如仅 PURR|HYPE 因 4H 数据不足被加入 new_coin_blacklist,却会取消整个 PURR 的订阅,导致 PURR|BTC 等其它配对也不再收到 K 线,被错误地"连带"停掉。

建议

  • 方案 A(推荐):取消订阅前判断:仅当该 symbol_pair_cache 中的所有 base 对应的配对都已出现在 new_coin_blacklist 时,才取消该 symbol 的订阅;否则只把当前配对加入黑名单,不取消订阅。
  • 方案 B:不在此处取消订阅,仅做"该配对不分析";若需节省资源,再单独做"按 symbol 聚合、全部配对都不可用再退订"的逻辑。

缺陷 2:数据自愈仅针对默认 base,多 base 配对未覆盖【中优先级】

位置src/services/realtime_kline_service_base.py(约 1717–1722 行)

现象
自愈配对列表为:

heal_pairs = [
    (s, self.base_symbol) for s in self.symbols
    if s != self.base_symbol and (s, self.base_symbol) in pairs_with_data
]

即只自愈 (symbol, self.base_symbol),未使用 _pair_cache 中的多 base。

问题
当同一 alt 对应多个 base(如 PURR|HYPE、PURR|BTC)时,只有 (PURR, self.base_symbol) 会参与自愈;若默认 base 为 HYPE,则 PURR|BTC 缺数时不会被自愈。

建议
_pair_cache 构建需自愈的配对列表,例如:

heal_pairs = [
    (s, b)
    for s in self.symbols
    for b in (self._pair_cache.get(s) or [self.base_symbol])
    if s != b and (s, b) in pairs_with_data
]

(并去重、控制并发/超时,避免一次自愈过多配对)。


缺陷 3:base_symbol 空值规范化存在三种混用模式【中优先级】

现象:代码中存在三种不统一的处理方式:

位置 模式 风险
strategy.py(9 处) base_symbol = base_symbol or "" 局部赋值 局部规范化 ✅
position_manager.pyorchestrator.py pos.base_symbol or "" 内联使用 部分覆盖 ⚠️
trade_repository.py(save_signal、save_position) 直接使用,未规范化 可能写入 NULL

问题
若某条调用路径中 base_symbolNone(而非 ""),会导致:

  • PairKey 不匹配:("PURR", None) ≠ ("PURR", "") → 字典 key 查找失败,状态悄然丢失
  • 数据库写入 NULL 值,后续查询行为不一致

建议
models.py 中定义统一的规范化 helper,全系统调用:

def normalize_base_symbol(base_symbol: str | None) -> str:
    return base_symbol or ""

缺陷 4:数据库 base_symbol 字段存在历史 NULL 值风险【中优先级】

位置src/trading/trade_repository.pysave_signalsave_position

现象
持久化时直接传入 Python 对象中的 base_symbol,未做 or "" 规范化,若对象中为 None 则数据库存入 NULL。

建议

  1. 先查验现有数据:
    SELECT COUNT(*) FROM pair_positions WHERE base_symbol IS NULL;
    SELECT COUNT(*) FROM trading_signals WHERE base_symbol IS NULL;
    SELECT COUNT(*) FROM analysis_results WHERE base_symbol IS NULL;
    
  2. 存在 NULL 时清理:
    UPDATE pair_positions   SET base_symbol = '' WHERE base_symbol IS NULL;
    UPDATE trading_signals  SET base_symbol = '' WHERE base_symbol IS NULL;
    UPDATE analysis_results SET base_symbol = '' WHERE base_symbol IS NULL;
    
  3. 加约束防止新写入 NULL:
    ALTER TABLE pair_positions   ALTER COLUMN base_symbol SET NOT NULL;
    ALTER TABLE trading_signals  ALTER COLUMN base_symbol SET NOT NULL;
    ALTER TABLE analysis_results ALTER COLUMN base_symbol SET NOT NULL;
    

三、不足与改进建议(非致命)

不足 5:get_positions_by_symbols 仅按 symbol 过滤,语义模糊

位置src/trading/trade_repository.py(约 257–262 行)

现状
WHERE symbol = ANY(%s),返回该 symbol 下所有 base_symbol 的仓位。
当前唯一调用方 PositionManager._build_orphan_positions 在内存中再按 (symbol, base_symbol) 分组,逻辑正确,无立即风险。

建议
保持现状;若未来有"按配对查询仓位"的接口需求,新增 get_open_positions_by_pairs(pairs: list[PairKey]) 而非复用现有方法,以避免语义混淆。


不足 6:每日统计无配对维度

位置src/trading/trade_repository.pyupdate_daily_stats
现状daily_trading_stats(stat_date, network, ...) 按"日+网络"全局汇总,无 (symbol, base_symbol)

建议
若产品需要"按配对看每日表现",可后续增加按 PairKey 的统计表或字段;当前若仅需全局视角,可保持不变。


不足 7:历史已压缩 Chunk 仍为旧分段方式

现状
新数据已按 (symbol, base_symbol) 分段压缩;已存在的压缩 chunk 仍是按旧分段(如仅 symbol)压缩的,不会自动重写。

建议
若需对历史数据也按 PairKey 分段压缩,可在低峰期对相关 hypertable 执行 decompress_chunk + 再压缩(评估 I/O 与锁影响);否则接受"历史 chunk 旧分段,新数据新分段"的混合状态,并在文档中注明。


不足 8:入队节流维度为 (symbol, timeframe),不含 base(有意设计)

位置realtime_kline_service_base.py(约 885 行注释)

现状
同一根 K 线只调度一次分析任务,任务内部对该 symbol 的所有 base 循环执行 _analyze_and_alert。节流 key 为 (symbol, timeframe),不按 base 分开。

结论
这是有意设计(一根 K 线驱动多配对分析),与配对维度不冲突;仅需在文档中明确"节流按 symbol+timeframe,分析按 (symbol, base_symbol)",防止后续开发者误解。


四、优先级汇总

编号 类型 描述 优先级
缺陷 1 Bug 新币黑名单按配对,但取消订阅按币种,导致其它配对被连带停数据 🔴 高
缺陷 2 Bug 数据自愈只考虑 (symbol, self.base_symbol),多 base 配对未自愈 🟡 中
缺陷 3 隐患 base_symbol 空值规范化三种模式混用,潜在 PairKey 失配 🟡 中
缺陷 4 隐患 数据库历史 NULL 值风险,持久化未规范化 🟡 中
不足 5 改进 仓库接口 get_positions_by_symbols 语义不够精确 🟢 低
不足 6 改进 每日统计无配对维度 🟢 低
不足 7 改进 历史压缩 chunk 仍为旧分段 🟢 低
不足 8 文档 入队节流维度说明缺失 🟢 低/文档

建议行动顺序

  1. 立即修复:缺陷 1(订阅取消逻辑改为配对聚合后再退订)
  2. 近期修复:缺陷 2(自愈从 _pair_cache 构建多 base 配对列表)+ 缺陷 3(统一 normalize_base_symbol helper)+ 缺陷 4(数据库 NULL 清理与约束)
  3. 技术债积累处理:不足 5–8 按需迭代

Read more

跑步的技巧(滚动落地)

“滚动落地(rolling contact / rolling foot strike)”不是一种教条式的“脚法”,而是一种 让冲击沿着整只脚、整条后链逐级传递的落地机制。 它的核心不是“你先用哪儿着地”,而是: 你的脚落地之后,冲击是不是像轮子一样滚过去,而不是像锤子一样砸下去。 这就是滚动落地的本质。 一、什么叫“滚动落地”? 你可以把它理解成两种完全不同的落地方式: 1. 砸地(撞击式) 脚像锤子一样拍到地上: * 要么后跟先砸 * 要么前掌先戳 * 冲击集中在一个点 * 一个结构瞬间吃掉大部分载荷 结果就是: * 后跟砸 → 膝盖难受 * 前掌戳 → 前脚掌磨烂 * 都不是长跑友好模式 这叫 撞击式着地(impact strike)。 2. 滚地(滚动式) 脚像轮胎一样“滚”过地面: * 不是某一点硬砸 * 而是外侧中足先轻触 * 再向前滚到前掌 * 最后从大脚趾蹬离

By SHI XIAOLONG

AMI的优越性

世界模型(World Models)的具体例子 如下,我按类型分类,便于理解。每类都附带实际实现、演示效果和应用场景。 1. Yann LeCun / Meta 的 JEPA 系列(最直接对应“世界模型”概念) 这些是 LeCun 主张的非生成式抽象预测世界模型代表。 * I-JEPA(Image JEPA,2023) 输入一张图像,模型把不同区域(context 和 target)编码成抽象表示,然后预测 target 的表示(不在像素级别重建)。 例子:给定一张遮挡了部分物体的图片,模型能预测“被遮挡物体的大致位置和属性”,构建对物体持久性和空间关系的理解。 这是一个“原始世界模型”,能学习物理常识(如物体不会凭空消失)。 * V-JEPA / V-JEPA 2(Video JEPA,

By SHI XIAOLONG

什么是:“世界模型(World Models)”

世界模型(World Models) 是人工智能领域的一个核心概念,尤其在 Yann LeCun 等研究者推动的下一代 AI 架构中占据中心位置。它指的是 AI 系统在内部构建的对现实世界的抽象模拟或内部表示,让机器能够像人类或动物一样“理解”物理世界、预测未来、规划行动。 简单比喻 想象你闭上眼睛也能“看到”房间里的物体会如何移动、碰撞或掉落——这就是你大脑里的世界模型。AI 的世界模型就是类似的“数字孪生”(digital twin)或“内部模拟器”:它不是简单记住数据,而是学习世界的动态、因果关系和物理直觉(如重力、物体持久性、遮挡、因果等)。 为什么需要世界模型? 当前主流的大型语言模型(LLM) 擅长处理文本(统计模式预测),但存在根本局限: * 缺乏对物理世界的真正理解 → 容易“幻觉”、无法可靠规划。 * 样本效率低 → 人类/

By SHI XIAOLONG

K线周期可配置化设计方案

K线周期可配置化设计方案 1. 背景与目标 当前 Beta 套利策略的 K 线周期硬编码为 "1h",分散在多个文件中。需要: 1. 将 K 线周期从 1h 改为 2h 2. 提取为环境变量 BETA_ARB_KLINE_INTERVAL,使其可在 .env 中配置 2. 影响范围分析 2.1 需要修改的文件(共 6 个) 文件 硬编码位置 修改内容 src/trading/config.py BetaArbConfig dataclass 新增 kline_interval 字段,

By SHI XIAOLONG