全系统key配对升级不完全分析1

系统缺陷分析报告:全系统 Key 配对维度升级后状态

Context

本次升级将系统内所有内部状态 key 从单一 symbol: str 升级为 PairKey = tuple[str, str](symbol, base_symbol),解决了同一 symbol 与多个 base 配对时的数据混淆问题。核心修改涉及 6 个文件:models.py, strategy.py, position_manager.py, trade_repository.py, protocols.py, orchestrator.py

分析目标:评估升级后系统是否仍存在遗漏,哪些地方未完全配对化。


发现的缺陷

🔴 P1(高优先级):query_avg_zscore_4h 缺少 base_symbol 过滤

文件src/utils/database/timescaledb.py:793-816

问题代码

def query_avg_zscore_4h(self, symbol: str, hours: int = 4) -> float | None:
    results = self.client.execute_query(
        """
        SELECT AVG(zscore_4h) as avg_zscore_4h
        FROM analysis_results
        WHERE symbol = %s           -- ❌ 没有 base_symbol 过滤!
            AND zscore_4h IS NOT NULL
            AND analysis_time >= NOW() - make_interval(hours => %s);
        """,
        (symbol, hours)
    )

影响

  • 如果 analysis_results 表中同一 symbol(如 PURR)有对应多个 base(HYPE、BTC)的记录,查询会混合不同配对的 z-score 来求平均
  • avg_zscore_4h 用于入场时 PairTradeSignal 的辅助参数(entry_avg_zscore_4h),混合数据会导致策略指标失真
  • 调用路径:realtime_kline_service_base.py:1441avg_zscore_4hon_entry_signal:453

修复方案:在方法中增加 base_symbol: str = None 参数,SQL 增加 AND (base_symbol = %s OR %s IS NULL) 过滤。


🟡 P2(中优先级):_has_open_position Gate bypass 逻辑是 symbol 维度

文件src/services/realtime_kline_service_base.py:1521-1531:1547-1557

问题代码

# 1521行
if self._has_open_position(symbol):    # ← 只检查 symbol,不区分 base_symbol
    # skip_gates=True 跑退场分析

# 1547行
def _has_open_position(self, symbol: str) -> bool:
    if pm is not None and any(
        p.symbol == symbol for p in pm.open_positions  # ← symbol 维度
    ):
        return True

场景

  1. PURR/HYPE 有开仓
  2. PURR/BTC 分析触发,Gate 未通过
  3. _has_open_position("PURR") 因为 PURR/HYPE 有仓位返回 True
  4. 系统为 PURR/BTC 运行 skip_gates exit_only 分析
  5. on_exit_signal 因为没有 PURR/BTC 持仓而跳过(返回 False,无实际操作)
  6. 日志中会出现 退场信号但无活跃仓位: PURR|BTC 的 debug 日志

当前影响:低(不会误操作),但会有日志噪音,且分析计算浪费资源。

修复方案:将 _has_open_position(symbol) 改为接受 base_symbol 参数,按配对维度判断。或把原方法保留(用于其他逻辑),增加 _has_open_pair(symbol, base_symbol) 专用方法用于 Gate bypass。


🟡 P3(中优先级):孤儿收纳后策略引擎无法为其产生退场信号

文件src/trading/position_manager.py:644-703 (_adopt_residual_base_leg)

机制:Leg A 平仓成功、Leg B 失败时,系统将 Leg B 转为独立的 single 模式孤儿仓位:

orphan = PairPosition(
    symbol=base_symbol,   # 原 base_symbol 作为新仓位的 symbol
    base_symbol="",       # base_symbol 为空
    pair_mode="single",
    ...
)

问题:策略引擎收到的 tick 来自服务层,走的是 (base_symbol, other_base) 的 pair key(比如 HYPE/BTC),而孤儿仓位的 pair key 是 (HYPE, "")。两个 key 不匹配,策略引擎不会为孤儿产生退场信号。

当前缓解措施:孤儿仓位由止损监控线程(固定止损/移动止损/超时)管理,不依赖策略信号退场。设计上属于有意为之,但策略层的均值回归退场逻辑对孤儿完全失效。

修复方案(可选):对孤儿收纳后,_position_sync 中调用 strategy.sync_position(base_symbol, "", ...) 同步孤儿状态,并确保服务层对该孤儿 symbol 的单模式分析也能触发退场。注意:这需要评估是否符合设计意图。


🟡 P4(中优先级):_has_open_position 数据库兜底查询缺少 base_symbol

文件src/services/realtime_kline_service_base.py:1559+_has_open_position 数据库兜底逻辑)

与 P2 类似,数据库兜底查询可能也只按 symbol 过滤,与 P2 一并修复。


🟢 P5(低优先级/设计确认项):_check_entry 冷却时间(cooldown_minutes

文件src/trading/strategy.py

状态:已确认 _last_trade_time: dict[PairKey, datetime] 是配对维度,冷却是 per-pair 的,无问题


🟢 P6(低优先级):trade_repository.get_known_pair_relations 的 None 处理

文件src/trading/trade_repository.py:298

return [(row["symbol"], row["base_symbol"]) for row in rows]

SQL 已有 WHERE base_symbol IS NOT NULL AND base_symbol != '' 过滤,实际不会返回 None,无问题


正确工作的部分(确认)

组件 状态
strategy.py — 所有 9 个 dict 按 PairKey 维度 ✅ 正确
position_manager.py — open/close/sync 按配对 ✅ 正确
orchestrator.py — base_symbol 全链路传递 ✅ 正确
orchestrator.process_analysis — 从 multi_period_result 取 base_symbol ✅ 正确
analysis_core.analyze_multi_period — 返回 dict 含 base_symbol ✅ 正确
信号去重 key = symbol:base_symbol:direction:timestamp ✅ 已配对化
黑名单系统 _is_blacklisted(symbol, base_symbol) ✅ 已配对化
仓位同步 sync_with_exchange 返回 list[PairKey] ✅ 正确
止损监控 _close_with_retrypos.base_symbol or "" ✅ 正确
策略回调 on_position_closed/opened/rejected 带 base_symbol ✅ 正确

优先修复建议

  1. P1 立即修复query_avg_zscore_4h 增加 base_symbol 参数和过滤,调用方(realtime_kline_service_base.py:1441)传入当前配对的 base_symbol
  2. P2/P4 近期修复_has_open_position 增加配对维度版本,Gate bypass 使用 pair 精确匹配
  3. P3 评估:确认孤儿仓位仅靠止损监控退场是否为设计意图,如需策略退场则需额外工作

关键文件路径

  • src/utils/database/timescaledb.pyquery_avg_zscore_4h 方法(P1)
  • src/services/realtime_kline_service_base.py_has_open_position 方法、Gate bypass 逻辑(P2/P4)
  • src/trading/position_manager.py_adopt_residual_base_leg 孤儿收纳(P3)

验证方式

  • 场景:配置两个配对(如 PURR/HYPE、PURR/BTC),观察 avg_zscore_4h 日志打印是否混合
  • 场景:PURR/HYPE 有仓位时,手动触发 PURR/BTC 的 Gate 失败,检查日志中是否出现无意义的孤立退场尝试
  • 单元测试:为 query_avg_zscore_4h 增加带 base_symbol 参数的测试用例

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