这页不发明新规则,也不重写旧研究;它只做一件事:把现有 Rank32B 还原成 最小 baseline + 若干可检验增量,并把 alpha 本体 和 live 部署层 分开。
页面生成时间:2026-05-13 06:03:44 北京时间 / 2026-05-12 22:03:44 UTC
spread-mid reclaim),这页会把它视为 已删除历史层,而不是继续当核心规则。Rank32B 的母题是:
先用 1h EMA 定结构方向,再只追那些 15m close 重新穿回 fast EMA、而且 EMA slope 已经明显同向展开的 continuation。
翻成人话:不是“看到均线就追”,而是“方向先对、回穿先确认、斜率还得够强”。
ema_fast_1h > ema_slow_1h 才允许 long;ema_fast_1h < ema_slow_1h 才允许 short。prev_close <= prev_fast 且 close > ema_fast_1h;short 镜像。slope floor、strongest-only、official-close freshness veto、并发限制、tiered universe、ATR TP/SL/timeout。为了让 ablation 可跑、可对照,这页把研究执行壳固定为 signal close → next-bar open → non-overlap → hold 8 bars。但这层只是实验载体,不算 Rank32B 的 alpha 主张。
EMA_FAST_1H = 20。EMA_SLOW_1H = 50。close 形成 higher-tf 序列,再在这条 1h 序列上算 EMA;然后再把结果回填到 15m 决策行。prev15_close。merge_asof(backward) 回填到 15m,所以同一个小时里的多根 15m 可能拿到同一个 ema_fast_1h;此时 prev_fast = frame["ema_fast_1h"].shift(1) 的确可能和当前 ema_fast_1h 一样。src/momentum/execution/canary32b/signal_adapter.py)不是这么做的:它先拿上一已完成小时的 prev_hour_fast,再用当前这根 15m 的 close 递推当前的 ema_fast_1h;上一根则单独取 prev15_fast。所以在 live 里,prev15_fast 和当前 ema_fast_1h 通常不会一样,除非价格刚好让递推结果几乎不变。| 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_fast 且 close > 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 等约束。
下面这块专门对应 src/momentum/execution/canary32b/signal_adapter.py 的 live 口径,不再混用简化回测。读法只有三步:
prev_hour_fast / prev_hour_slow。ema_fast_1h / ema_slow_1h。prev15_fast 不是“上一小时的 fast”,而是上一根已完成 15m 决策 bar 当时算出来的 fast。prev15_fast 只用于比较,不会带未来 15m。| 已完成小时 close | hour_close | prev_hour_fast | prev_hour_slow |
|---|---|---|---|
| 09:00 | 98.60 | 98.6000 | 98.6000 |
| 10:00 | 99.40 | 98.6762 | 98.6314 |
| 11:00 | 100.10 | 98.8118 | 98.6890 |
| 12:00 | 99.80 | 98.9059 | 98.7325 |
这一步只用已经结束的小时。它的作用不是直接发信号,而是生成下一批 15m bar 会共用的 hour-level EMA 锚点。
| 15m close | prev15_close | prev15_fast | close | prev_hour_fast | ema_fast_1h(now) | ema_slow_1h(now) | 读法 |
|---|---|---|---|---|---|---|---|
| 12:15 | - | - | 99.30 | 98.9059 | 98.9434 | 98.7548 | 当前 bar 只能用上一已完成小时的 EMA 锚点 + 当前 15m close 递推 |
| 12:30 | 99.30 | 98.9434 | 99.55 | 98.9059 | 98.9672 | 98.7646 | 上一根 15m 的 close / fast 只作为比较对象,不会把未来 15m 带进来 |
| 12:45 | 99.55 | 98.9672 | 99.95 | 98.9059 | 99.0053 | 98.7803 | 上一根 15m 的 close / fast 只作为比较对象,不会把未来 15m 带进来 |
重点看两列:prev_hour_fast 在这一组 15m bar 里是固定锚点;prev15_fast 则是一根一根往前滚的“上一根 15m fast”。所以 current live 里它通常和当前 ema_fast_1h(now) 不一样。
这张表只回答一个问题:每一根 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:00 | H1 在这一刻完成 | K4.close 会成为 H1.hour_close | - | - | K1~K4 共同形成第一个完整小时 H1 |
| K5 | [01:00,01:15) | 01:15 | fast(H1), slow(H1) | K5.close + prev_hour_fast(H1) | 通常先不强调 | K1~K4 | 这是第一根真正使用 H1 锚点递推的 15m bar |
| K6 | [01:15,01:30) | 01:30 | fast(H1), slow(H1) | K6.close + prev_hour_fast(H1) | fast(K5) | K1~K4 | K6 真正在比较:上一根 15m 的 fast vs 当前这根 15m 递推出来的 fast |
| K7 | [01:30,01:45) | 01:45 | fast(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~K4 | K8 自己算完的同时,K5~K8 也凑齐了 H2;下一根开始换锚点 |
| K9 | [02:00,02:15) | 02:15 | fast(H2), slow(H2) | K9.close + prev_hour_fast(H2) | fast(K8) | K5~K8 | 这是换锚点后的第一根 15m bar;从这里起 hour 锚点改成 H2 |
fast(H1) 上。K6.close + fast(H1),K7 用 K7.close + fast(H1),所以 K6 的 prev15_fast = fast(K5) 通常不等于 K6 当前的 ema_fast_1h(now)。aligned slope floor,只留明显同向展开的 continuation。
same-bar strongest-only,同窗只留最强币。
|fast slope| 过最小门槛,避免把很平、很弱的结构也认成 continuation。slope_strength 最强的那个。TP + SL + timeout 的风险闭环,把 live 退出从研究壳推进到实盘可执行。现有 32b 页面里,没有看到一个像“牛市/熊市开关”那样明确的市场状态型 regime gate;这层更像 execution veto,不是新的 alpha 母题。
trade_enabled、API、行情延迟、ATR、状态同步都正常时放行。EMA cross + aligned slope floor 外推到更多主流币,验证 edge 不是只在 core3 站住。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 only 与 freshness gate:都在做 entry hygiene,只是一个防未收盘噪音,一个防过期信号。strongest-only、max_new_signals_per_run、max_concurrent_positions:都在压缩暴露,目标高度相近。same-symbol single-position 与 cross-lane conflict veto:都在防重复暴露,只是一个 lane 内,一个 lane 间。fixed hold 8 bars 与 ATR OCO exit:这是两套互相竞争的 exit 家族,不该同时当作独立增量往上堆。建议先把研究执行壳固定为:official 15m close / next-bar open / non-overlap / hold 8 bars。先只动一个组件轴,避免把“信号质量”与“部署层收益实现”搅在一起。
baseline only
只保留 ema_cross_only,core3。
baseline + aligned slope floor
先钉死 32b 最核心增量到底是不是这刀。
baseline + strongest-only
不加 slope floor,单测 selection 有没有独立价值。
baseline + aligned slope floor + strongest-only
看核心 entry 增量和组合选择能不能叠加。
Exp2 + cross-asset expansion
从 core3 扩到更宽 universe,测 edge 是否能外推。
Exp4 + cross-asset expansion
看“强 entry + 组合选择 + 扩池”是不是当前主线雏形。
Exp6 + risk veto pack
加 same-symbol / max-concurrent / cross-lane,测组合约束值不值。
Exp6 + ATR OCO exit
单测 live exit 家族到底给了什么,而不是把它混进 entry 归因里。
aligned slope floor。现有 clean replication 证据最直接支持这件事:删掉 reclaim 后 pocket 没塌,真正站住的更像就是这层 slope 约束。
ATR OCO exit。这里的意思不是它对部署没价值,而是:如果目标是解释 32b 的 alpha 母体,它更像部署/风控组件,不像第一层 edge 来源。
先只做 Exp1 vs Exp2:ema_cross_only 对 ema_cross_only + aligned slope floor。先把“edge 到底是不是 slope floor 提供的”钉死,再去讨论 strongest-only、扩池、ATR exit。
baseline = ema_cross_only、Rank32B = ema_cross_plus_slope_floor,并明确说明已经删除 spread-mid reclaim。如果以后 32b 改版,这页最该跟着更新的不是措辞,而是这条分层:baseline / core alpha / selection / live hygiene / exit / universe。
说明:这是一页解释型文档,不替代 Dashboard、透明页或研究页;它的价值在于减少“页面都看过,但还是说不清 32b 到底由哪几层组成”的沟通成本。