全系统 Key 改为配对维度 (symbol, base_symbol)-设计文档

全系统 Key 改为配对维度 (symbol, base_symbol)

目标

  • 所有“按币种/标的”区分的 key 统一改为配对维度(symbol, base_symbol)
  • 同一 symbol 对多个 base 时:基线、持仓、突破状态、冷却、退场重试等均按配对独立,互不覆盖、语义清晰。
  • 单 base 场景(single 或全局唯一 base):base_symbol 使用 "" 或配置的默认 base,保持兼容。

1. 配对 Key 约定

  • 类型tuple[str, str],即 (symbol, base_symbol)base_symbol 为空时用 ""(single 模式或未指定时)。
  • 辅助:在 src/trading/models.pysrc/utils 中提供:
    • def pair_key(symbol: str, base_symbol: str | None) -> tuple[str, str]
      返回 (symbol, base_symbol or ""),供各处统一生成 key。
    • 若需字符串形式(日志/缓存 key):f"{symbol}|{base_symbol or ''}"
  • 兼容:现有 single 模式或“仅一个 base”时,调用方传入 base_symbol="" 或配置的 base_symbol,行为与“单配对”一致。

2. 策略层 (src/trading/strategy.py)

  • 涉及字典(全部改为以 pair_key(symbol, base_symbol) 为 key):
    • _baselines
    • _prev_above_threshold
    • _positions
    • _last_trade_time
    • _exit_pending(改为 set of pair_key)
    • _signal_history(key 可改为 f"{pair_key}:{direction}:{ts}" 或保留 pair 维度)
    • _last_near_thresh_time
    • _last_status_time
    • _tick_count
    • _last_adaptive_z
  • 接口
    • process_tick(symbol, z4h, timestamp, ..., base_symbol: str | None = None)
      内部 key = pair_key(symbol, base_symbol),所有读写用 key
    • _get_baseline(symbol, base_symbol) → 使用 pair_key(symbol, base_symbol) 查找/创建。
    • is_ready(symbol, base_symbol)get_adaptive_z(symbol, base_symbol) 等增加 base_symbol 参数并改用 pair key。
    • prime_buffer(symbol, base_symbol, z4h_values):按配对灌入历史 z4h;若无 base 维度则 base_symbol=""
    • on_position_opened(symbol, base_symbol, direction, entry_z4h, adaptive_z, ...)on_position_closed(symbol, base_symbol, ...)sync_position(symbol, base_symbol, ...)on_exit_failed(symbol, base_symbol)on_entry_rejected(symbol, base_symbol)clear_symbol(symbol, base_symbol) 等:凡带 symbol 的入口均增加 base_symbol,内部用 pair key。
  • PositionTracker:可增加 base_symbol: str 字段便于日志与告警,key 仍为 pair。
  • 策略参数_params_for(symbol) 若当前支持按 symbol 覆盖,可保留仅 symbol 的 overrides,或扩展为 _params_for(symbol, base_symbol)(按需)。

3. 仓位管理层 (src/trading/position_manager.py)

  • 内存结构_positions: dict[tuple[str, str], PairPosition],key = (symbol, base_symbol)
  • 开仓open_position(signal) 中,key = (signal.symbol, signal.base_symbol or "")self._positions[key] = position
  • 平仓 / 查询:所有原先 _positions.get(symbol)_positions.pop(symbol) 改为按 (symbol, base_symbol) 查找;对外接口需同时接受 symbol + base_symbol(或传入 PairPosition 取其二)。
    • 例如:close_position(symbol, base_symbol, signal, reason, ...)close_position(position) 内部用 (position.symbol, position.base_symbol) 作 key。
  • open_positions:保持返回 list[PairPosition] 即可(每个 position 已有 symbol、base_symbol)。
  • 恢复/对账:从 DB 读出的每行 (symbol, base_symbol, ...) 转为 key = (row["symbol"], row.get("base_symbol") or ""),再 _positions[key] = position;避免按 symbol 覆盖。
  • 孤儿收纳_adopt_paired_orphans 等处写入 _positions 时使用 (position.symbol, position.base_symbol) 为 key。
  • sync_with_exchangerecover:遍历 _positions.items() 时 key 为 pair,value 为 PairPosition;需要“按 symbol 列出某 symbol 下所有仓位”时,用列表推导按 pos.symbol == symbol 过滤即可。

4. 仓储层 (src/trading/trade_repository.py)

  • get_positions_by_symbols(symbols):改为 get_positions_by_pairs(pairs: list[tuple[str, str]]) 或保留原名但语义改为“按配对查询”:
    • SQL:WHERE (symbol, base_symbol) = ANY(%s)WHERE (symbol, base_symbol) IN (...),参数为 [(s, b) for (s, b) in pairs]
    • 返回:dict[tuple[str, str], dict],即 {(row["symbol"], row.get("base_symbol") or ""): row for row in rows},这样同一 symbol 不同 base 不会互相覆盖。
  • 其他:若还有按 symbol 查仓位的方法,改为按 (symbol, base_symbol) 或返回 list 由调用方按 pair 建 dict。
  • get_known_pair_relations:当前返回 {alt_symbol: base_symbol},一对多时会丢信息;可改为 list[tuple[str, str]]{(alt, base): True},供孤儿收纳等使用。需与 position_manager 的孤儿逻辑一起看。

5. 编排器 (src/trading/orchestrator.py)

  • process_analysis:已有 symbolmulti_period_result.get("base_symbol"),调用策略时始终传入 base_symbol(可为 ""):
    • self._strategy.process_tick(symbol, z4h, timestamp, ..., base_symbol=multi_period_result.get("base_symbol") or "")
  • 退场on_exit_signal(reversion_info)reversion_info 已含 symbolbase_symbol;查找要平的仓位时用 (reversion_info.symbol, reversion_info.base_symbol) 在 position_manager 中查找。
  • 入场on_entry_signal 成功后 on_position_opened(symbol, base_symbol, direction, ...)sync_position 时对每个 pospos.symbol, pos.base_symbol
  • 启动时灌历史 z4h:若 DB 的 analysis_results 按 (symbol, base_symbol) 存,则按配对查询并灌入:
    • 先得到“待交易配对”列表(可从配置或 cointegrated_pairs 等来源);
    • 对每个 (sym, base_sym) 查询 WHERE symbol = %s AND base_symbol = %s ... zscore_4h,再 prime_buffer(sym, base_sym, z4h_values)
  • “是否有该 symbol 下任意持仓”:若仍需用于黑名单豁免等,可提供 has_open_position_for_symbol(symbol):在 position_manager 中判断是否存在任意 pos.symbol == symbol退场/策略状态仍严格按 pair 判断。

6. 服务层 (src/services/realtime_kline_service_base.py)

  • _has_open_position:改为 _(symbol, base_symbol)(或保留 _has_open_position(symbol, base_symbol=None),若传入 base_symbol 则按配对查,否则按 symbol 是否存在任意持仓)。
    • 实现:问 position_manager 是否有 (symbol, base_symbol) 的仓位;若接口是 has_position(symbol, base_symbol) 则直接调。
  • _trigger_strategy_if_ready:已传 base_symbol=base_sym,保证 process_analysis(..., multi_period_result=...) 里能拿到 base_symbol 并一路传到 strategy.process_tick。
  • 黑名单、配对缓存:已是 (symbol, base_symbol),无需改 key;仅需保证“有持仓”判断与 pair 一致(例如某 symbol 对 base A 有仓位,则仅对 (symbol, A) 豁免拉黑,不影响 (symbol, B))。

7. 数据库与历史数据

  • pair_positions:表已有 symbolbase_symbol,无需改表结构;唯一约束若有需要可加 UNIQUE(symbol, base_symbol) 在 (open/opening/closing) 维度,防止同一配对重复开仓(按业务决定是否必要)。
  • analysis_results:已有 symbolbase_symbol;灌 buffer 的 SQL 改为 WHERE symbol = %s AND base_symbol = %s AND zscore_4h IS NOT NULL ...,按配对取历史 z4h。
  • symbol_blacklist:已是 (symbol, base_symbol),无需改。

8. 其他调用点

  • risk_manager:若存在按 pos.symbol == signal.symbol 的判断,改为同时比较 base_symbol,或改为按 pair 查找仓位。
  • executor:执行层主要用 signal.symbolsignal.base_symbolposition.symbolposition.base_symbol,不直接维护 dict key;只需保证传入的 position/signal 来自“按 pair 查到的”即可。
  • 告警/格式化:已带 symbol、base_symbol,无需改 key,仅保证数据源来自按 pair 的仓位与信号。

9. 实施顺序建议

  1. 模型与工具:增加 pair_key(symbol, base_symbol) 及(可选)字符串形式,统一放在一处(如 models.pytrading/utils.py)。
  2. 策略层:先改 _baselines_positionsprocess_tick 的 key 与参数,再改其余字典与对外接口(prime_buffer、sync_position、on_position_opened 等)。
  3. 仓储层get_positions_by_symbolsget_positions_by_pairs 及返回 dict[(symbol, base_symbol), row],并调整调用方(position_manager)。
  4. 仓位管理层_positions 改为 pair key,所有 get/pop/赋值与恢复、对账、孤儿收纳改为按 pair。
  5. 编排器:传入/使用 base_symbol,灌 buffer 按配对查 DB,退场/入场/同步均按 pair。
  6. 服务层_has_open_position(symbol, base_symbol) 及与 position_manager 的接口对齐。
  7. 回归:单 base / single 模式用 base_symbol="" 或默认 base 跑通;多 base 场景下同一 symbol 两配对基线与持仓互不干扰。

10. 风险与注意点

  • 向后兼容:若已有未带 base_symbol 的仓位(DB 中 base_symbol 为空),加载时统一为 (symbol, ""),与 single 模式一致。
  • 配置:若存在“按 symbol 禁用平仓/关闭”等,需明确是“该 symbol 下所有配对”还是“仅某配对”;通常按配对更清晰。
  • 日志与监控:所有按 pair 的 key 在日志中建议打印为 symbol vs 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