32b baseline → components → ablation 研究母体 vs live 叠加层 reader-facing decomposition

Rank32B 结构拆解页

这页不发明新规则,也不重写旧研究;它只做一件事:把现有 Rank32B 还原成 最小 baseline + 若干可检验增量,并把 alpha 本体live 部署层 分开。

页面生成时间:2026-05-13 06:03:44 北京时间 / 2026-05-12 22:03:44 UTC

这页的边界

  • 只使用现有 32b 页面已经明示过的规则与口径。
  • 如果某条规则只属于 live execution,不把它硬塞进 baseline alpha。
  • 如果某条规则只是研究壳(例如固定持有 8 根 15m bar),会明确标注为 实验载体,不是母体 edge 主张。
  • 如果某条旧文案已经被 32b 当前主线删掉(例如 spread-mid reclaim),这页会把它视为 已删除历史层,而不是继续当核心规则。

一句话结论

Rank32B 的母题是:
先用 1h EMA 定结构方向,再只追那些 15m close 重新穿回 fast EMA、而且 EMA slope 已经明显同向展开的 continuation。

翻成人话:不是“看到均线就追”,而是“方向先对、回穿先确认、斜率还得够强”。

最小 baseline

  • 方向定义ema_fast_1h > ema_slow_1h 才允许 long;ema_fast_1h < ema_slow_1h 才允许 short。
  • 触发定义:long 为 prev_close <= prev_fastclose > ema_fast_1h;short 镜像。
  • baseline 不包含slope floorstrongest-only、official-close freshness veto、并发限制、tiered universe、ATR TP/SL/timeout。
研究壳说明

为了让 ablation 可跑、可对照,这页把研究执行壳固定为 signal close → next-bar open → non-overlap → hold 8 bars。但这层只是实验载体,不算 Rank32B 的 alpha 主张。

术语与公式:先把 fast / slow / previous fast 说清楚

  • EMA fast:不是“更短周期图”,而是 同样基于 1h close 算出来的较快均线。在 clean replication 脚本里,它是 EMA_FAST_1H = 20
  • EMA slow:同样基于 1h close 算出来的较慢均线。在 clean replication 脚本里,它是 EMA_SLOW_1H = 50
  • 1h 的意思:先把价格序列按 1 小时聚合,用每个 1h bar 的 close 形成 higher-tf 序列,再在这条 1h 序列上算 EMA;然后再把结果回填到 15m 决策行。
  • previous fast / prev_fast:广义上就是“上一根决策 bar 看到的 fast EMA 值”。但具体实现要分 clean research 和 current live
  • previous close / prev_close:同理,就是上一根决策 bar 的收盘价;在 live 口径里通常写成 prev15_close
EMA 递推公式
EMA_t = α · Price_t + (1 - α) · EMA_(t-1)
α = 2 / (N + 1)
所以在 32b 里:
ema_fast_1h = EMA(close_1h, N=20)
ema_slow_1h = EMA(close_1h, N=50)
fast_slope = ema_fast_1h.pct_change()
slow_slope = ema_slow_1h.pct_change()
baseline long 触发公式
long_structure = (ema_fast_1h > ema_slow_1h)
cross_only_long = long_structure ∧ (prev_close <= prev_fast) ∧ (close > ema_fast_1h)
直白说:上一根 15m 收盘还在 fast EMA 下方或贴着它,这一根 15m 收盘重新站回 fast EMA 上方;同时 higher-tf 结构已经是 fast 在 slow 上方。
这里要订正:current live 的定义更精确
clean replication 里,常见写法是先算完已收盘 1h EMA,再 merge_asof(backward) 回填到 15m,所以同一个小时里的多根 15m 可能拿到同一个 ema_fast_1h;此时 prev_fast = frame["ema_fast_1h"].shift(1) 的确可能和当前 ema_fast_1h 一样。
current live source-of-truthsrc/momentum/execution/canary32b/signal_adapter.py)不是这么做的:它先拿上一已完成小时的 prev_hour_fast,再用当前这根 15m 的 close 递推当前的 ema_fast_1h;上一根则单独取 prev15_fast。所以在 live 里,prev15_fast 和当前 ema_fast_1h 通常不会一样,除非价格刚好让递推结果几乎不变。

示例数据:current live 里 prev15_fast 到底是什么意思

15m bar prev_close prev15_fast close ema_fast_1h ema_slow_1h 读法
t-1 - - 99.8 100.0 98.7 结构已经偏多(fast > slow),但这根 15m close 还在 fast 下方。
t 99.8 100.0 100.6 100.2 98.7 这一根满足 prev15_close <= prev15_fastclose > ema_fast_1h,所以这是一次 long cross。
t+1 100.6 100.2 100.9 100.3 98.7 虽然价格还在 fast 上方,但因为上一根 close 已经在上方,prev15_close <= prev15_fast 不再成立,所以不会连续重复记成新 cross。

这个表只是解释变量含义,不代表真实 market sample;真正的 32b 还会在 baseline 之上继续叠加 aligned slope floor,而 live 层还会再叠加 strongest-only、freshness、risk veto 等约束。

只看 current live:warmup → prev_hour_fast/slow → prev15_fast 的可视化

下面这块专门对应 src/momentum/execution/canary32b/signal_adapter.py 的 live 口径,不再混用简化回测。读法只有三步:

current live 核心公式
ema_fast_1h(now) = α_fast · close_15m(now) + (1-α_fast) · prev_hour_fast
ema_slow_1h(now) = α_slow · close_15m(now) + (1-α_slow) · prev_hour_slow
prev15_fast = ema_fast_1h(previous completed 15m bar)
一眼看懂这张图
灰色块 = 更早的 15m 历史;金色块 = 每个已完成小时的 hour close,会进入 warmup / prev_hour_fast 计算;绿色块 = 当前关注的连续 15m 决策 bar;蓝色箭头 = 用上一已完成小时的 EMA 锚点去递推当前 fast/slow;橙色箭头 = 上一根 15m 算出来的 prev15_fast 只用于比较,不会带未来 15m。
current live EMA 计算时间轴(示例) 重点:先 warmup 出上一已完成小时的 EMA 状态,再用当前 15m close 递推;prev15_fast 来自上一根 15m,而不是“静态回填的一小时值”。 11:15历史15m 11:30历史15m 11:45历史15m 12:00hour close 12:15决策bar 12:30决策bar 12:45决策bar 13:00边界/换锚点 这根 12:00 作为上一已完成小时的收盘,会先进入 warmup,得到 prev_hour_fast / prev_hour_slow warmup 输出 prev_hour_fast / prev_hour_slow 这里先只画同一个上一小时锚点下的 12:15 / 12:30 / 12:45 三根 15m;跨到下一小时时会重取新的 prev_hour_fast/slow 当前 bar 的 EMA ema_fast_1h(now), ema_slow_1h(now) = f(prev_hour_fast/slow, close_15m(now)) prev15_fast 来自上一根 15m 决策 bar 的 fast

Step A · warmup:先把很多根 15m 拼成已完成小时

已完成小时 closehour_closeprev_hour_fastprev_hour_slow
09:0098.6098.600098.6000
10:0099.4098.676298.6314
11:00100.1098.811898.6890
12:0099.8098.905998.7325

这一步只用已经结束的小时。它的作用不是直接发信号,而是生成下一批 15m bar 会共用的 hour-level EMA 锚点。

Step B · 当前关注的连续 15m bar

15m closeprev15_closeprev15_fastcloseprev_hour_fastema_fast_1h(now)ema_slow_1h(now)读法
12:15--99.3098.905998.943498.7548当前 bar 只能用上一已完成小时的 EMA 锚点 + 当前 15m close 递推
12:3099.3098.943499.5598.905998.967298.7646上一根 15m 的 close / fast 只作为比较对象,不会把未来 15m 带进来
12:4599.5598.967299.9598.905999.005398.7803上一根 15m 的 close / fast 只作为比较对象,不会把未来 15m 带进来

重点看两列:prev_hour_fast 在这一组 15m bar 里是固定锚点;prev15_fast 则是一根一根往前滚的“上一根 15m fast”。所以 current live 里它通常和当前 ema_fast_1h(now) 不一样。

按第几根 15m K 线数:K1 到 K9 逐根计数表

这张表只回答一个问题:每一根 K 线在收盘时,到底用了谁的数据? 记法固定如下:K1 = [00:00, 00:15) 在 00:15 收盘;K4 = [00:45, 01:00) 在 01:00 收盘,因此 K1~K4 合起来形成第一个完整小时 H1。

K线 时间段 收盘时刻 当前可用的 hour 锚点 当前 fast 直接用了谁 prev15_fast 来自谁 hour 锚点来自哪几根 15m 一句话说明
K1[00:00,00:15)00:15还没形成完整 1h只拿到 K1 自己的 close;还不能有稳定 hour 锚点--只是攒小时,不应该拿未来 01:00 的小时结果回填
K2[00:15,00:30)00:30还没形成完整 1h只拿到 K2 自己的 close;还不能有稳定 hour 锚点--仍在攒首个完整小时
K3[00:30,00:45)00:45还没形成完整 1h只拿到 K3 自己的 close;还不能有稳定 hour 锚点--仍在攒首个完整小时
K4[00:45,01:00)01:00H1 在这一刻完成K4.close 会成为 H1.hour_close--K1~K4 共同形成第一个完整小时 H1
K5[01:00,01:15)01:15fast(H1), slow(H1)K5.close + prev_hour_fast(H1)通常先不强调K1~K4这是第一根真正使用 H1 锚点递推的 15m bar
K6[01:15,01:30)01:30fast(H1), slow(H1)K6.close + prev_hour_fast(H1)fast(K5)K1~K4K6 真正在比较:上一根 15m 的 fast vs 当前这根 15m 递推出来的 fast
K7[01:30,01:45)01:45fast(H1), slow(H1)K7.close + prev_hour_fast(H1)fast(K6)K1~K4和 K6 一样,hour 锚点不变,但 prev15_fast 会滚动
K8[01:45,02:00)02:00仍然用 fast(H1), slow(H1)K8.close + prev_hour_fast(H1)fast(K7)K1~K4K8 自己算完的同时,K5~K8 也凑齐了 H2;下一根开始换锚点
K9[02:00,02:15)02:15fast(H2), slow(H2)K9.close + prev_hour_fast(H2)fast(K8)K5~K8这是换锚点后的第一根 15m bar;从这里起 hour 锚点改成 H2
把这张表读成两句话就够了
1)同一小时里固定的是 hour 锚点:比如 K5/K6/K7/K8 都挂在同一个 fast(H1) 上。
2)每一根 15m 都会重新算自己的当前 fast:K6 用 K6.close + fast(H1),K7 用 K7.close + fast(H1),所以 K6 的 prev15_fast = fast(K5) 通常不等于 K6 当前的 ema_fast_1h(now)

把 baseline 推成 Rank32B 的结构树

Layer 0 · baseline 1h EMA 定方向 + 15m close 重新穿回 fast EMA。
Layer 1 · 核心 alpha 增量aligned slope floor,只留明显同向展开的 continuation。
Layer 2 · 组合选择层same-bar strongest-only,同窗只留最强币。
Layer 3 · live 执行卫生层 official-close only、freshness、same-symbol / cross-lane veto、并发限制。
Layer 4 · 部署层 ATR OCO exit、timeout、下单与状态同步。
Layer 5 · universe 层 core3 → 扩池 → admission / whitelist / tiering。

① entry filters

aligned slope floor

核心增量
理论作用:
要求 fast / slow EMA slope 同向,且 |fast slope| 过最小门槛,避免把很平、很弱的结构也认成 continuation。
它试图解决 baseline 的什么缺陷:
baseline 只知道“重新穿回 fast EMA”,却分不清这次回穿发生在强趋势里,还是发生在弱震荡里。
预期改善指标:
减少假突破、提高胜率、降低无效 churn、改善成本后表现。

official-close only

执行一致性层
理论作用:
只接受 15m official close 确认后的信号,不把 preview / 盘中碰一下当成真正 continuation。
它试图解决 baseline 的什么缺陷:
baseline 如果被 live 误实现,容易把未收盘噪音混成交易信号。
预期改善指标:
减少假信号、降低 live / shadow 偏差、提高可复现性。

② selection filters

same-bar strongest-only

组合层关键一刀
理论作用:
多个币在同一 timestamp 同时出信号时,只保留 slope_strength 最强的那个。
它试图解决 baseline 的什么缺陷:
baseline 默认会把一篮子相关币一起收进来,导致最强 continuation 被弱信号稀释,也把组合变成同质化暴露。
预期改善指标:
提高平均单笔质量、减少同窗重复暴露、降低换手与拥挤、改善组合 tail。

③ exit rules

fixed hold 8×15m

研究壳
理论作用:
给 baseline 一个最朴素、最低自由度的兑现方式,让 entry ablation 能在统一口径下比较。
它试图解决 baseline 的什么缺陷:
baseline 只有 entry,没有可对照的 exit 壳。
预期改善指标:
提高可解释性、降低过拟合风险、让不同 entry 版本能在同一执行口径下对比。

ATR OCO exit(TP / SL / timeout)

部署层
理论作用:
入场后立刻形成 TP + SL + timeout 的风险闭环,把 live 退出从研究壳推进到实盘可执行。
它试图解决 baseline 的什么缺陷:
fixed hold 对 live 过于粗糙:不会提早兑现好单,也不会更快切掉坏单,还容易占用仓位。
预期改善指标:
降低回撤、改善尾部、缩短平均持仓、提高 live 可部署性。

④ risk veto / regime veto

现有 32b 页面里,没有看到一个像“牛市/熊市开关”那样明确的市场状态型 regime gate;这层更像 execution veto,不是新的 alpha 母题。

signal freshness gate

卫生条件
理论作用:
即便会扫描较长窗口,真正进入交易决策的信号也必须足够新,不允许历史 backlog 被误下成当前单。
它试图解决 baseline 的什么缺陷:
baseline/backfill 风格实现容易把旧信号混进 live 执行。
预期改善指标:
减少 stale fill、减少 live/backtest 偏差、提高事件归因正确性。

same-symbol single-position

风险约束
理论作用:
同一 symbol 已有 live / pending 仓位时,不再重复叠仓。
它试图解决 baseline 的什么缺陷:
baseline 在连续重复触发时,可能把同一标的不断加码,导致暴露失真。
预期改善指标:
降低单标的尾部风险、减少重复暴露、提高组合可控性。

max_concurrent_positions / max_new_signals_per_run

容量约束
理论作用:
限制同一时刻总仓位数,以及单轮 run 最多新开多少个仓。
它试图解决 baseline 的什么缺陷:
baseline 在宽 universe 下可能从“抓最强 continuation”滑成“批量扫信号”。
预期改善指标:
降低拥挤、控制保证金占用、约束组合 tail risk。

cross-lane conflict veto

账户层约束
理论作用:
如果别的 lane 已经占了某个 symbol,32b 当前 lane 直接跳过。
它试图解决 baseline 的什么缺陷:
baseline 不知道账户里别的策略已经持有同一标的,容易跨策略重复暴露。
预期改善指标:
降低跨系统重复风险、提高全账户风险一致性。

execution health gates

基础设施层
理论作用:
只在 trade_enabled、API、行情延迟、ATR、状态同步都正常时放行。
它试图解决 baseline 的什么缺陷:
baseline 假设世界永远正常,但 live 世界里 data delay、API 故障、缺指标都是实实在在的问题。
预期改善指标:
降低事故率、提高 live 可靠性、减少伪交易与错误归因。

⑤ symbol / universe constraints

core3 universe(BTC / ETH / SOL)

研究起点
理论作用:
先在最清楚、最液、最容易解释的三条腿上验证母体 alpha。
它试图解决 baseline 的什么缺陷:
如果一开始就上宽 universe,很难区分“alpha 真的对”还是“扩池碰巧更好看”。
预期改善指标:
提高解释性、降低微结构噪音、减少样本异质性。

cross-asset expansion

外推验证
理论作用:
EMA cross + aligned slope floor 外推到更多主流币,验证 edge 不是只在 core3 站住。
它试图解决 baseline 的什么缺陷:
core3 的最大问题是:它可能只是三条腿特例,而不是真正可扩展的 rotation alpha。
预期改善指标:
提高 trade density、增加机会覆盖、验证 edge 是否可外推。

tiered admission / whitelist

质量控制层
理论作用:
不是“能做的都做”,而是按流动性、长窗稳定性、盘口质量把币分层放行。
它试图解决 baseline 的什么缺陷:
baseline 扩池后容易把“回测看着行、实盘口子不友好”的币也一并带进来。
预期改善指标:
降低滑点/深度风险、提高 live 可复制性、减少 universe 噪音。

哪些组件彼此独立,哪些高度重叠

看起来较独立的

  • aligned slope floor vs ATR OCO exit:一个管 entry 质量,一个管 exit 风险闭环。
  • same-bar strongest-only vs tiered admission:一个管同窗谁最强,一个管哪些币有资格入池。
  • cross-asset expansion vs signal freshness:一个扩机会池,一个防 stale 执行。

看起来高度重叠的

  • official-close onlyfreshness gate:都在做 entry hygiene,只是一个防未收盘噪音,一个防过期信号。
  • strongest-onlymax_new_signals_per_runmax_concurrent_positions:都在压缩暴露,目标高度相近。
  • same-symbol single-positioncross-lane conflict veto:都在防重复暴露,只是一个 lane 内,一个 lane 间。
  • fixed hold 8 barsATR OCO exit:这是两套互相竞争的 exit 家族,不该同时当作独立增量往上堆。

最小 ablation 实验矩阵

建议先把研究执行壳固定为:official 15m close / next-bar open / non-overlap / hold 8 bars。先只动一个组件轴,避免把“信号质量”与“部署层收益实现”搅在一起。

Exp1

baseline only

只保留 ema_cross_only,core3。

Exp2

baseline + aligned slope floor

先钉死 32b 最核心增量到底是不是这刀。

Exp3

baseline + strongest-only

不加 slope floor,单测 selection 有没有独立价值。

Exp4

baseline + aligned slope floor + strongest-only

看核心 entry 增量和组合选择能不能叠加。

Exp5

Exp2 + cross-asset expansion

从 core3 扩到更宽 universe,测 edge 是否能外推。

Exp6

Exp4 + cross-asset expansion

看“强 entry + 组合选择 + 扩池”是不是当前主线雏形。

Exp7

Exp6 + risk veto pack

same-symbol / max-concurrent / cross-lane,测组合约束值不值。

Exp8

Exp6 + ATR OCO exit

单测 live exit 家族到底给了什么,而不是把它混进 entry 归因里。

最后 3 个判断

最值得优先验证的 1 个组件

aligned slope floor。现有 clean replication 证据最直接支持这件事:删掉 reclaim 后 pocket 没塌,真正站住的更像就是这层 slope 约束。

最可能只是制造复杂度的 1 个组件

ATR OCO exit。这里的意思不是它对部署没价值,而是:如果目标是解释 32b 的 alpha 母体,它更像部署/风控组件,不像第一层 edge 来源。

下一步最该做的唯一动作

先只做 Exp1 vs Exp2ema_cross_onlyema_cross_only + aligned slope floor。先把“edge 到底是不是 slope floor 提供的”钉死,再去讨论 strongest-only、扩池、ATR exit。

这页依赖的 source-of-truth 页面

如果以后 32b 改版,这页最该跟着更新的不是措辞,而是这条分层:baseline / core alpha / selection / live hygiene / exit / universe

说明:这是一页解释型文档,不替代 Dashboard、透明页或研究页;它的价值在于减少“页面都看过,但还是说不清 32b 到底由哪几层组成”的沟通成本。