全系统key配对升级 bug5

配对维度优化后系统缺陷与不足分析

持久化自分析报告。在全系统 Key 已改为 (symbol, base_symbol) 配对维度的前提下,从一致性、边界情况、索引与节流设计、可维护性四方面分析当前仍存在的缺陷与可改进点。


一、当前状态概览

全系统配对维度改造已基本落地:

  • 类型src/trading/models.pyPairKey = (symbol, base_symbol),单腿/孤儿用 base_symbol=""
  • 策略/仓位/配置:策略引擎、仓位管理器、配置的配对覆盖均按 PairKey"ALT|BASE" 键存取。
  • DBtrading_signalspair_positionsanalysis_results 的索引/压缩已通过 database/migrations/20260219_fix_pairkey_indexes.sql 迁移为 PairKey 维度;symbol_blacklistcointegrated_pairs 表结构本身即配对维度。
  • 实时服务:黑名单/新币冷却/配对关系缓存均使用 (symbol, base_symbol);WebSocket 缓存仍为按币种 key(coin:intervalcoin:l2Book),与交易所数据按币种推送一致,属合理设计。

以下为仍存在的缺陷与不足及建议。


二、缺陷与不足

1. base_symbol 归一化不统一(潜在 Key 分裂)

现象
部分路径用 base_symbol or "",部分直接用 row["base_symbol"] 或参数,若未来出现 None(如 DB 连接器、历史数据)会得到 (sym, None)(sym, "") 两套 key,导致同一逻辑配对被当成两个 key。

位置

  • src/trading/trade_repository.py 第 269 行:get_positions_by_symbols 已用 row.get("base_symbol") or ""
  • 同文件第 292 行:get_known_pair_relations 返回 row["base_symbol"],未做 or ""。若某处返回 None,后续用该 list 做 key 会得到 (sym, None)
  • src/services/realtime_kline_service_base.py 第 1323 行:_load_blacklist_from_db 使用 (row['symbol'], row['base_symbol']),未防御 None

建议
在全系统约定「配对 Key 的 base 为空一律用 ""」。

  • get_known_pair_relations 改为 (row["symbol"], row.get("base_symbol") or "")
  • 黑名单恢复改为 (row['symbol'], row.get('base_symbol') or '')
  • 可选:在 src/trading/strategy.py_params_foron_tick 等入口对 base_symbol 做防御性 base_symbol = base_symbol or "",避免调用方漏传导致 (sym, None)

2. analysis_results 遗留“仅 symbol”索引

现象
database/init_timescaledb.sql 中仍保留:

  • idx_analysis_symbol_time on (symbol, analysis_time DESC)(第 142–143 行)
  • idx_analysis_kline_time on (symbol, kline_time DESC)(第 155–156 行)

而业务查询已按 PairKey 使用 (symbol, base_symbol, ...)(如 src/utils/database/timescaledb.pyquery_avg_zscore_4h、orchestrator 的灌缓冲区 SQL)。
迁移 20260219_fix_pairkey_indexes.sql 只改了 trading_signalspair_positionsanalysis_results压缩,未删除 analysis_results 的旧索引。

影响
写入 analysis_results 时多维护两个 symbol-only 索引,增加写入开销与存储;新库从 init 脚本建库会一直带着这两个索引,与「全系统 PairKey 维度」不一致。

建议

  • 在迁移中或新建迁移中:对 analysis_results 执行 DROP INDEX IF EXISTS idx_analysis_symbol_time;DROP INDEX IF EXISTS idx_analysis_kline_time;(若仍有脚本按 symbol+kline_time 查,需先改为按 PairKey 查并确认无依赖后再删)。
  • 或在文档中明确:查询 analysis_results 一律带 base_symbol,以 PairKey 索引为准,旧索引仅作兼容保留并计划废弃。

3. recent_analysis 节流维度与“配对维度”不一致

现象
src/services/realtime_kline_service_base.pyrecent_analysis 的 key 为 (symbol, timeframe)(第 884、930、946 行)。
即:同一 symbol 在同一 timeframe 下,无论对多少个 base(如 PURR|HYPE、PURR|BTC)只做一次「分析任务」节流,然后在该任务内对多个 base 依次执行 _analyze_and_alert

影响

  • 若期望「按配对维度」节流(例如 PURR|HYPE 与 PURR|BTC 独立节流),当前实现不满足。
  • 若期望「按 symbol+timeframe 只调度一次、再对多 base 展开」以控制 CPU/DB 压力,则当前设计一致,但文档未说明,易被误以为按 pair 节流。

建议

  • realtime_kline_service_base 或相关文档中明确:recent_analysis 是 (symbol, timeframe) 维度的节流,不是 (symbol, base_symbol, timeframe),并说明设计理由(如减少同一 K 线下的重复调度)。
  • 若产品上需要「按配对」节流(例如某配对分析过密则单独限流),则需将 key 改为 (symbol, base_symbol, timeframe) 并评估 QPS/存储影响。

4. 策略层 Key 的防御性归一化

现象
src/trading/strategy.py 中所有使用 key 的地方均为 key = (symbol, base_symbol)(如第 220、273、292、324 行等)。若上游误传 base_symbol=None,会得到 (sym, None),与 position_manager / orchestrator 使用的 (sym, "") 不一致,导致「同一配对」在策略与仓位侧被当作不同 key。

建议
在策略入口做一次统一归一化(不影响现有正确调用方):

  • _params_foron_tickprime_bufferget_adaptive_zis_readycleanup_pair 等对外接口中,将 base_symbol 视为可选并执行 base_symbol = base_symbol or ""(或仅在构造 key 时使用 (symbol, base_symbol or "")),保证策略内部所有 dict/set 的 key 与仓位、orchestrator 一致。

5. 单腿/孤儿仓位的 PairKey 一致性(已满足,仅作确认)

结论
单腿或 base 腿残留转孤儿时,均使用 base_symbol="",且 pair_positionsbase_symbol NOT NULL 存为 ""
position_manager_pair_key、开仓 key、orchestrator 的仓位同步与退出均使用 base_symbol or "",与策略、DB 一致,此处无缺陷


6. WebSocket 缓存为“按币种”的说明

结论
src/utils/websocket/enhanced_ws_manager.py 使用 coin:intervalcoin:l2Book 等按币种缓存,与交易所数据按币种推送一致;配对由「alt 币种 + base 币种」在业务层组合。设计正确,无需改为 pair 维度。
建议在注释或架构文档中简短说明:WS 缓存为 coin 维度,配对维度在应用层用 (symbol, base_symbol) 组合,避免后续误改成 pair key。


三、数据流与 Key 维度小结(便于核对)

flowchart LR
  subgraph ws [WS/数据层]
    CoinKline["K线/L2 按 coin"]
    CoinKline --> App
  end
  subgraph app [应用层 PairKey]
    App["(symbol, base_symbol)"]
    App --> Strategy
    App --> PositionManager
    App --> Blacklist
    App --> RealtimeThrottle["recent_analysis: (symbol, tf)"]
  end
  subgraph db [DB]
    Strategy --> AR["analysis_results"]
    PositionManager --> PP["pair_positions"]
    Blacklist --> SB["symbol_blacklist"]
  end
  • 一致:策略、仓位、黑名单、DB 表与迁移均为 PairKey;WS 为 coin 维度且合理。
  • 待统一:base_symbol 的 None"" 归一化(repo/黑名单加载/策略入口);analysis_results 旧索引的清理或文档说明;recent_analysis 节流维度的文档或改为 pair 维度。

四、建议优先级

优先级 动作
base_symbol 归一化 get_known_pair_relations、_load_blacklist_from_db 使用 or "";策略入口可选防御 (symbol, base_symbol or "")
analysis_results 索引 评估后 DROP 旧 symbol-only 索引,或在文档中标注以 PairKey 索引为准并计划废弃旧索引
recent_analysis 语义 文档明确 (symbol, timeframe) 节流;若需按配对节流则改 key 为 (symbol, base_symbol, timeframe)
文档 说明 WS 缓存为 coin 维度、PairKey 仅在应用层;新贡献者须知「空 base 一律 ""」

按上述顺序处理可进一步消除配对维度优化后的残留不一致与歧义,并避免未来因 None/旧索引/节流语义导致的隐蔽问题。

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