Files
Chan/research/HANDOFF.md
T
jackyu66gitandCursor 27a4360ce8 「有前序信号」通过样本外验证:6/6 时段、4/4 ATR 分层全部同向
step48 那条唯一可交易的线索(开仓时过去 5 分钟内已有别的币发过信号,
则滑点余量更高)用更长历史验证。10 币 × 80 万根,2025-02 ~ 2026-08 共
3941 笔,发现期 1161 笔、样本外 2780 笔。

  样本外 无前序 2326 笔  毛R 1.086  PF 3.91  余量 18.83bp
  样本外 有前序  454 笔  毛R 1.275  PF 4.60  余量 24.89bp

逐时段 6/6 全部同向,余量差中位 8.03bp。发现期毛R 差只有 0.085,样本外
放大到 0.189——不是过拟合衰减,是发现期恰好偏保守。占比各时段 13~19%,很稳。

ATR 混淆已排除:有前序的 ATR 确实略高(中位 15.04 vs 13.13bp),但按四分位
分层后 4/4 层同向,层内余量差 3.29/8.39/5.16/4.14bp,与不分层的 +6.06 同
量级。毛R 本身是 ATR 归一化指标,其 +0.19 不可能是 ATR 假象。

可用方式:这 16% 的信号多容忍约 6bp 执行成本,可加仓位权重,或对这批放宽
ATR 门控(最低 ATR 层里有前序余量仍有 14.92bp vs 对照 11.63)。放宽门控尚未
回测,先别改。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 04:36:39 +08:00

95 KiB
Raw Blame History

缠论信号研究 → 实盘落地:交接文档

最后更新:2026-08-27。写给接手这项工作的下一个 agent。 读完这份文档应该不需要再翻聊天记录。若确有需要,历史转录在 /Users/jack/.cursor/projects/Users-jack-Project-chan/agent-transcripts/


0. 一句话现状

策略在回测和多重偏差审计下都站得住(跨 11 个币、7 年、多空对称、无未来函数), 研究阶段基本结束;当前唯一的拦路问题是「实盘执行成本能否压进预算」, 下一步是写影子交易器实测滑点,而不是继续调参。

用户明确要求:不要再跑新的参数优化。 他的原话是「很多时候回测数据特别好, 一到 dry run 和实盘就歇菜了」。他要的是执行层的验证。


1. 策略的确切定义

这是全文最重要的一节。所有回测数字都基于以下这套口径,改任何一条数字就不可比。

1.1 信号生成(三层)

第一层  小级别(LTF) 自身的中枢         build_htf_zones(cdf, ltf, chan=chan_l)
第二层  中枢突破后回抽不回,收盘转强 → 入场   find_fast_bsp3(cdf, zones)
第三层  大级别(HTF) 分型方向必须同向        attach_htf_context(...) 后取 h1_agree == 1
可选    中枢阶梯方向过滤(顺向推进)        z_above / z_below,见 1.4

用户对「区间套」的定义(务必按这个理解,早期我理解错过): 大级别(1h/4h)分型定位转折点 + 小级别(15m/5m/1m)中枢突破形成第三类买卖点。 不是大级别中枢突破。

1.2 find_fast_bsp3 的当前默认参数

research/lib/fast_bsp3.py

参数 默认值 含义与注意
scan 200 中枢成立后向后扫多少根找突破
pullback_win 30 回抽窗口
tol -1.0 负值=禁用「回抽未触及边界就跳过」。这是最关键的参数,见 3.2
max_per_zone 1 同一中枢只做首次入场,见 4.2
require_touch False 不要求回抽触及中枢边界,见 3.2

tol=-1 + require_touch=False 是当前口径,滞后 2.2 根。 早期默认(tol=0.003, require_touch=True)滞后 5.8 根,年化从 906% 掉到 370%。 新旧差异已完整量化在 step34(tol 扫描)与 step33require_touch)里, 旧口径的原始输出已清理——不需要它,也不要回到旧口径

1.3 交易执行口径

SL, TP, MAX_BARS = 1.5, 3.0, 48      # ATR 倍数止损/止盈 + 超时根数
run_trades(cdf, entries, SL, TP, MAX_BARS, fee=..., entry_delay=1)
  • 入场:信号次根开盘价entry_delay=1),不是信号根收盘价
  • 研究口径成本:4bp 手续费 + 1bp 滑点 = 5bp(所有带「已扣 5bp」的数字都是这个)
  • ATR 取信号根的值(atr[sig_idx]),不是入场根

⚠️ TP=3.0 已被证明偏小(step41/42,见 3.5 与 5.3,且出场参数要按级别分开定。 本文档所有历史数字仍是 TP=3.0 口径,改口径前不要混用

成本模型:不是一刀切的 5bp(用户 2026-08-27 指出)

用户指出「只有开仓才是 taker」。对了一半——止盈挂限价确实是 maker 但止损是 stop-market,成交时仍是 taker(做成 stop-limit 会有急跌不成交的 风险,那种损失远大于省下的费)。所以按出场原因分别计费。

实际费率档位(用户 2026-08-27 给的,单边):返佣前 taker 0.040% / maker 0.016%API 返 50% → taker 2.0bp / maker 0.8bp。

环节 性质 单边费率
入场(次根开盘市价) taker + 滑点 2.0bp
止盈(限价被动成交) maker,无滑点 0.8bp
止损(stop-market taker + 滑点 2.0bp
超时(到点市价平) taker + 滑点 2.0bp

⚠️ step41/42 首轮跑的时候这里写的是 taker 3.0 / maker 1.0bp 隐含「原始 taker 6bp、返 50% 得 3bp」的错误前提。真实原始是 4bp。 方向是保守的——taker 高估了 50%,所以那两步跑出来的净收益、 滑点余量、均R 全部偏低,不是偏高。exit_model.py 已改成实际值, 但本文档里凡是标注「旧费率 3/1bp」的数字尚未逐条重算

SL1.5/TP3/48根 1m 样本外实测(止盈成交占 60%):

口径 平均成本 说明
全 taker 双边 8.00bp 最早的口径,双重高估
混合费率 @ 3/1bp 6.20bp step41/42 首轮
混合费率 @ 实际 2/0.8bp 2.00bp 当前
研究口径 固定 5bp 5.00bp §2 那批老数字

注意方向变了:研究口径的 5bp 现在是偏保守的。 实际混合费率只有 2bp。 实现在 research/lib/exit_model.pystep41/42 共用。 分批离场不额外增加费用(手续费按名义额收,出场 0.5+0.5 总额不变), 而且第一批必然是止盈成交,所以分批在成本上还占便宜。

1.4 阶梯过滤(顺向推进)

对应缠论「趋势 vs 盘整」:当前中枢相对前一个中枢是否同向推进。

pg, pdn = z["zg"].shift(), z["zd"].shift()
z["z_above"], z["z_below"] = z["zd"] > pg, z["zg"] < pdn
push = z_above if direction == 1 else z_below

加上它 PF 从 2.72 → 3.4130m/2h)。用户特别在意这一点,因为它印证了 缠论对趋势的定义(一个分型后第一个中枢就反转的概率低于出现第二个中枢后反转)。

1.5 各级别的确切配对

小级别 大级别(h1,做同向过滤) 备注
1m 5m step23 的配置是 1m:5m:15m15m 只记录不过滤
5m 30m 统计量最强
15m 1h
30m 2h 单笔质量最高

2. 最优配置与核心数字

2.1 级别矩阵(step28,同向+阶梯,3 币)

组合 笔数 胜率 中位 PF t值
5m/30m 1321 53.1% +0.31% 1.98 10.16
30m/2h 258 65.1% +1.65% 3.41 8.51
5m/15m 1292 51.7% +0.24% 1.82 8.84
15m/1h 467 56.5% +0.74% 2.46 7.96

选择逻辑:30m/2h 单笔质量最好,5m/30m 统计显著性最强。1h 及以上小级别笔数不足。

2.2 跨品种样本外(step37)— 最有说服力的一项

参数一个没动,拿 8 个完全没参与调参的币验证:

分组 笔数 年笔数 胜率 中位 PF t值 剔10%PF
样本内(BTC/ETH/SOL) 2309 334 61.4% +0.531% 2.86 +19.11 1.77
样本外(8 个新币) 5859 884 62.9% +0.592% 2.73 +28.50 1.66

逐币最弱的 XRP 仍是 PF 2.21 / t 7.64。没有一个币是负的。

2.3 收益量级——务必用正确口径(step35 第 5 节)

这一条最容易被误读,历史上我自己也一度报错过口径:

口径 年化 回撤 Sharpe
A 1%风险+20倍上限+复利 +1323.8% 8.1% 10.38
B 1%风险+20倍上限+不复利 +270.0% 8.4% 10.38
C 固定名义1倍+不复利 +194.7% 8.4% 7.95
D 固定名义3倍+不复利 +584.1% 25.2% 7.95

只有 C/D 是可以直接对照的量级。 那些 906%/1323% 的数字来自复利+杠杆假设。 平均单笔杠杆 2.1x(中位 1.8x)。 未含资金费率,未含同时持仓的保证金约束。


3. 已验证成立的结论

3.1 没有未来函数(step38,最要紧的一项)

担心的是 incremental.py 里那句注释:「最后一笔 is_sure 允许收回」—— 中枢生效时刻 available_ts 取自笔的 sure_time,而那是全量重算得出的。

做法:对每个信号只喂到该根为止的数据(窗口 4000 根),重跑 TF_DF → 中枢 → fast_bsp3,看信号是否真的在那一刻存在。

结果:同根命中 100.0%(抽检 1217 个信号),完全消失 0.0%,假阳性 0.7%。 偏移中位 +0.0 根。回测口径可信。

3.2 滞后是收益的第一驱动(step34)

口径 笔数 滞后(根) 胜率 PF 年化 Sharpe
禁用跳过(现用) 2309 2.2 61.4% 2.86 +906.1% 9.02
tol 0 2214 2.7 60.4% 2.74 +731.3% 8.43
tol 0.1% 2134 3.6 58.7% 2.64 +569.8% 7.65
tol 0.3%(旧默认) 2045 5.8 55.4% 2.37 +370.4% 6.30
tol 1% 1561 9.9 48.3% 1.88 +112.0% 3.53

滞后与收益严格单调。这也意味着实盘延迟会直接侵蚀收益,是下一阶段的核心风险。

3.3 其余已排除的偏差

  • 中枢生效时刻step36 §1):0% 走 end_time 回退分支,全部用 sure_time
  • 多空对称step36 §3):做多 PF 3.12 / t 14.77,做空 PF 2.62 / t 12.27 → 不是单纯吃加密货币的上涨 beta
  • 时间样本外step36 §4):20192022 挑参数,20232026 验证 → PF 从 3.31 降到 2.44t 仍 12.29。有衰减但成立
  • 滑点脆弱性step35 §1):加到 +30bp 仍 PF 1.73 / t 10.15
  • 入场后移step35 §2):后移 1→4 根平滑衰减(PF 3.18→2.53), 未来函数会呈断崖,这里没有
  • 持仓重叠(step35 §3-4):单腿平均并发 0.01,组合 9 腿平均并发 0.1, 有仓位时间仅 8.6%

⚠️ 「各笔基本独立」这句原来说得太满,已修正。 低并发确实成立, 但那只说明「时间上不重叠」,不等于「统计上独立」——见下方 3.31。

3.31 新出场口径下的并发,以及信号之间的相关性(1m,8 币样本外,门控后)

分批出场把平均持仓从 9.9 根拉到 29 根,并发必须重算:

出场 范围 平均并发 有仓位时间 峰值并发
旧 SL1.5/整仓TP3/48 8 币组合 0.043 4.0% 6
新 SL2/分批→8/留损2/48 8 币组合 0.120 10.2% 6

并发翻近三倍,绝对值仍低。要紧的是峰值 6——8 个币里 6 个同时在仓。

信号在时间上扎堆,且方向高度一致:

  • ±5 分钟内有其他币信号的占 21.6%,±30 分钟 39.6%,±60 分钟 49.6%
  • 同一小时内有 ≥2 个币发信号的时段占 20.9%(2262 个小时), 其中 92.7% 方向完全一致,完全对冲的只有 5.8%

这不是缺陷,是信号在正常工作。 市场同涨同跌时,同一个中枢突破形态在 各币上同时出现;若 6 个币同时发信号却方向随机,那才说明信号是噪声。

但它有两个后果:

  1. t 值有一定虚高:有效样本量小于名义的 13929 笔。不足以推翻结论 (t 值 43 以上),但「各笔基本独立」不再是准确说法
  2. 加币不产生分散,只增加机会数量。组合波动不会随币数下降。 仓位不能按「1% 风险 × N 个币」线性放——峰值 6 仓 × 92.7% 同向, 8 个币就是 6% 风险压在一个移动上;平均杠杆 3.6x 时峰值 21.6 倍名义额。 要设并发上限,或按当前并发数缩放单仓风险。 §10 里「保证金约束未建模」那条在扩币前必须先做

好消息:§5.3 报的 12.6% 最大回撤是在真实时间序列上按实际发生顺序算的, 亏损扎堆已经体现在里面,不是用独立假设推出来的。相关性没被漏掉, 只是不能再指望「加币能降回撤」。

11 币全样本复核(step482026-08-281161 笔 / 208 天 / 实盘口径。

相邻两笔的间隔:中位 122 分钟,62.8% 超过 1 小时,组合平均每天仅 5.58 笔。 同时持仓数:90.9% 的时间空仓,7.5% 只有 1 仓,≥2 仓合计 1.7%,峰值 8。

所以「11 个币会不会同时开」的答案是:绝大多数时候不会,但左尾是硬的—— 7.4% 的信号与前一笔同分钟、20.7% 在 5 分钟内。而这批的方向:

同一分钟出现多笔的时刻共 72 个,方向完全一致的占 100.0%(不是 92.7%)。

这些同时开的仓不是分散,是同一笔押注被拆到几个币上做。 名义 3 个仓位,实质是 3 倍单向敞口。两条推论:

  1. 保证金不是约束,闲置才是。 91% 时间空仓,峰值并发只占 0.1% 的时间。 「币多了保证金不够」基本不成立,真问题是资金绝大部分时间在睡觉
  2. 并发上限要按「同向净敞口」设,不能按「仓位个数」设。 同时开的必然同向,限「最多 3 仓」等于允许 3 倍单向敞口

扎堆的交易赚不赚钱(step48:必须把「同一分钟」和「错开几分钟」分开, 两者结论相反,混在一起会得出错误判断。

分组 笔数 胜率 毛R PF 余量bp
真孤立(±5 分钟内无同伴) 763 (66%) 65.5% 0.832 2.83 11.92
错开:5 分钟内但不同分钟 240 (21%) 82.1% 1.443 7.31 29.59
同一分钟撞在一起 158 (14%) 63.3% 0.777 2.20 12.35

错开的那批是全样本最好的一档(毛R 是孤立组的 1.7 倍),而严格同分钟的 反而略差于孤立组。机制上说得通:错开 = 一波行情从某个币扩散开,后发信号是 对先发的确认;同分钟 = 全市场同时被一个冲击打中,那就是追高。

簇级复核(±5 分钟合一簇,每簇算一个观测,排除重复计数): 多笔簇簇均毛R 1.180 vs 单笔簇 0.832,簇级 R 夏普 0.848 vs 0.459。 结论在簇级依然成立。多笔簇内全赢 59.5%、全输 10.1%、有赢有输 30.4% —— 簇内风险不可分散,但偏度有利(赢的簇是输的簇的 6 倍)。

集中度上两类没差别:整簇方向一致 99.4%(同分钟 100%、错开 99.2%)。 簇内中位 2 个币、最大 8,跨度中位 2 分钟。所以「限制最多 N 个并发仓位」 把两类一视同仁是错的,它们期望收益差 1.9 倍。

簇内顺序:看着是圣杯,其实大半是未来信息(step48) ⚠️

用户提出研究簇内的币种先后顺序。事后按位次切,落差很大:

分组 笔数 胜率 毛R PF 余量bp
(对照)孤立单笔 763 65.5% 0.832 2.83 11.92
簇内第 1 笔 158 81.6% 1.441 5.58 25.63
簇内第 2 笔 158 72.8% 1.085 3.93 20.09
簇内第 3 笔 53 62.3% 0.733 2.19 11.41

但「我是首发」= 「接下来 5 分钟没有别的币再发」,这是未来信息。 首发赢面大恰恰因为后面真跟出来了别的币(那波行情是真的), 而"会不会跟出来"在下单那一刻不可知。

换成开仓时真正可知的信息(过去 5 分钟有无别的币先发):

分组 笔数 占比 胜率 毛R PF 余量bp
无前序 979 84% 68.4% 0.938 3.19 14.13
有前序 ≥1 个币先发 182 16% 69.8% 1.021 3.71 21.88

43% 的落差塌成 8.8%,方向还反过来(跟随略优于首发)。 但残留不是零,且有一处比毛R 更要紧:滑点余量 14.13 → 21.88bp,高 55%。 对 1m 这是实打实的——1m 的生死线就在执行成本上。

「谁在领跑」无稳定结构:首发率 BTC 8.6% ~ DOGE 18.4%158 次首发摊到 10 个 币平均 15.8 次,这个离散度基本是抽样噪声。

这个方向的纪律(组合空间大,样本只有 158 个簇,不设约束必然批量产出 假发现):每一个切法都必须能写成「开仓那一刻我已经知道的信息」。 凡用到「这一簇共几个币」「我是第几个」「簇跨度多长」的,都含未来信息, 回测漂亮但实盘拿不到。

唯一可交易的那条已通过样本外验证(step49)10 币 × 80 万根, 2025-02 ~ 2026-08 共 3941 笔,其中发现期(step48 用过的最近 208 天)1161 笔、 样本外 2780 笔。

无前序 有前序
样本外 毛R 1.086 1.275 +0.189
样本外 余量 18.83bp 24.89bp +6.06bp
发现期 余量 14.14bp 21.96bp +7.82bp

逐时段 6/6 全部同向(余量差 12.52 / 9.10 / 3.82 / 3.89 / 6.95 / 9.25bp 中位 8.03)。发现期毛R 差只有 0.085,样本外反而放大到 0.189——不是过拟合 衰减,是发现期恰好偏保守。占比很稳,各时段 13~19%。

ATR 混淆已排除:有前序 的 ATR 确实略高(中位 15.04 vs 13.13bp),但按 ATR 四分位分层后 4/4 层同向,层内余量差 3.29 / 8.39 / 5.16 / 4.14bp,与不分层 的 +6.06 同量级。且毛R 本身是 ATR 归一化指标,其 +0.19 不可能是 ATR 假象。

可用方式:这 16% 的信号能多容忍约 6bp 执行成本。可用于加仓位权重, 或对这批放宽 ATR 门控——ATR 最低层里 有前序 余量仍有 14.92bp(对照 11.63), 提示门控对它们可以更松。但放宽门控尚未回测,先别改。

⚠️ 「同分钟 vs 错开」是看过数据之后才划的切法,不是事先定的。 208 天、158 个簇,post-hoc 切分容易切出噪声。拿它当仓位规则前必须换一段 时间验证。 目前可确定的只有「扎堆整体更好」(簇级也成立); 「好处全集中在错开那一档」尚待样本外确认。

TRX 应从币池剔除:实盘口径 208 天只有 5 笔,ATR 门控几乎全刷掉 (与 §5.3「2026 只剩 4.2%」一致)。实际可用是 10 个币,不是 11 个。 逐币每天笔数:DOGE/AVAX/SOL 约 0.66BTC/LTC 0.45BNB 0.31TRX 0.02。

3.32 多空对称:这不是伪装成策略的 beta

用户问「整个市场都是正相关的,是不是很少有独立行情」。市场相关是真的, 但这个策略不是市场敞口1m8 币样本外,门控后):

方向 笔数 占比 胜率 净bp PF 均R t值
做多 7057 50.7% 71.2% 35.4 4.05 0.968 43.0
做空 6872 49.3% 71.9% 40.5 4.40 1.006 43.4

做空还略好。所有时段净方向合计仅 +185 笔(总 13929),长期无方向偏置

分年更决定性——若是 beta,2021 年做空该被打爆:

多 均R / PF 空 均R / PF 空头占比
2021 大牛 1.019 / 4.45 1.116 / 5.34 46.5%
2022 熊 0.901 / 3.85 0.962 / 4.07 53.8%
2026 熊 0.863 / 3.33 0.793 / 3.42 55.9%

2021 年做空的 PF 5.34 是整张表最高的一格,七年里没有一年、 没有一个方向是亏的。空头占比随行情切换(牛市 46.5% → 熊市 55.9%), 说明结构识别在跟着市况调方向。与 §3.3 的 30m 结论(多 PF 3.12 / 空 2.62)一致。

3.33 扩币的筛选标准(两条方向相反的约束)

  1. ATR 分布对门控阈值(当前 8bp)——够不够扛住固定成本
  2. 流动性 / 盘口价差——滑点能否压进预算

两条都是及格线,不是「越高越好」的排序依据。

⚠️ 「那就做 ATR 最大的」是错的,两个方向都不支持:

币内(每个币按自己的 ATR 分位)——严格单调,高 ATR 时刻更差:

币内 ATR 分位 净均R R夏普
最低 20% 1.040 0.690
40-60% 0.982 0.655
最高 20% 0.878 0.599

ATR 飙升往往意味着行情已走过头,噪声大、容易反抽。 (但不必加上限门控:最高分位的 0.878 仍然是好交易,砍掉只是白丢机会。)

跨币——看似正相关(ATR vs 净均R r=+0.684),但剔除 BTC 后掉到 +0.469, 且其余 9 币的净均R 区间只有 0.935~1.024(极差 0.089)。BTC 自己 0.787, 明显低于所有其他币。BTC 差更可能因为它是最大最有效的市场、结构性机会少, 把它的低 ATR 与低 R 读成因果是过度拟合一个点。

ATR 唯一真正提供的是 bp 余量r=+0.85,剔 BTC 后仍 +0.85)。 但这是机械关系——余量按定义随 ATR 缩放。它有用(滑点大致固定在 bp, 余量高就能扛更多滑点),但不代表 ATR 高的币「更赚」。

⚠️ 追高 ATR 还会撞上这份数据看不见的流动性墙。 现有 11 币全是头部流动性; 高 ATR 通常意味着小市值、盘口更薄,多出来的余量很可能被滑点吃回去。 把在头部币上成立的关系外推到另一个流动性区间,是最容易翻车的那类外推。

现有 11 币的实际情况:BTC ATR 中位 2026 仅 6.5bp、门控刷掉 58.5%、 预算 8.58bp 垫底;TRX 2026 门控后只剩 4.2% 的信号,当前环境基本不能做。

筛选很便宜:拉候选币 1m 数据,只算 ATR 分位数与盘口价差,不必跑策略 就能排掉大半。

⚠️ 但样本外的说服力会被稀释:当前最硬的证据是「8 个币完全没参与调参、 全部为正」。若新币是在同一份历史上筛出来的,它们就不再是样本外。 要保持这个性质,得留一批筛完不看、直接进实盘验证。

3.34 组合最优解:选币的杠杆很小,币数的杠杆在前 6 个

穷举每个 N 的最优子集(1m,门控后,固定日历,只扣手续费不扣滑点):

币数 最优子集夏普 增量 年化R 若信号独立应有 捕获比例
1 9.94 323 9.94 100%
2 13.15 +3.21 611 14.06 94%
4 16.93 +1.61 1174 19.88 85%
6 18.87 +0.78 1672 24.35 77%
8 19.87 +0.38 2188 28.11 71%
11 20.22 +0.02 2690 32.97 61%

三条结论:

  1. 边际收益在 6~8 币后归零。 8→11 只换来 +0.35 夏普(+1.8%), 但年笔数多 500+,成本与运维复杂度是实打实的。
  2. 具体选哪几个几乎不重要。 165 个 8 币组合:最好 19.87ADA/AVAX/ DOGE/ETH/LINK/LTC/SOL/XRP)、最差 17.61、中位 18.66,极差 2.2612%)。 ⚠️ 这一条已被 §3.37 推翻——它忽略了盘口冲击。计入后币间差距是 5 倍, 且排序近乎翻转(AVAX 从必选变成必剔,BTC 反而可用)。选币很重要。
  3. 相关性吃掉近 40% 的分散化收益——捕获比例从 100% 单调降到 61%。 与 3.31 的「92.7% 同向」一致:加币是加机会,不是加分散。

⚠️ 并发保证金不是瓶颈,此前的担心是错的。(早前按事件平均算出 0.92, 高估了——事件在繁忙时段聚集。时间加权才是对的口径。)

时间加权均并发 有仓时间占比 有仓时均并发 p99 最大
全样本 11 币 0.15 12.3% 1.24 2 9
2026 11 币 0.11 9.1% 1.26 2 8

资金 88% 的时间闲置,扩币在保证金维度有大把余地。峰值 9 仍要按 3.31 的同向假设做限额,但那是尾部风控,不是容量约束。

⚠️ 上表夏普只扣手续费、未扣滑点,绝对值虚高(年化 20 不可信), 只能用于相对比较。 真正的约束是实测滑点 vs 预算——见 5.3 与 3.35。 按杠杆排序:滑点是生死(100%)> 币数 1→6(+90%)> 选哪几个(±12%,基本是噪声)

3.36 成本模型的已知缺口:滑点被当成了常数,但它是仓位的函数 ⚠️

全文所有预算数字都假设滑点是固定 bp,与下单规模无关。这是错的 (用户 2026-08-28 指出)。且这个错误不是随机的——它系统性偏袒低 ATR 端。

固定分数下单意味着 名义额 = 风险额 / (2·ATR),即仓位 ∝ 1/ATR 而预算(bp)∝ ATR。两者方向相反:

ATR 桶 bp 中位杠杆 中位名义额(10万本金、每笔冒1% 预算 bp
8-12 5.0x $502,029 13.7
12-16 3.6x $362,362 19.5
16-22 2.7x $269,999 23.1
22-30 2.0x $198,172 29.3
>30 1.3x $129,065 52.1

低 ATR = 单子最大 + 预算最小 + 滑点随单子变大 = 三重挨打。 所以按固定 bp 算出的逐币/分桶预算,系统性低估了低 ATR 端的劣势

ATR 门控因此比原论证更有价值:被刷掉的信号中位杠杆 8.9x、p90 17.6x (保留的是中位 3.2x、p90 5.3x)——门控砍掉的正是最大的单子。 这比「固定成本占比高」是更强的理由。

三条待办(都属于「数据回来前不做、回来后会后悔」):

  1. 影子交易要记录信号时刻的盘口快照(≥10 档),不只是成交价。 有深度就能离线算任意仓位的冲击成本——一次测量回答所有资金量级, 否则换个规模就得重测。若用极小量或 paper 测,得到的只是 价差/2 + 漂移 这个下界,必然乐观。
  2. 资金容量要算出来,不要等实盘暴露。 预算 20bp 蕴含一个资金上限。 中位名义额 $32 万、p90 $53 万,在 ADA/LINK/AVAX 的 1m 永续盘口上不是零头。
  3. maker 腿的仓位问题是成交率,不是冲击。 回测假设 3 ATR 与 8 ATR 的限价单全额成交。$30 万挂单可能只部分成交,而部分成交会改变分批出场 的收益结构(§3.5 的结论建立在全额成交上)。需在影子数据里验证。

3.37 计入盘口冲击后,币种排序几乎翻转 —— §3.34「选哪几个不重要」作废 ⚠️

Bitget USDT 永续实时盘口(2026-08-28 01:30 HKT5 次快照取中位)。 净预算 = 回测预算 − $300k 单边吃单冲击($300k ≈ 10万本金 × 中位杠杆 3.2x):

价差bp ask深度 $300k冲击 回测预算 净预算 冲击占预算
SOL 0.09 $3.3M 2.82 28.3 25.5 10%
DOGE 1.12 $13.5M 4.35 28.5 24.1 15%
ETH 0.04 $19.4M 0.27 20.8 20.5 1%
XRP 0.68 $14.9M 4.82 24.5 19.7 20%
BTC 0.01 $4.5M 0.26 14.6 14.3 2%
LINK 0.84 $2.8M 12.20 26.2 14.0 47%
ADA 4.62 $6.3M 9.70 23.5 13.8 41%
LTC 1.99 $3.2M 11.13 23.6 12.5 47%
AVAX 1.33 $3.0M 23.65 29.0 5.3 82%

§3.34 的「165 个 8 币组合极差仅 12%、选哪几个不重要」是错的——那个结论 完全建立在忽略流动性上。计入冲击后币间差距是 5 倍25.5 vs 5.3)。

排序近乎翻转,根因是 ATR 与流动性负相关,所以按预算(∝ATR)排出的序 恰好是按流动性排的逆序:

  • AVAX 原始预算最高(29.0)、净预算最低(5.3)。它在最优 8 币里入选频率 95%,实际最该剔除。5 次快照 22.3~24.7bp,不是抽样噪声
  • LINK / ADA / LTC(入选频率 95%/95%/70%)净预算全掉到 12~14
  • BTC 此前判为「中性」,实际净预算 14.3,反而优于 LINK/ADA/LTC—— 原始预算最低但冲击几乎为零

这就是 §3.33 定性警告过的「流动性墙」,现已量化,且比预想严重。

真正的结论:可用币种是资金量的函数,不存在固定的最优币表。 按 $100k 名义额(≈$32k 本金)重算,净预算回到 ADA 18.0 / LINK 17.2 / LTC 16.5 / AVAX 11.6——除 AVAX 外全部健康。扩币前先定本金。

当前运行点:本金 < $2k(用户 2026-08-28 确认,目的是先跑通流程)。 在这个规模上 §3.37 的重排序不适用——单笔仅 $6.4k,冲击占预算 18% (连 AVAX 也只有 8%),9 个币全部可用,§3.34 的「选哪几个不重要」重新成立。 分水岭在 **$20k$50k 本金**:以上才需要收缩到 SOL/DOGE/ETH/XRP/BTC (这 5 个在 $2k~$200k 全区间冲击 ≤21%,是与资金量无关的安全核心)。

冲击占预算比例(按本金,杠杆 3.2x):

$2k $10k $20k $50k $100k
BTC / ETH 0% 0% 0% 0% 0~2%
SOL 1% 3% 4% 5% 6%
XRP / DOGE 5~6% 9~10% 12% 15% 16~17%
LINK 4% 11% 16% 31% 46%
LTC 12% 22% 30% 41% 57%
ADA 20% 28% 29% 38% 51%
AVAX 8% 28% 43% 70% 91%

小资金无操作性障碍Bitget 最小下单量在 $300 本金都不卡, 半仓取整误差最差 2.4%(ETH @ $500),其余 <1%。

⚠️ 但 $2k 跑通 ≠ 验证了策略容量。 小资金下有两处系统性偏乐观、且不可外推: (a) 冲击≈0,测出的滑点只剩 价差/2 + 延迟漂移,几乎必然通过 15.19bp, 但不能推出 $50k 也通过;(b) maker 腿成交率也是假的好——$3.2k 挂单几乎 必然全成,$150k 不一定,而 §3.5 分批出场的收益结构全建立在全额成交上。 → 这正是「记录盘口快照」的价值:它是唯一能让小资金数据回答大资金问题的东西。 只记成交价的话,每上一个资金台阶都得重测一遍。

$2k 阶段真正该盯的只有两件:延迟与漂移(与规模无关,结论长期有效)、 中枢阶梯 + ATR 门控必须在线上生效(否则测的是另一批信号,与回测不可比)。

⚠️ 三条保留:(1) 单一时段快照,盘口有日内周期,需跨时段采样; (2) 信号恰在波动放大时触发,那时盘口更薄——上表是乐观下界 (3) 只算了入场 taker 腿,止损/超时同为 taker,maker 腿则是成交率问题。 第 (2) 条意味着这批静态数字不能替代影子数据,只是把「该测什么、该剔谁」 提前定下来了。

3.35 跨 venue:信号身份不迁移,但总体期望迁移(live 前置测量)

回测全部跑在 Binance 数据上,实盘要在 Bitget 成交。 服务器侧的 research/live/venue_parity.py 把这件事量了:

品种 Bitget信号 Binance信号 同根重合
BTC 47 38 42.6%
ETH 39 35 28.2%
SOL 48 29 14.6%

(5m 同向过滤后口径。SOL 差得最多是因为 tick 粗细不同:Bitget 0.001、 Binance 0.01,粗 10 倍会让 close > high[j-1] 大量平局不触发, Bitget 上信号多出 74%。这是系统性差异,不是随机扰动。

signal_sensitivity.py 进一步显示 0.25bp 的数据扰动就能换掉一半信号

aggregate_robustness.py 的结论是:总体期望不塌。 加 0.5 / 1 / 2bp 噪声重跑,毛均收益与 PF 都在原区间内摆动,没有单调恶化。

脆的是信号身份,不是 alpha。 这决定了两件事: 一、滑点不能逐笔对照 Binance 回测,只能对照同一 venue 上的总体毛均收益; 二、影子测量必须跑在生产路径上(Bitget 原生数据 + Hummingbot), 换个运行时测出来的数就不作数。

同窗口 Bitget vs Binance 毛均收益(210 天、TP=3.0 口径): BTC 5.87 vs 6.09、ETH 10.02 vs 12.06、SOL 8.92 vs 9.87bp。 Bitget 一致略低 0.2~2bp,但没有量级差异,总体口径可迁移。

⚠️ 上面那批数字用的是 毛均收益 6.0bp、只有同向过滤、TP=3.0 不能直接当预算用,正确的逐币预算见 lib/shadow_budget.py 与 5.3。

3.38 浅色信号(未过双过滤)在 1m 上不能做——差在毛质量,不在成本(step44)

用户观察「图上很多浅色 b4/s4 的入场价看着也很有优势」。step40 做过同类消融但 只覆盖 15m/30m 且用旧口径(5bp 平摊、1.5/3.0/48),1m 从未验证。

research/step44_filter_ablation_1m.py,8 币 × 30 万根,当前最优 1m 出场 SL2.0 / 3ATR 减半 / runner 8ATR / rstop 留原位 / 48 根),真实费率, ATR ≥ 8bp 门控后共 2302 笔:

口径 笔数 胜率 毛R 净均R 剔10%PF 滑点余量bp
深色(同向 ∧ 阶梯) 955 68.3% 0.933 0.798 2.35 15.07
浅色(任一不过) 1347 44.3% 0.155 0.009 0.74 0.10
— 只过阶梯 445 52.1% 0.419 0.279 1.03 4.18
— 只过同向 265 38.1% 0.029 0.176 0.59 2.15
— 两个都不过 637 41.4% 0.046 0.103 0.62 1.64

关键是「毛R」列——那是扣任何成本之前的数字。 浅色 0.155 vs 深色 0.933 差 6 倍。所以不存在「信号本来不错、被手续费吃掉」这回事:浅色的跟随性 本来就差。浅色扣完手续费只剩 0.10bp,任何滑点都会让它亏;逐币 8 个里 4 个已为负(ETH 1.98 / LTC 2.93 / DOGE 1.05 / XRP 0.14),最好的 ADA 也才 2.41bp。

为什么肉眼看着有优势:(1) 入场价确实是好的,信号标的是真实局部结构; (2) 但价格不跟随,毛R 0.155 覆盖不了 2 ATR 的止损——入场点好 ≠ 价格继续 朝你走;(3) 44.3% 的胜率意味着近一半确实走对,扫图时看到的就是这些, 走错的当时形态一样好看。

⚠️ 新发现:1m 上阶梯过滤远比同向过滤重要,与 30m 相反。 只过阶梯 +4.18bp,只过同向 2.15bp 且毛R 为负;而 30m 上同向单独就能把 PF 从 1.59 提到 1.85(§4 step30)。两个过滤器的相对价值随级别翻转, 不要跨级别套用滤网结论。

3.4 alpha 的来源(step32 消融)

逐条拆掉 fast_bsp3 的条件后发现:alpha 完全来自缠论中枢的上下文定位, 不是「回抽结束、收盘转强」那个触发动作本身。 触发条件只负责压低滞后。

这个结论回答了用户当时的问题(「如果有这个,那就可以去判断任何笔的端点了」): 不能。脱离中枢上下文,那个触发条件没有预测力。

3.5 出场:TP=3.0 把右尾截早了(step41

起因是用户看图指出「止盈没做好」。查下来确实如此。

先量 MFE(每笔在被止损打掉之前最远走到几个 ATR):

分组 级别 笔数 中位 MFE ≥3ATR ≥5ATR ≥8ATR
样本内 15m/30m/5m 2309 3.66 / 4.30 / 4.27 55~62% 41~45% 23~28%
样本外 15m/30m/5m 5859 4.08 / 3.80 / 4.30 57~61% 42~45% 25~28%

中位数就已经高于 TP=3,样本内外一致。抬高 TP 的样本外结果:

出场 胜率 均收益 中位 PF t值 剔10%PF 均持仓
tp3(现用) 62.6% +0.559% +0.588% 2.71 +28.31 1.64 11.2
tp4 58.7% +0.692% +0.579% 2.95 +29.24 1.71 15.3
tp5 56.5% +0.783% +0.485% 3.12 +29.36 1.75 18.8
tp6 55.3% +0.860% +0.369% 3.28 +29.17 1.77 21.7
tp8 54.1% +0.983% +0.284% 3.56 +28.27 1.78 25.7
  • 8 个样本外币逐个看,均收益与 PF 全部提升2020~2026 七年 PF 也全部提升
  • 剔掉最好 10% 后 PF 仍从 1.64 升到 1.75 → 不是几笔暴利撑起来的
  • t 值在 tp5 见顶(+29.36)后走平,tp6/tp8 靠的是越来越薄的右尾
  • 基线复现校验:step41 的 tp3 = 5859 笔 / PF 2.71 / t +28.31 / 剔10% 1.64 对上 §2.2 的 2.73 / +28.50 / 1.66,差在千分位(同根内止损与新高并存时保守 假定止损先到),说明对比是在正确基线上做的

代价不是零:胜率 62.6%→56.5%,中位 +0.588%→+0.485%(过半单子变差, 输在「摸到 3ATR 没走到 5ATR 又反手止损」那批),平均持仓 11.2→18.8 根, §3.3 的并发数据需重算。心理上也更难拿。

分批离场更优(用户提的方案,改一处后成立)

用户方案:到 3 ATR 平一半 + 止损移到开仓价,剩下跑到大目标。 前两步对,「止损移到开仓价」是错的。 用户随后要求把剩余半仓的止损位 也扫一遍(0 / 0.5 / 1 / 1.5 / 2 ATR),结果严格单调,三组初始 SL 全一致

样本外 5859 笔,初始 SL1.5、分批→8 ATR、48 根:

剩余半仓止损位 净均收益 中位 PF t值 剔10%PF
保本损(0 +0.611% +0.420% 2.81 +25.66 1.50
留损 0.5 ATR +0.688% +0.455% 3.03 +27.65 1.65
留损 1.0 ATR +0.732% +0.475% 3.17 +28.64 1.74
留损 1.5 ATR(不动) +0.754% +0.498% 3.23 +29.25 1.79
留损 2.0 ATR(放宽) +0.762% +0.510% 3.25 +29.48 1.81

没有中间最优点,越松越好,但增量在「不动」处饱和 保本→0.5 加 0.077%0.5→1 加 0.044%1→1.5 加 0.022%1.5→2 只加 0.008%。 所以止损保持原位即可,放得比原止损更宽是拿实打实的风险换千分之一的收益

机理与移动止损失败同源(§4):回抽到成本价是突破后的正常结构,不是信号失效。 信号已用「摸到 3 ATR」自证,此时收紧止损等于用最坏价格淘汰掉最好的单子。

胜率与整仓 TP3 完全相同是结构决定的:摸到 3 ATR 的单子在分批下必然是赢家 (半仓 +3 ATR,剩余半仓最坏 1.5 ATR,净 +0.75 ATR)。这正是分批相对整仓 高 TP 的价值——同一批单子在整仓 TP5 下会变成 −1.5 ATR 的亏损。

初始 SL 扫描:必须用 R 倍数口径,否则会把仓位差异算成策略优势

用户要求扫 1 / 1.5 / 2 ATR 初始止损。百分比收益会误导:SL 越宽每笔风险越大, 固定风险仓位下仓位越小,raw % 里 SL2 看着比 SL1.5 好 68%,其中大半是仓位效应。

样本外,分批→8 ATR、留损=初始 SL、48 根,§2.3 的 1%风险 + 20倍上限 + 复利:

配置 均R R夏普 最差1%R 平均杠杆 最大回撤(样本外/内) Sharpe(外/内)
现用 SL1.5 整仓TP3 +0.722 0.494 1.55 1.97x 12.1% / 11.9% 14.79 / 8.33
SL1.0 分批→8 +1.023 0.381 1.93 2.70x 16.0% / 14.7% 11.36 / 6.72
SL1.5 分批→8 +1.023 0.530 1.55 1.97x 13.5% / 9.4% 15.79 / 9.30
SL2.0 分批→8 +0.943 0.638 1.37 1.53x 13.1% / 6.4% 19.00 / 11.35
  • SL=1.0 明确最差:均R 与 SL1.5 打平,但 R夏普 只有 0.381、回撤最大、 最差单笔 −1.93R。止损太紧被噪声打掉,和 §3.2「滞后是第一驱动」是一类问题
  • SL=1.5 期望值最高(均R 1.023),SL=2.0 风险调整最好 R夏普 0.638、回撤 6.4%、Sharpe 11.35,样本内外一致)
  • SL2 只让出 8% 的单位风险期望,换来 20% 更高的 R夏普和更好的最差单笔。 纠正一次误判:修正仓位效应后 SL=2.0 仍然占优,不是纯粹的仓位错觉
  • 按剔10%PF 排全网格,前 14 名全是 SL=2 的分批配置, 第一名 SL2 分批→8ATR 留损2 48根:剔10%PF 2.26(现用 1.59)、 净 +0.920%、PF 3.84、滑点余量 61.79bp(现用 40.05bp
  • 该配置样本外 8/8 币、7/7 年对现用全面提升,无例外

上表的年化数字是 §2.3 的口径 A(复利+杠杆),且把 8 个币当一个账户串起来算, 严重虚高,故意不记录。只有回撤、Sharpe、R 这些比值可以横向比。

换成实际费率(2/0.8bp)后:几乎没变

step41 首轮跑的是错误的 3/1bp(见 §1.3),已用实际费率重算分析段 (feather 存的是毛收益+出场原因,不必重跑模拟):

口径 平均费 净均收益 余量bp 剔10%PF 均R
样本外 现用 SL1.5/TP3/48 3.00→2.00bp 0.579→0.589% 41.34→42.05 2.01→2.05 0.790→0.811
样本外 最优 SL2 分批→8 留损2/48 4.45→3.01bp 0.941→0.955% 62.17→63.13 2.69→2.75 0.975→0.998
样本内 最优 SL2 分批→8 留损2/48 4.43→2.99bp 0.866→0.881% 57.15→58.10 2.91→2.98 0.960→0.984

结论一个都没变,量级也没变(余量动了 2%)。原因还是那条: 成本固定在 bp、目标随 ATR 缩放,所以费率只对 1m 有杠杆—— 同一次改动在 1m 上把均R 抬了 8%,在这里只有 2%。

ATR 门控在这三条腿上是惰性的

1m 上有效的 ATR ≥ 8bp 门控(见 5.3),搬到这里几乎不触发:

级别 ATR中位 <8bp 占比 门控后保留 均R 变化
5m 33.6bp 2.60% 97.4% 1.007 → 1.006
15m 60.2bp 0.16% 99.8% 0.995 → 0.992
30m 82.5bp 0.00% 100% 0.947 → 0.947

无害也无用,所以可以当全局规则统一写进执行层,不必按级别分叉: ATR ≥ 5 + 1.1 × taker费(bp),当前费率下即 ≥ 8bp。 它只在 1m 上真正起作用(那里 21.5% 的信号在阈值以下)。


4. 已验证无效 / 不要重做的方向

方向 结论 出处
动态止盈(小级别三买后等大级别三买再调止盈) 无效。持仓期太短(8~13 根),大级别确认来得太罕见 step27
移动止损(1.5 ATR 跟踪距离) 明显劣于固定 TP:样本外 PF 2.32、剔10%PF 0.94TP=3 是 2.71/1.64)。突破后的正常回抽就能把它洗出去,和 §3.2「滞后是第一驱动」同源 step41
分批后收紧剩余半仓的止损(保本损及一切更紧的位置) 直觉上该做,数据上是负的。止损位 0/0.5/1/1.5/2 ATR 严格单调,越紧越差,三组初始 SL 全一致:保本损比不动少赚 0.14%/笔,剔10%PF 从 1.79 塌到 1.50。与移动止损同源——回抽到成本价是正常结构,不是信号失效。分批要做,止损保持原位 step41 §3.5
初始止损收到 1.0 ATR 5m/15m/30m 上均R 与 1.5 打平但 R夏普 只有 0.3811.5 是 0.530)、回撤 16.0%、最差单笔 1.93R。1m 上更极端:剔10%PF 0.78~0.99、中位收益 0.122%、回撤 25.5%。1 ATR 就是噪声宽度 step41/42
同一中枢重复入场(二次、三次) 质量骤降,只做首次 step25
缠论引擎原生 find_all_bsp 的 B3/S3 统计上呈逆势、显著亏损:胜率 27.4%(低于 SL1.5/TP3.0 的随机基准 33%)、PF 0.66、t 18.76。不是滞后造成的——同一组过滤器把 B4 从 1.59 提到 2.26,对它无效(0.66→0.71),且入场后移 1~4 根只是平滑衰减。它几乎不筛(627 个中枢发 625 个信号),把「价格早已离开、再没回来」的历史区间也当信号发出来。B4/S4 因此单独立类,不是它的提前版 step30/31
刷交易额换 VIP 费率 成本收益不划算,见 5.3。但前提已变:该结论算于「原始 taker 6bp、全 taker、TP=3.0、无门控」,四个前提现在全不成立(实际 2/0.8bp、混合费率、分批出场、有 ATR 门控)。已在返 50% 的档位上,继续压缩的空间本就有限,但若要重估需重跑,不要直接引用旧结论 step23
按 ATR 从大到小选币 / 追高 ATR 时刻 门控之上 ATR 高不加分。币内严格单调递减ATR 最低 20% 分位净均R 1.040,最高 20% 只有 0.878。跨币看似正相关(r=+0.684)但剔除 BTC 后掉到 +0.469,其余 9 币极差仅 0.089。ATR 唯一真正给的是 bp 余量(机械关系)。且追高 ATR 会撞上流动性墙——现有 11 币全是头部流动性,外推到小市值币时多出的余量会被滑点吃回去。ATR 是及格线不是排序键 §3.33
available_ts 改取 bis[2](中枢成立即可用)以消除右边缘重画 重画确实从 6.5% 降到 1.2%、滞后 2.16→2.01但 alpha 被打成零:实盘口径毛 R 0.933 → 0.000(扣费前就没了 edge),PF 3.22→0.80,余量 15.07→−2.20bp,8/8 币全变差。中枢没发育完就下注,支撑/压力还没立住。**「等中枢最后一笔」就是 alpha 本身,重画是必付代价。**推论:任何以「让信号更早确定」为目标的改动,先测毛 R,不要只看重画率和滞后 step47 §5.42
线段(Chan_XD)做大级别 滞后太大,且中枢极少 早期,用户也这么说

5. 实盘落地的现状与关键约束

5.1 交易所:这是当前最大的未决项 ⚠️

用户实际用 Bitget手续费.xlsx 在项目根目录):

VIP maker taker 升级门槛(月交易额)
1 0.020% 0.060% 0
2 0.016% 0.040% $3M
3 0.014% 0.0375% $20M

返还比例:手动 60%、API 50%

框架支持情况(已查证,2026-08):

框架 Bitget 永续 说明
freqtrade(本地已装 2025.4-dev 源码里搜不到一处 bitgetSUPPORTED_EXCHANGES = binance/bingx/bitmart/bybit/gate/htx/hyperliquid/kraken/okx
NautilusTrader nautilus-bitget 是 0.0.0 空壳无 API;官方适配器列表(2026-06-30)无 Bitget。Bitget 只出现在第三方 Tardis 历史数据里
Hummingbot bitget_perpetual v2.0 连接器,2026 年 Bitget 官方合作。支持单向/对冲、限价/市价,有 Perp Candles Feed

用户最后问的就是「还有没有其他框架支持 Bitget」,答案是 Hummingbot—— 这个问题还没得到他的回应,需要先确认交易所再定框架。

其他信息:Hummingbot V2 的 PositionExecutor 结构恰好匹配我们的 「入场 + 止损 + 止盈 + 超时」,架构上契合。用户的费率表里还有一列空着的 HL Hyperliquid),而 Hyperliquid 在 freqtrade 和 Nautilus 都是原生支持的。

5.2 网络:Bitget 必须走代理 ⚠️

直连  失败 NetworkError: bitget GET https://api.bitget.com/api/v2/spot/public/coins
代理  OK 2.39s  (http://127.0.0.1:7897)

盘口实测(BTC/USDT:USDT 永续):bid 79492.7 / ask 79492.8 价差仅 0.01bp100 档深度。即时价差成本可忽略。

但代理会把延迟从几百毫秒放大到秒级,而 1m 那条腿的滑点预算只有 3.9bp。 实盘这条腿最终必须落到境外 VPS,否则测出来的滑点是代理的账,不是策略的账。

5.3 1m 那条腿的经济性(用户的核心问题)

用户原话:「1m 测的是返佣后是否能够不亏钱」,配合「一边刷交易额,一边走大点周期」。

1m 同向信号实测:3578 笔 / 2.28 年 / 3 币 = 524 笔/年/币, 毛均收益 +0.0991%,胜率 54.2%,平均持仓仅 8.3 分钟。

按 Bitget 真实费率算滑点预算:

⚠️ 下表的费率档位是错的:它假设原始 taker 0.12%、返 50% 得 0.060% 双边。 实际是原始 taker 0.040% / maker 0.016%,返 50% 后 taker 2.0bp / maker 0.8bp (见 §1.3)。整张表连同下面那张「四条腿对比」都只保留跨级别的相对关系 绝对数字全部作废。

档位 双边费率 PF=1 滑点上限 t>2 实用上限
VIP1 taker + API 返50% 0.060% 3.9bp ~2.5bp
VIP1 taker + 手动返60% 0.048% 5.1bp ~3.8bp
VIP2 taker + API 返50% 0.040% 5.9bp ~4.5bp
VIP1 maker + API 返50% 0.020% 7.9bp ~6.5bp

四条腿的滑点余量对比VIP1 taker + API 返50%,即双边费率 0.060%):

级别 笔数 毛均收益 平均持仓 滑点余量
1m 3578 +0.0991% 8.3 根 3.91bp
5m 1984 +0.3253% 9.7 根 26.53bp
15m 689 +0.4436% 12.1 根 38.36bp
30m 340 +0.9504% 11.7 根 89.04bp

1m 和 30m 的余量差 23 倍。

重要判断:1m 若失败,绝不能拿它去否定 5m/30m。 三条腿的成本敏感度不在一个量级上。

⚠️ 上面的 3.91bp 已被 step42 推翻:那是 30m 的参数套在 1m 上量出来的

用户指出:SL1.5/TP3.0/MAXB48 是在 5m/15m/30m 上定的,1m 不该混用。 成本固定 5bp,而目标随 ATR 缩放1m 的 3 ATR 只有 0.39%、30m 是 1.87% 成本占比差 5 倍,最优 TP 不可能相同。查证后确实如此,而且原因比成本更根本:

级别 MFE 中位 ≥6 ATR ≥10 ATR
1m 5.16 ATR 46.1% 28.6%
5m 4.29 37.8% 18.6%
15m 3.98 34.7% 17.0%
30m 3.94 36.6% 18.7%

1m 以 ATR 计的右尾是其他级别的两倍。 机理:1m 的 ATR 量的是分钟级噪声, 但信号一旦成立抓到的是几小时级别的趋势,所以「行程 / ATR」比值天然更大; 30m 的 ATR 本身已经吃进了一部分趋势。所以 TP=3 ATR 在 1m 上是个远比在 30m 上 更紧的目标——这不是调参问题,是量纲问题

(MFE 本身也随初始止损变化,止损越松活得越久、右尾越长: 1m 上 SL1.0 中位 2.37 ATR、SL1.5 是 5.16、SL2.0 是 6.73。 所以 TP 和 SL 必须一起定,不能固定一个扫另一个。)

1m 全网格重测(step4211 币 × 7 年,25476 笔)

⚠️ 本小节的表用的是旧费率 3/1bp(跑的时候费率档位写错了,见 §1.3)。 实际是 2/0.8bp,所以下面所有净收益、余量、均R 都偏保守。 用实际费率重算的版本在再下一小节,决策请用那一版

扫描空间:SL ∈ {1.0, 1.5, 2.0} × TP ∈ {2,3,4,5,6,8,10,12} × MAXB ∈ {48, 96} × 分批(3 ATR 减半 → 剩余目标 {5,6,8,不设} × 留损 {0,0.5,1,1.5,2})。

结论与 5m/15m/30m 同向,但幅度更大,且 1m 上没有取舍——最优解在每个指标上都赢。

样本外(8 个未调参币,17734 笔):

口径 胜率 毛bp 净均收益 中位 PF 剔10%PF 滑点余量 均R R夏普 最大回撤 均持仓
现用 SL1.5 / 整仓TP3 / 48根 60.8% 20.27 +0.141% +0.169% 2.09 1.24 11.06bp +0.434 0.274 14.7% 9.7
SL1 分批→8ATR 留损1 / 48根 45.9% 20.29 +0.133% 0.122% 2.01 0.96 9.07bp +0.649 0.225 25.5% 17.5
SL1.5 分批→8ATR 留损1.5 / 48根 58.9% 28.60 +0.219% +0.132% 2.70 1.49 15.12bp +0.781 0.376 14.1% 23.7
SL2 分批→8ATR 留损2 / 48根 67.6% 34.90 +0.284% +0.233% 3.41 2.01 20.12bp +0.792 0.500 12.6% 28.4

(滑点余量口径已改:分子是毛收益减实际手续费,分母是 taker 名义额, 即每条 taker 腿能承受多少滑点。旧表按双边固定 6bp 扣、不除 taker 腿, 所以数字偏大——上一版写的 14.27bp 就是旧口径,与 11.06bp 是同一件事的两种算法。)

  • 滑点余量 11.06 → 20.12bp,接近翻倍;均 R +0.434 → +0.792+82%
  • 8/8 样本外币、7/7 年份全部提升,无例外。最弱的 2026 年: 现用余量 4.69bp / 剔10%PF 0.92(已跌破 1),最优 9.84bp / 1.45
  • 样本内同向:净 +0.100% → +0.221%,剔10%PF 1.07 → 1.72,回撤 19.7% → 10.2%
  • MAX_BARS=48 不用改:1m 上 96 根在同配置下一致略差(剔10%PF 2.01 → 1.95), 这点与 5m/15m/30m 不同,是 1m 唯一沿用原参数的地方
  • 纯整仓高 TP(TP8/TP10)毛收益更高(4447bp)但胜率跌到 5960%、 中位收益反而更低;分批版 PF 与剔10%PF 更好,是更稳的那一侧

1m 上 SL=1.0 是废的(比其他级别更明确):剔10%PF 只有 0.78~0.99 中位收益 −0.122%(一半以上的交易是亏的),最差 1% 到 −3.69R,回撤 25.5%。 1 ATR 在 1m 上就是噪声宽度,止损放在噪声里必然被反复扫。

减仓后剩余半仓的止损位——三组初始 SL 下都是同一条单调曲线:

初始SL 保本损(0) 留损0.5 留损1 留损1.5 留损2
SL1.0 剔10%PF 0.78 0.91 0.96 0.98 0.99
SL1.5 剔10%PF 1.23 1.38 1.45 1.49 1.50
SL2.0 剔10%PF 1.68 1.86 1.95 2.00 2.01

越松越好,到「不动」(= 初始 SL)为止基本饱和,再放宽只有 +0.01 的边际。 保本损在 SL2 上直接砍掉 0.33 的剔10%PF,是全表最差的一档。 结论与 5m/15m/30m 完全一致:减仓后不要动止损

逐年余量在衰减——那是波动率压缩,不是 alpha 衰减

用户看到余量逐年递减后提的假设:「是不是跟波动率有关,2026 是熊市、2025 是牛市」。 查证成立,而且相关性高到接近恒等式。

余量bp当年 ATR 中位数 的跨年相关系数 r = +0.989n=7)。

ATR中位 毛bp 毛/ATR 余量bp(旧费率) 均R
2020 16.3 39.8 2.44 23.98 0.939
2021 牛 22.1 58.7 2.65 36.49 1.031
2022 15.4 36.5 2.37 21.30 0.876
2023 9.8 24.9 2.53 13.88 0.846
2024 11.7 31.3 2.67 18.07 0.877
2025 11.6 27.8 2.40 15.76 0.883
2026 熊 8.8 19.8 2.26 10.28 0.713

关键是「毛/ATR」列:2.26~2.67,七年无趋势。 信号质量以 ATR 计几乎没衰减。 衰减的是 ATR 本身——2021 的 22.1bp 压到 2026 的 8.8bp,掉了 60%。 余量是 bp 口径,自然跟着掉。这就是 §5.3 的论证从跨级别搬到跨时间: 成本固定在 bp,目标随 ATR 缩放。低波动年份等于「1m 变得更像 1m」。

保留意见:2026 的毛/ATR 2.26 与余量/ATR 1.17 都是七年最低, 可能还有一点真衰减,但 8 个月 1682 笔分不出是噪声还是趋势。

ATR 门控:低 ATR 的信号毛质量不差,是被固定成本吃掉的

按信号根 ATR 分桶看 R(零成本口径),结论与直觉相反:

ATR桶 毛R 净R @2/0.8bp 净R @6/2bp
<6bp 1.156 0.025
6-8 1.160 0.527
8-10 1.227 0.736
12-15 1.203 0.870
>30 0.940 0.829

低 ATR 桶的毛 R 不但不差,还是最高的一批1.16 vs 高 ATR 桶的 0.94)。 断崖只在扣费之后出现。所以「低波动时段信号变差」是错的说法, 正确说法是固定成本在低波动时占比过大

推论:门控阈值是费率的函数,不是市场常数。 换 VIP 档 / 换返佣 / 换交易所都要重算,不能抄:

单边 taker 最优 ATR 阈值
0(假想) 5bp
1.5bp 8bp
3bp 9bp
6bp 12bp

大致 阈值 ≈ 5 + 1.1 × taker费(bp),亚线性。

实际费率(2/0.8bp)下的最终口径——决策用这一版

口径 笔数 平均费 净bp 余量bp PF 剔10%PF 均R R夏普
现用 SL1.5/TP3/48 17734 2.00bp 18.3 13.06 2.73 1.96 0.702 0.482
最优 SL2 分批→8 留损2/48 17734 2.99bp 31.9 21.45 4.18 2.85 0.958 0.639
最优 + ATR≥8bp 门控 13929 3.00bp 36.5 25.39 4.23 2.98 0.987 0.662

逐年(最优 + 8bp 门控,样本外):

ATR中位 无门控余量 门控余量 保留% 笔/周 剔10%PF 均R
2021 牛 22.1 37.47 37.80 98.6% 55.5 3.41 1.064
2023 9.8 14.84 19.45 63.5% 28.4 2.84 0.982
2025 11.6 16.73 20.79 71.2% 45.5 3.11 1.007
2026 熊 8.8 11.21 15.19 55.4% 27.5 2.51 0.824
  • 门控是自适应的:高波动年份几乎不触发(2021 保留 98.6%), 低波动年份才发力(2026 保留 55.4%、余量 +36%)。不是拟合出来的常数
  • 费率降低后门控的边际价值也降低:旧费率下门控带来 +5.6% 均R, 实际费率下只有 +3.0%。阈值曲线在 512bp 之间很平(均R 0.9720.987), 8bp 是峰值但不敏感,不必纠结精确值
  • 影子交易判据:14~15bp(2026 最差年份口径)。近两年合计是 19.17bp, 全样本外 25.39bp。用 2026 那个数做及格线,别用平均值

与旧 3.91bp 的差距来源未完全对齐:旧数字来自 step23(2.28 年数据、 3578 笔、毛均收益 0.0991%),本步是 7 年、25476 笔、毛均收益 0.2027%, 且滤网口径可能不同(§5.3 原文写的是「1m 同向信号」,未提阶梯), 费率口径也已改成混合 maker/taker。在重新对齐之前,两个数字不要混用。

风险点:入场条件恰好是「收盘突破转强」,那一刻价格正朝我们的方向跑, 所以延迟造成的是系统性的追高/追低,不会正负抵消。这正是 「回测漂亮、实盘歇菜」最常见的具体机制。

5.4 实时计算窗口(step39,已跑完)

research/step39_pit_1m.py(新写,已跑完:3 币 × 每币 60 信号 = 180 笔抽检):

窗口(根) 覆盖天数 同根命中 ±3根内 完全消失 同向过滤也成立 假阳性 耗时中位 耗时P95
2000 1.4 100.0% 100.0% 0.0% 100.0% 0.0% 0.20s 0.22s
4000 2.8 100.0% 100.0% 0.0% 100.0% 0.0% 0.40s 0.42s
8000 5.6 100.0% 100.0% 0.0% 100.0% 0.0% 0.81s 0.84s
16000 11.1 100.0% 100.0% 0.0% 100.0% 0.0% 1.68s 1.81s

分币种(最大窗口):BTC/ETH/SOL 各 60 笔全部 100% 命中,零偏移。

结论:1m 在 2000 根窗口(1.4 天)就已完全饱和,单次计算 0.20s,假阳性 0%。 比 15m/30m 的 step38 结果还干净(那里有 0.7% 假阳性)。耗时对窗口严格线性 (约 0.105ms/根),所以没有任何理由带更长的历史。

⚠️ 「假阳性 0%」是 n=180 的结果,不足以排除 0.5% 量级的重画 2026-08-28 更正)。若真实率为 0.5%,180 笔里期望仅出现 0.9 次—— 0% 与 0.5% 在该样本量下无法区分

实测反例:web 端 BTC 1m(10 万根窗口),同一份数据分别截到本地 22:25 与 02:08 两个视角,212 个信号中 1 个消失08-27 22:19 的 B4,约 0.47%), 与 15m/30m 的 0.7% 同量级。用户在界面上先看到、后消失,即此现象。

缓解事实:消失的那个 htf_agree=False, ladder_ok=False,是浅色 b4 本就不交易。 真正要回答的是「双过滤通过的深色信号会不会重画」—— step39 报的「同向过滤也成立 100%」同样基于 n=180,同样不足以排除低频事件。

⚠️ step39 的「假阳性」测法本身是无效的:它从全序列随机抽非信号点,看时点 重建会不会凭空冒信号。1m 信号密度约 474 根 1 个,180 个随机点期望只撞上 0.38 个——测出 0% 几乎不含信息量。重画只发生在「差一点就成型」的结构附近, 不在随机点上。

5.41 重画的根因:available_ts 取的是中枢结束而非形成 ⚠️⚠️

代码审计(比逐根跑数据快得多):find_fast_bsp3 给定 zones 后严格因果 (只用 close[j] / high[j-1]),加未来K线动不了已成型的入场点。 重画只可能来自 zones 表被修订。

zones_from_zs_list 里:

last_bi = bis[-1]                      # ← 中枢的最后一笔
avail = ts_of.get(sure_key) or ...     # available_ts = 它的确认时刻

用户 2026-08-28 指出的缠论定义问题:中枢形成只需三笔有重叠区间; 结束才需要「离开且不返回的笔」确认。判信号只需形成,不必等结束。 而 bis[-1] 只有中枢走完才知道是哪一笔——取的是结束时刻

实测(BTC 1m,30 万根,1651 个中枢):

中枢笔数 占比
恰好 3 笔 25.5%
>3 笔 74.5%(中位 5、均值 8.1、最大 89

「最后一笔确认」比「第三笔确认」晚:中位 62 分钟、p75 142、p90 247、最大 1739。 1m 上 62 分钟就是 62 根 K 线。

三个后果:

  1. 这就是重画源。 中枢每吸收一笔,bis[-1] 就后移一次。300 时点抽样、 3284 个「当时已生效」的中枢:完全一致 84.4%,确认时刻被改 6.5% (推后 198 个 vs 提前 17 个,中位 +100 分钟、p90 +413,中枢消失 9.0%, 阶梯翻转 2.6%。用户看到的 08-27 22:19 B4 消失即此。
  2. 它解释了 docstring 里那个 34%。 「627 个中枢只认 212 个(34%),被拒的 多数是『中枢确认时价格早已离开、此后再没回来』」——「价格早已离开」不是 市场现象,是这个定义造出来的:中枢正是被离开笔终结的,所以扫描起点天然 落在离开之后;代码又要求 was_inside,于是只能等价格再次回到中枢再突破 一次。那 66% 多半不是没机会,是第一次离开时还没开始看。
  3. 方向对回测有利、对实盘不利。 全量的 available_ts 系统性更晚 → 回测扫描起点比实盘晚 → 回测偏保守,不是被高估;但实盘会产出更多、更早 的信号,这部分质量不在回测统计里。

关键性质:bis[2] 是不变量,bis[-1] 不是。 用户 2026-08-28 补充的 判断——「只有没确认的才会重画,确认的都不会」——与实测一致:6.5% 的改动 不是已确认的笔被推翻,而是中枢又吸收了新笔、bis[-1] 变成了另一根笔。 原来那根笔本身没变。而中枢一旦由三笔构成,第三笔就固定,不随延伸改变。

A/B 实测(BTC 1m300 时点,3284 个已生效中枢):

口径 完全一致 确认时刻被改 中枢消失 改动中位
现行 bis[-1](中枢结束) 84.4% 6.5% 9.0% +100 分
改用 bis[2](中枢形成) 89.7% 1.2% 9.0% +16 分

bis[2] 把该重画源压到 1/5。 两种口径全量中枢数都是 1651——纯粹改变 「何时可用」,不增删中枢。

改成「第三笔确认」的预期收益:消除该重画源(第三笔确认后不再变)、 符合缠论定义、滞后大幅下降(§3.2 已证滞后是收益第一驱动)。

⚠️ 剩下 9.0% 的「中枢消失」两种口径完全相同,是另一个源,与笔确认无关 且在改用 bis[2] 后成为主要重画来源。最可能是窗口左边界效应:2000 根窗口 截断笔结构,造出全量视角里不存在的中枢。

⚠️⚠️ 由此牵出一个此前未记录的口径差:回测用全量历史建中枢,实盘用 2000 根 窗口。 若那 9% 确由左边界造成,则它不是重画,而是回测与实盘看到的中枢集合 本就不同——比重画更根本。待查。

⚠️ 但不要直接改。 这会换掉整个信号总体,本文档所有数字都绑定当前实现。 反向风险明确:中枢形成即可用意味着会去做「仍在形成中」的中枢的突破, 价格可能再回来——信号变多但质量可能变差。必须 A/B 实测。

A/B 已跑完(step472026-08-28):bis[2] 作废,不要再试。 详见 §5.42。它把重画压到 1/5 的同时,把毛 R 从 0.933 打到 −0.000—— alpha 归零,不是成本问题。 下面这段「待办」保留仅作推理记录。

(已完成)available_ts = bis[2].sure_time vs bis[-1].sure_time 的完整 A/B (信号数、滞后、PF、剔10%PF、滑点预算),以及深色信号的 大样本重画审计(脚本已写:research/step45_repaint.py)。

对实盘的影响有限但真实:实盘会比回测多开极少量的仓,这部分质量不在回测统计里。 但出场(止损/止盈/超时)不依赖信号是否仍在图上,不会出现「信号消失、仓位卡住」。

这一步顺带解决了一个更重要的问题1m 的回测口径本身是可信的, is_sure 回撤对 1m 同样没有影响。1m 现在唯一的风险就剩执行成本。

⚠️ 延迟预算的分解(这直接决定 1m 生死):

环节 实测 说明
信号计算 0.20s 2000 根窗口,可控
走代理访问 Bitget 约 2.4s 单次 REST 往返(含建连),这才是瓶颈

计算只占延迟的一小部分,网络是主要来源。所以影子交易器必须: 用 WebSocket 订阅而非轮询 REST 拉 K 线,并尽快把实盘迁到境外 VPS。 否则测到的滑点全是代理的账。

5.42 A/B 判决:bis[2] 把 alpha 打成零,重画是必付代价(step47)

8 个样本外币 × 30 万根 1m,两组共用同一个 TF_DF,只切 available_ts 的取法。 实盘口径(深色 ∧ ATR≥8bp):

bis[-1] 现行 bis[2] 中枢成立
笔数 955 989
滞后 2.16 2.01
胜率 68.3% 40.2%
毛 R 0.933 0.000
净均 R 0.798 0.147
R 夏普 0.532 0.107
PF 3.22 0.80
剔10% PF 2.35 0.55
滑点余量 15.07bp 2.20bp

判决依据是「毛 R 0.933 → −0.000」这一行:扣任何费用之前 edge 就没了, 所以不是成本、不是门控、不是出场参数的问题,是信号本身不再有预测力。 逐币 8/8 全部变差,只有 BTC 勉强为正(0.617 → 0.116)。

为什么bis[2] 只要三笔重叠就认为中枢可用,此时中枢尚未发育, 支撑/压力还没立住。bis[-1] 那段「等待」不是可以优化掉的延迟——它就是 alpha 本身

由此得到一条一般性结论,值得推广到别的"降延迟"想法上:

右边缘重画不是 bug,是这个信号质量的必付代价。任何以「让信号更早确定」 为目标的改动,都要先测毛 R,不能只测重画率或滞后。 §5.41 只测了稳定性就给出「唯一能同时改善收益与稳定性」的判断,是过早的。

顺带交叉验证:现行口径本次算出滑点余量 15.07bp,与 §5.3 里 2026 组合口径的 15.19bp 基本吻合——两条独立路径得到同一个数,该预算值可信。

脚本 research/step47_avail_bi_ab.py;开关在 chanlun/analysis/fast_bsp.pyAVAIL_BI_INDEX(环境变量 CHAN_AVAIL_BI),默认 1,保持现行口径

5.5 增量更新已验证:一致且快 12 倍(2026-08-28

pipeline/builders/incremental.py 此前一直标着「需重新验证」。已验完。

一致性:400 根、每 20 根与全量重算对拍一次(共 20 次), 笔数 / 中枢 zg·zd / 信号 entry_idx 全部相同,无漂移。

耗时(本机 arm64 单线程,1m 2000 根窗口):

环节 增量 全量重算
TF_DF / append_bar 14.0ms 192.5ms
中枢 + find_fast_bsp3 7.6ms 10.1ms
1m 侧合计 21.7ms 202.6ms 9.3x
5m 侧(append_bar 7.1 + 分型线 2.9 10.0ms/次 84.4ms 每 5 根一次 → 摊 2.0ms
完整一根 ≈24ms 286ms ≈12x

⚠️ 必须定期重建窗口,否则增量的优势会被自己吃掉。 append_bar 不是 O(1)——pd.concatadd_indicatorscal_bi_list 三处 仍是全量 O(n),而 dataframe 只增不减:

1200 根后行数 中位 前100根 → 后100根
不裁剪 3200 16.3ms 13.9 → 19.4+40%
每 500 根重建 2199 14.4ms 14.2 → 14.0(持平)

IncrementalBuilderMixin 没有裁剪接口,做法是每约 500 根用最近 2000 根 重新 init_stream。单次约 192ms,摊到每根 0.4ms,可忽略。

下一个数量级的线索(用户 2026-08-28 指出)add_indicators 算了很多本策略用不到的指标。它在 append_bar 里是每根全表重算的, 所以浪费不是一次性的,而是每分钟一次、且随窗口长度线性放大。 改它会动到 dataframe 的列集合,web 与回测都依赖,需整体评估。

后续实测(见 §5.6推翻了这条线索的份量add_indicators 只占全量 构建的 1.3%,talib 是向量化 C,便宜。真正的浪费在 ChanKLU.set_indicatorsChanKLC.cal_all_ema_status。方向对(确实有大量无用计算),位置错了。

这是延迟这块唯一有数量级收益的方向find_fast_bsp3 本身只占 0.75ms (全链路的 0.3%),优化信号代码毫无意义;95% 的时间花在 TF_DF 从头重建 2000 根上,而实盘每分钟只新增 1 根——重算了 1999 根没变的东西

服务器侧实测 1m 那条腿 695ms(本机同口径 202.6ms,慢 3.4x)。若两条腿 同比例,那边完整链路约 980ms,已超 §6 定的 800ms lag 告警线,且尚未计 任何网络耗时。改用增量后应降至约 82ms。⚠️ 该外推假设两条腿慢的比例一致, 服务器侧应直接实测一次完整链路。

§5.6 优化后本机复测(同口径 2001 根、单线程、从头算一遍)

口径 优化前 现在 full 现在 lean
1m 腿 202.6ms 71.8ms 50.0ms
完整链路(两腿+信号+过滤) 286ms 178.4ms 120.5ms
增量 append_bar 24ms/根 13.6ms/根

按 3.4x 换算到服务器:完整链路 980ms → 约 611ms(full) / 413ms(lean) 即使完全不上增量也已落回 800ms 告警线以内;上增量约 46ms。 ⚠️ 但 3.4x 是在优化前的代码上量的。优化把工作从逐行 Python 对象操作挪到 numpy 批量操作,若服务器慢在 CPU 主频则比值成立,若慢在内存带宽则未必。 服务器侧必须直接实测,不要只信这个换算。

为什么这一步必要:step38 只验证了 15m/30m,从没验证 1m。而窗口 4000 根 对 15m 是 41 天、对 1m 只有 2.8 天,中枢的左边界效应完全不是一个量级。 窗口同时牵动两头:太短则中枢被截断信号不符,太长则算得慢延迟大滑点高。

5.6 引擎提速 2.6~3.6x,逐位一致(2026-08-28

先建了 step46_engine_parity.py 作为安全网:对 5 个用例(BTC 1m/5m、ETH 5m、 SOL 15m、XRP 30m,各 2 万根)固化 klc/笔/中枢/信号/被消费列的哈希。 没有它不要碰引擎——行为变化是静默的,不报错、不崩,只是信号悄悄换一批, 而 HANDOFF 全部数字都绑在当前实现上。

三处改动,每处都过了对拍:

改动 原因 效果
cal_kl_data 预取 ndarray,不再 df.iloc[i] 每根新建 40 列 Series + 在其上做几十次逐键查找 这一处就占构建的 96%2 万根 1946ms → 824ms
ChanKLC.cal_all_ema_status 改惰性 每 KLC 立即重算,占 25%,而全仓无任何读取方 调用 14322 → 2248 次
get_klc_list 里的 ema_up_list/ema_down_list 累加一整轮后直接丢弃,纯死代码

另外加了 TF_DF(..., lean=True):只构建到中枢,跳过线段/走势中枢/整套 MACD 状态机(这些只服务 bsp_list 和 web 展示,笔与中枢不依赖)。 已验证 lean 与 full 的笔/中枢/信号在 5 个用例上完全一致。

结果(2 万根 5m):full 1946 → 754ms2.6x),lean → 543ms3.6x。 增量路径在两种模式下都仍与全量逐位一致;web API 全字段正常(full 模式一字未动)。

验证做了四层,每改一处都重跑:

  1. 对拍基线(上表所列全部哈希项),full 模式三处改动后全部一致
  2. lean ≡ full:笔/中枢/信号在 5 个用例上完全相同
  3. 增量路径init_stream + append_bar 追加 150~200 根 vs 全量重建, lean/full 两种模式都逐位一致
  4. web 冒烟:真实 HTTP 请求,bsp_list 168 / seg_list 177 / zs_list 17 / klc_trend 齐全

大样本对拍(20 万根 × 5 用例):用 git stash 切回改动前的原始代码存基线, 再切回优化版对拍,逐位一致。这是真正的改前/改后比对,不是自己跟自己比。 同一批工作量 99.9s → 43.3sfull 模式 2.3x,与 2 万根时的 2.6x 一致, 说明提速不随规模衰减。复现:

git stash push -- chanlun/
python step46_engine_parity.py --save  --rows 200000 --out step46_baseline_big.json
git stash pop
python step46_engine_parity.py --check --rows 200000 --out step46_baseline_big.json

关键认识订正:

  • 缩放是线性的,不是 O(n²)。中途一度量到"数据 6 倍、耗时 44 倍",是我自己 开的 tracemalloc 污染了计时。干净重测每翻倍 ×2.06~2.2016 万根 lean 4.2s。
  • add_indicators 只占 1.3%,删无用指标在这里几乎省不到时间。 它有 11 个列(bbup365/bblow30/bbp302 等)Python 与前端都无人读取, 但它们不进 KLU,唯一成本是 web 响应体积(约占 45 列中的 11 列)。
  • 实盘延迟已不是瓶颈:append_bar 约 32ms/根,对 800ms 告警线有 25 倍余量。 继续优化只对研究吞吐有意义。

剩余热点(lean、8 万根口径):cal_trendset_indicators_from 各约 0.36~0.59s。 cal_trend 不能跳过——bi.py:221klc.trend,笔的计算依赖它; 它带序列状态(last_trend + 近 5 根窗口),向量化风险高,收益约 20%,暂不做。


6. 接下来要做的事(按优先级)

第 1 步:跑完 step39,确定实时窗口 已完成

结果见 5.4 节。结论:影子交易器用 2000 根 1m 窗口,单次计算 0.20s。 完整输出在 research/out/step39.logstep39_pit_1m.csv,无需重跑。

(若日后要重跑:python research/step39_pit_1m.py --symbols BTC,ETH,SOL --probe 60 --workers 3,约 4 分钟。瓶颈不在窗口重建,而在 run_one 开头 那次 120 万根 1m 的全量 TF_DF。)

第 2 步:向用户确认交易所 已定:Bitget + Hummingbot

他已选定先只上 1m(在我问「先从哪条腿落地」时选的 1m_first)。

延迟已实测完成(2026-08-27,服务器侧)

四路对照(宿主机 ccxt.pro / 宿主机原始 WS / 容器原始 WS / 容器 Hummingbot, 同一批 K 线对齐),把最初测到的「Hummingbot 慢 1030ms」拆开了:

  • 容器网络 2~18ms
  • Hummingbot 自身处理开销 10~30ms(不慢反快)
  • 剩下 1350~1480ms 全在上游连接器的一个 bug 上

Bug:Bitget 换根时推的是带两根 K 线的消息 [上一根, 新一根] 而上游解析写的是 data["data"][0],拿到的是上一根;新一根要等下一条 单元素消息、约 1.1 秒后才进 deque。ccxt 遍历全部元素,所以没这问题。

修法:不能简单改成 [-1]——那样上一根的收盘价会永远停在换根前 约 1 秒的那次推送上,而我们的信号对 0.25bp 的扰动都会换掉一半结果, 收盘价偏一个 tick 不可接受。正确做法是处理消息里的全部元素: 前面的就地写回,最后一根交基类 append。

20 分钟 / 60 根配对验证:

上游 lag 补丁后 lag 上游漂移 补丁后漂移
BTC 1454ms 547ms 0.81bp 0.50bp
ETH 1683ms 506ms 1.20bp 0.66bp
SOL 1408ms 642ms 1.29bp 0.87bp

补丁后与原始 WS 只差 5~14ms,贴着理论下限;19 根已收盘 K 线 OHLCV 逐根相同。

漂移 0.50~0.87bp 对 15.19bp 的预算只用掉 6%,延迟这一关过了。

⚠️ 但这是无条件漂移(60 根里绝大多数是普通换根),而我们只在 「收盘突破转强」那一刻入场,那一刻价格正朝我们方向跑。§3.2 已量化 滞后与收益严格单调且是系统性追高。信号根上的条件漂移预计显著更高, 影子测量必须按信号根条件化统计,见第 3 步。 另外测的是 BTC/ETH/SOL——既是流动性最好的,又恰好是样本内那三个; 真正要跑的 8 个样本外币盘口更薄,至少补测 TRX 和 ADA。

容器内可行性(同批确认)

Python 3.13.14 + pandas 3.0.5 + numpy 2.4.6,与本机 .venv 的 pandas 同版本。 同一份切片喂进去,三个币的信号下标、中枢数、中枢 checksum 全部逐一相同 容器内 0.26s/币 比本机 0.29s 还快。chanlun 直接挂载进容器即可, 不需要另起信号服务。(装进现有 .venv 走不通:Hummingbot 要 numba>=0.61.2aiohttp<3.14,与本机 Python 3.14 冲突。)

2000 根 1m 够取:单次上限 1000、分两页,1m 限 30 天。

补丁落地方式:子类覆盖(已定)

不改镜像,用子类覆盖连接器的解析方法,升级 Hummingbot 不冲突。

⚠️ 这个方案有一个缺口必须堵:如果上游把被覆盖的方法改名, 子类覆盖会变成死代码,静默退回 1.4s,不报任何错。 所以启动时要断言基类上确实存在该方法名(有条件的话连签名一起校验), 把静默失效转成启动即失败。

⚠️ 无论用哪种补丁方式,都要有运行时 lag 探针——补丁机制只防得住 「上游代码变了」,防不住 Bitget 再改一次消息格式:

  • 每根 K 线收盘记 本地接收时间 K线收盘时间
  • 最近 30 根取滚动中位数
  • 中位数 > 800ms 告警并停止开新仓(补丁后实测 506~642ms 理论下限约 500ms800ms 留足抖动余量又能对 1.4s 的退化一刀切死)

要停开仓而不只是打日志,因为损失是经济性且静默的—— 不会崩、不会报错,只会让收益慢慢变差,几周后才从统计里看出来。

第 3 步:写影子交易器测滑点(核心工作)

关键判断:测滑点不需要任何交易框架。 完整框架解决的是「如何可靠下单」, 而当前的未知量是「成交价会差多少」。所以先写一个不下单的影子跑法:

每根 1m 收盘 → 拉最新 K 线 → 算信号(窗口取第 1 步的结论)
           → 信号触发时抓真实盘口(bid/ask + 深度)
           → 按仓位吃单深度算出真实成交价
           → 等下一根 K 线出来,取其开盘价(回测假设的成交价)
           → 两者相减 = 真实滑点

必须把时间戳拆开记录,否则不知道该优化哪里:

时间戳 含义
t_close K 线收盘时刻
t_data 数据到手时刻 → 拉取延迟
t_signal 信号算完时刻 → 计算延迟
t_book 盘口快照时刻 → 下单时点

滑点应分解成三块:延迟漂移t_book 中间价 次根开盘价)、 盘口价差ask 中间价)、深度冲击(加权成交价 − ask)。 延迟漂移已单独测过(第 2 步,0.50~0.87bp 无条件), 但信号根上的条件漂移才是要测的量

形态已定:Hummingbot V2 controller(不再写独立 shadow.py

  • 信号承载在 V2 controller 里,chanlun 挂载进容器直接用
  • chanlun 计算走 ProcessPoolExecutor0.26s 是纯 CPU 且受 GIL 限制, 直接放进 async 会卡住事件循环
  • 滑点测量读连接器真实盘口,不用 paper trade 的模拟成交

必须记录的字段(否则数据回来无法对判据)

时间戳四件套,拆开才知道该优化哪里:

字段 含义
t_close K 线收盘时刻
t_data 数据到手时刻 → 拉取延迟
t_signal 信号算完时刻 → 计算延迟
t_book 盘口快照时刻 → 下单时点

每笔还必须记 atr_pct——判据是 bp 口径而 ATR 逐年变化(见 5.3), 不记 ATR 就无法把实测滑点换算成 R、也无法验证门控是否正确执行。

统计口径三条硬要求:

  1. 只统计通过全部滤网的信号根(同向 + 阶梯 + ATR ≥ 8bp 门控)。 在未过滤的根上测滑点会把判据算宽——那些单子我们根本不做
  2. 条件漂移与无条件漂移分开报。无条件值(0.5~0.87bp)已知, 要的是信号根上的值。两者的差就是「系统性追高」的大小
  3. 出场腿单独统计:止盈是 maker 不吃滑点,止损/超时是 taker 要吃。 §1.3 的费率模型按出场原因分别计费,滑点也必须这样分, 否则会把 60% 不吃滑点的止盈腿混进平均值里,低估真实成本

对判据时用每条 taker 腿的滑点(入场 + 止损/超时出场), 不是每笔的总滑点——余量 15.19bp 就是这个口径。

记录与报表已在服务器侧实现research/live/shadow_hb.py(采集)与 shadow_report.py(报表)。它的设计比研究侧曾经写过的那版好,不要重复造: 每个信号在 0.5s / 1s / 2s / 5s / actual 五个延迟上各测一次——同信号内的 受控对比,能直接读出「延迟压到 X 秒滑点是多少」,决策不被当前实现拖累; 另外还扫了仓位,滑点也已拆成漂移 / 价差 / 冲击。

判据常数留在研究侧research/lib/shadow_budget.py (逐币 BUDGET_BPATR_GATE_BPLEG_IS_TAKERlag_healthy()verdict())。分工的理由是这些数会变——2026-08-27 一天之内预算就动了四次, 费率也改了一次,写死在 live 侧的任何一份都会静默过期。

其他实现要点:

  • 数据格式必须与 lib/data.py 一致:timestamp(int64 ms), date(tz Asia/Shanghai), open/high/low/close/volume
  • 持仓也要影子管理:出场按 1m 自己的参数(3 ATR 减半 / 留损 2 / 目标 8 ATR / 48 根超时),出场同样记录真实盘口
  • 状态要落盘,重启不能丢

第 4 步:根据滑点结果决策

旧阈值(2.5 / 3.9bp)已作废:那是 TP=3.0、全 taker、原始费率记错 三重错误叠加出来的,见 5.3。新判据如下。

前提:1m 用自己的出场参数(SL2 / 3ATR减半 / 留损2 / 目标8ATR / 48根

  • ATR ≥ 8bp 门控 + 实际费率 2/0.8bp。

判据用 2026 那个最差年份的 15.19bp,不要用全样本的 25.39bp。 低波动环境是当前状态,不是尾部情形。

实测滑点(每条 taker 腿) 判断
≤ 5bp 1m 可行,各年份都有厚余量,进真实 dry run
5~10bp 可行但只在中高波动期,门控阈值要上调(见 5.3 的费率-阈值关系)
10~15bp 仅 2021 型牛市能做,常态环境不要开
> 15bp 1m 放弃

5m/30m 不受影响这一句仍成立(余量 26bp / 89bp,且那是旧费率下的保守值)。

另外两点:

  • 滑点必须用 WebSocket 测。代理下 REST 单次往返约 2.4s,而信号计算只要 0.20s(§5.4),REST 测出来的全是代理的账
  • 入场条件是「收盘突破转强」,那一刻价格正朝我们方向跑, 延迟造成系统性追高、不会正负抵消(§3.2 已量化滞后与收益严格单调)

第 5 步(后续):1m 与 5m 分实例

用户问过「1m 和 5m 分成两个实例跑呢?」——对,而且是硬要求 freqtrade 一实例只能一个 timeframe;另有资金池隔离、统计独立、 API 限流风险隔离三个好处。

⚠️ 有个坑要提前处理:两个实例可能在同一个币上同时持反向仓位 (1m 出三卖做空、5m 出三买做多),单向持仓模式下会互相平掉或直接报错。 要么开对冲模式,要么两个实例分配不同币种(币种够多,分开还能看出品种间差异)。


7. 环境与数据

7.1 数据

  • 位置:data/binance/futures/{SYM}_USDT_USDT-{tf}-futures.feather
  • BTC/ETH/SOL:全周期 1m1w21722543 天
  • 另有 8 个样本外币种(BNB/XRP/DOGE/ADA/AVAX/LINK/LTC/TRX): 48 个文件已全部校验,2020~2026-08-26,零缺口零重复
  • 读取统一走 research/lib/data.pyfetch_ohlcv(symbol, tf, limit) 本地优先,回落到 https://provider.jackyu66.com(该服务只有 BTC/ETH/SOL, 且小周期仅 90 天,别指望它)

7.2 代理

本地代理 127.0.0.1:7897。Binance 和 Bitget 的 API 都需要它。

7.3 已修过的两个 bug(别再踩)

  1. 时间戳精度lib/data.py):不能用 date.astype("int64")//10**6 该值单位取决于列精度([ns] 给纳秒、[ms] 给毫秒),对毫秒精度的文件 会把时间戳砸平,再被 drop_duplicates 删掉九成数据。 正确写法:(date - pd.Timestamp("1970-01-01", tz="UTC")) // pd.Timedelta("1ms")
  2. 相邻中枢撞同一 entry_idx:会让下游 set_index("entry_idx")InvalidIndexError。已在 find_fast_bsp3 末尾按 ["entry_idx","occ","zone_i"] 排序后 drop_duplicates("entry_idx") 去重。

7.4 跑长任务的注意事项

  • 用 shell 工具的原生后台执行(block_until_ms=0), 不要用 nohup——早期用 nohup 的后台任务多次莫名消失
  • 1m 全量数据(120 万根)的 TF_DF 约需 2 分钟,任何涉及 1m 全量的脚本 都要预留时间
  • 多进程用 ProcessPoolExecutor,记得在子进程里重新 sys.path.insertwarnings.filterwarnings("ignore")
  • 内存很大(用户说「随便用」),但 1m 全量 × 多进程仍可能吃掉几十 GB

8. 代码地图

8.1 研究库 research/lib/

文件 作用
data.py 数据层,本地 feather 优先
fast_bsp3.py 实现已移入引擎chanlun/analysis/fast_bsp.py),这里只剩转发导入。所有 step 脚本的 from lib.fast_bsp3 import find_fast_bsp3 不用改
nested_level.py build_htf_zones 同样移入引擎并转发;annotate_position 仍在本地
nested_bsp.py htf_fx_timeline / attach_htf_context:区间套上下文。
confirm_ts+period 修正 K 线收盘时刻
fx_signal.py 分型信号提取与背驰
breakout.py 事件驱动回测。run_trades 支持 entry_delay/slippage/
boost_dir(动态止盈,已验证无效)

8.2 缠论引擎 chanlun/

  • TF_DF(df, 1, tf) 是入口,.dataframe 拿到含缠论标注的 DataFrame
  • analysis/fast_bsp.py核心,自研第四类买卖点 B4/S4(滞后 2.2 根), 2026-08-27 从 research/lib/ 搬来,回测与 web 图表现在共用同一份代码。 搬运时逐条比对过 BTC/ETH/SOL × 15m/30m 六组,中枢与信号完全一致。 它不是「B3/S3 提前几根」:判据(收盘价实时 vs 笔端点事后)、方向来源 (突破侧 vs 离开笔)、选样口径(627 个中枢里认 212 个 vs 引擎发 625 个)都不同。 step30 同条件对拍见 §4——同一组过滤器把 B4 从 PF 1.59 提到 2.26,对引擎 B3/S3 无效(0.66→0.71);引擎那批胜率 27.4% 低于 SL1.5/TP3.0 的随机基准 33%, 是系统性反向样本,不是滞后造成的衰减 除 find_fast_bsp3 / build_htf_zones 外,还有过滤用的 add_zone_ladder (中枢阶梯,§1.4)与 htf_fx_timeline / attach_htf_agree(区间套同向,§1.1 第三层)
  • pipeline/builders/fast_bsp.pyTF_DF.cal_fast_bsp(),把上面那套包成 ChanFastBSP(类型 Chan_BSP_TYPE.B4/S4)。大级别由同一份 df 重采样得到, 配对表 FAST_BSP_HTF_PAIR 就是 §1.5 那张表。 不在 init_TF_DF 里默认计算,要显式调用
  • web 端:/api/analyze 返回 fast_bsp_list / element_fast_bsp_list / sub_sub_fast_bsp_list,每条带 htf_agreeladder_ok 两个过滤标志。 图上深色 B4/S4 = 两个标志都满足,浅色 = 未通过过滤
  • pipeline/builders/incremental.py:增量更新(init_stream / append_bar / replace_last_bar / rebuild_bi_zs)。注释写明「最后一笔 is_sure 允许收回」, 这是 step38 要验证的那个隐患(已证实无影响)。 实盘若要用增量而非全量重算,需重新验证
  • pipeline/orchestrator.pyTF_DF 方法的门面
  • web/:图表与分析服务,无下单/订单管理功能,实盘用不上

8.3 实验索引

step 一句话
1~14 早期探索:信号有效性、滞后测量、直接预测收益(后发现有未来函数偏差,已弃)
15~18 区间套雏形;fast_bsp3 诞生(降滞后)
19~20 级别配对批量扫描 + 并行化
21 最优配置的尽调(尾部依赖、成本敏感)
22 执行压力:收盘价 vs 次根开盘、滑点
23 费率分档 + 刷量测算1m 经济性的数据来源)
24 信号聚簇:同一大级别分型下的多信号是否独立(是)
25 同中枢重复入场(只做首次)
26 中枢阶梯序列(趋势 vs 盘整,印证缠论定义)
27 动态止盈(无效)
28 全级别矩阵(最优配置来源)
29 信号漏斗诊断 + 参数敏感性
30/31 引擎原生 B3/S3 对比 + 方向反转诊断(引擎信号因滞后而亏损)
32 消融研究(alpha 来自中枢上下文,非触发动作)
33 require_touch=False 的影响(显著提升)
34 tol 扫描(滞后与收益严格单调)
35 高收益审计(口径、滑点、并发)
36 偏差审计(生效时刻、多空、时间样本外)
37 跨品种样本外8 个新币)
38 时点重建(无未来函数)
39 1m 时点重建 + 窗口扫描2000 根窗口饱和)
40 第四类买卖点的过滤消融(web 端原始 vs 过滤)
41 出场口径全扫SL × TP × MAX_BARS × 分批 × 剩余半仓止损位 + 真实费率模型)。TP=3 截早了;分批要做但止损保持原位;SL=1.0 最差
42 1m 单独定出场(同一张全网格,11 币 7 年 25476 笔)。1m 右尾是其他级别 2 倍,TP 不能混用;SL2 分批→8ATR 留损2 48根 在均R/R夏普/回撤/剔10%PF 四项全赢,滑点余量 11.06→20.12bpMAX_BARS=48 反而不用改

输出都在 research/out/2026-08-27 清理过一轮:step1~20 的输出(早期方法论 已被推翻,含未来函数偏差)与旧口径备份一并删除,只留支撑当前结论的证据。 脚本都还在,需要时可重跑。step31 及之后的 .py 都在 research/ 下。


9. 与用户协作的注意事项

  • 用中文回复(用户规则)
  • 用户技术判断力强,会主动纠正方向(他纠正过我对区间套的理解、 指出内存回收、指出结论印证缠论定义)。他的领域直觉值得认真对待
  • 他反复强调不要再调参,要落地验证
  • 他讨厌长时间等待,早期多次问「还在跑吗」「好了吗」。 长任务要后台跑并主动汇报进度,不要让他干等
  • 报数字时必须交代口径(复利/杠杆/费率),否则会误导

10. 待办清单

  • step391m 时点重建 + 窗口扫描 → 2000 根窗口饱和,计算 0.20s, 假阳性 0%,1m 回测口径可信
  • 对齐 step23 与 step42 的 1m 数字3.91bp vs 11.06bp)。差距可能来自 数据年限(2.28 年 vs 7 年)或滤网(§5.3 原文只提「同向」,未提阶梯)。 §6 第 4 步的三条决策阈值全部依赖这个数字,对齐前不要据它做去留判断
  • 决定是否改出场口径(step41/42 样本外均已过,见 3.5 与 5.3)。 出场参数要按级别分开定,不能一套走天下。 5m/15m/30m 的首选是 「初始 SL 2.0 ATR、到 3 ATR 平一半、剩余半仓止损保持原位、跑到 8 ATR、 48 根超时」;若更看重单位风险期望而非回撤,初始 SL 用 1.5。 1m 用同一套形状,但 SL=2.0 是无争议的最优(均 R、R夏普、回撤、 剔10%PF 四项全赢,见 5.3),MAX_BARS=48 不变。 改的话 run_trades 要支持分批(现在只支持整仓单目标), 并重跑 step28/35/37 刷新本文档的年化/回撤数字——不要新旧口径混用。 1m 的并发已在 3.31 重算完(0.043→0.120,峰值 6),5m/15m/30m 尚未
  • 用实际费率(2/0.8bp)重算 step41/42 的分析段 → 1m 见 5.3 末尾 (均R +8%,判据 15.19bp);5m/15m/30m 见 3.5 末尾(余量只动 2%,结论不变)
  • ATR 门控搬到 5m/15m/30m 验证 → 惰性(30m 触发 0%、15m 0.16%、5m 2.6%), 可作全局规则 ATR ≥ 5 + 1.1×taker费(bp),当前即 ≥ 8bp
  • 确认交易所与框架 → Bitget + Hummingbot,先只上 1m
  • 测执行延迟 → 上游连接器 bug 已定位并修好,补丁后 lag 506642ms、 无条件漂移 0.500.87bp,占预算 6%。见 §6 第 2 步
  • 实盘信号计算改用增量(§5.5,已验证一致且快 12x286ms → 24ms)。 配套必须做窗口裁剪:每约 500 根用最近 2000 根重新 init_stream 否则 append_bar 的 O(n) 部分会让耗时持续爬升(1200 根后 +40%)
  • available_ts 改用 bis[2](中枢形成)而非 bis[-1](中枢结束)的 完整 A/B —— 已完成,结论是不换step47,见 §5.42)。 当时预判的「反向风险:会去做仍在形成中的中枢的突破,质量可能变差」 正是实际发生的事,且比预期严重:毛 R 0.933 → −0.0008/8 币全变差。 这条已关闭,不要重开。
  • 查那 9.0% 的「中枢消失」是不是窗口左边界效应(§5.41)。若是,则 「回测用全量历史建中枢、实盘用 2000 根窗口」是比重画更根本的口径差。 注意这条与 bis[2] 无关,没有被 step47 否掉,仍然要查
  • 深色信号大样本重画审计,脚本已写:research/step45_repaint.py (逐根时点重建,替换掉 step39 那个随机抽点的无效测法)。 §5.42 之后这条的意义变了:不再是为了「修掉重画」,而是为了量化实盘 会多开多少仓、那部分的质量如何——重画本身已确认是必付代价
  • 写 V2 controller + 盘口缓冲,跑影子测量(当前第一件事)。 字段与统计口径见 §6 第 3 步,三条硬要求别漏:只统计过滤后的信号根、 条件漂移与无条件漂移分开报、出场腿按 maker/taker 分开统计
  • 改掉 shadow_report.pyBUDGET_BP(当前 BTC 0.13 / ETH 4.02 / SOL 2.92)。那三个数由六处差异叠加而来:只有同向没有阶梯过滤、 费率按 6bp 双边 taker、TP=3.0、余量没除 taker 名义额、无 ATR 门控、 且 BTC/ETH/SOL 恰是 ATR 最低的三个币。正确值 8.58 / 20.64 / 16.83 直接从 lib/shadow_budget.py import。 这条优先级最高:报表里 drift > bdrift > b*0.6 是自动停机开关, 用错的预算会让它比真实情况早约五倍触发,误杀一个可行的策略
  • live 信号路径补上中枢阶梯过滤与 ATR 门控。现在是 fin = full[full["h1_agree"] == 1],只有同向。缺这两项测的就不是 我们要交易的那批信号,改常数解决不了
  • 子类覆盖加启动断言 + 运行时 lag 探针(>800ms 停开仓),见 §6 第 2 步
  • 补测 ADA / DOGE / AVAX 的漂移——真正要交易的是这批(预算 15~22bp)。 BTC/ETH/SOL 流动性最好,测滑点偏乐观是安全方向,但判可行性不能只看它们。 BTC 大概率不该做 1mATR 中位 2026 仅 6.5bp11 币最低), 门控刷掉 58.5%,修正后预算 8.58bp 仍是最低。TRX 2026 门控后只剩 4.2%
  • 收集 1~2 周影子数据,与回测口径逐笔对比
  • 按 §6 第 4 步的四档判据决策 1m 是否可行
  • 若可行:真实 dry run
  • 补一项研究阶段的缺口:资金费率从未计入任何回测。 注:1m 新参数下平均持仓 28.4 根 = 28 分钟,很少跨 8 小时结算点, 这一项对 1m 影响小;30m 腿才是真问题。 30m 腿平均持仓 6.5 小时会跨结算点,需要评估影响
  • 保证金约束仍未建模,且比原来估的要紧。原注「有仓位时间仅 8.6%、 预计影响小」是旧出场口径下的;新口径是 10.2%,峰值并发 6 且 92.7% 同向,平均杠杆 3.6x 时峰值约 21.6 倍名义额。见 3.31。 这条是扩币的前置条件——加币不分散,只把峰值敞口推得更高
  • 若要扩币:按 3.33 的两条标准筛(ATR 对门控 + 流动性), 并留一批筛完不看、直接进实盘验证,以保住样本外的说服力