否掉 bis[2]:修右边缘重画会把 alpha 打成零,重画是必付代价
§5.41 发现 available_ts 取「中枢最后一笔」是右边缘重画的根因,改取「第三笔」 能把重画率从 6.5% 压到 1.2%,当时据此判断它是「唯一可能同时改善收益与稳定性」 的改动。那个判断只测了稳定性,过早了。 8 个样本外币 × 30 万根 1m,两组共用同一个 TF_DF,只切 available_ts 的取法。 实盘口径(深色 ∧ ATR≥8bp,955 vs 989 笔): 毛 R 0.933 → -0.000 净均 R 0.798 → -0.147 PF 3.22 → 0.80 滑点余量 15.07 → -2.20 bp 判决依据是毛 R 那一行:扣任何费用之前 edge 就没了,所以不是成本、门控或出场 参数的问题,是信号本身不再有预测力。逐币 8/8 全部变差。滞后确实降了 (2.16 → 2.01),但换来的是另一批交易——两组重合度只有约 30%。 原因是中枢没发育完就下注,支撑/压力还没立住。「等中枢最后一笔」那段等待不是 可以优化掉的延迟,它就是 alpha 本身。由此得一条一般规则:任何以「让信号更早 确定」为目标的改动,先测毛 R,不能只看重画率和滞后。 开关 AVAIL_BI_INDEX 保留只为可复现该 A/B,默认 -1 维持现行口径。环境变量在 调用时解析而非 import 时——fork 启动的子进程会继承已 import 的模块,import 时读会固化成父进程的值。 顺带交叉验证:现行口径本次算出滑点余量 15.07bp,与用优化前代码算的同组同期 15.19bp 吻合。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+482
-6
@@ -267,13 +267,39 @@ push = z_above if direction == 1 else z_below
|
||||
|
||||
#### 3.33 扩币的筛选标准(两条方向相反的约束)
|
||||
|
||||
1. **ATR 分布对门控阈值**(当前 8bp)——小市值币波动大,这条更容易过
|
||||
2. **流动性 / 盘口价差**——决定滑点能否压进预算,小市值币更难过
|
||||
1. **ATR 分布对门控阈值**(当前 8bp)——够不够扛住固定成本
|
||||
2. **流动性 / 盘口价差**——滑点能否压进预算
|
||||
|
||||
**两条方向相反,所以最优区间在中间,不在两端。** 现有 11 币正好演示:
|
||||
BTC ATR 中位 2026 仅 6.5bp、门控刷掉 58.5%、预算 8.58bp 垫底(**大市值输在
|
||||
波动不够**);TRX 2026 门控后只剩 4.2% 的信号,当前环境基本不能做。
|
||||
最好的是中间那批:ADA 22.28、DOGE 18.55、XRP 17.04。
|
||||
**两条都是及格线,不是「越高越好」的排序依据。**
|
||||
|
||||
⚠️ **「那就做 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 分位数与盘口价差,**不必跑策略**
|
||||
就能排掉大半。
|
||||
@@ -282,6 +308,152 @@ BTC ATR 中位 2026 仅 6.5bp、门控刷掉 58.5%、预算 8.58bp 垫底(**
|
||||
全部为正」。若新币是在同一份历史上筛出来的,它们就不再是样本外。
|
||||
要保持这个性质,得留一批筛完不看、直接进实盘验证。
|
||||
|
||||
#### 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.87(ADA/AVAX/
|
||||
DOGE/ETH/LINK/LTC/SOL/XRP)、最差 17.61、中位 18.66,极差 2.26(12%)。
|
||||
⚠️ **这一条已被 §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 HKT,5 次快照取中位)。
|
||||
**净预算 = 回测预算 − $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,冲击占预算 1~8%
|
||||
(连 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 成交。** 服务器侧的
|
||||
@@ -314,6 +486,39 @@ BTC 5.87 vs 6.09、ETH 10.02 vs 12.06、SOL 8.92 vs 9.87bp。
|
||||
⚠️ 上面那批数字用的是 `毛均收益 − 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 完全来自缠论中枢的上下文定位,
|
||||
@@ -451,6 +656,8 @@ step41 首轮跑的是错误的 3/1bp(见 §1.3),已用实际费率重算
|
||||
| 同一中枢重复入场(二次、三次) | 质量骤降,**只做首次** | 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`)做大级别 | 滞后太大,且中枢极少 | 早期,用户也这么说 |
|
||||
|
||||
---
|
||||
@@ -707,6 +914,106 @@ step41 首轮跑的是错误的 3/1bp(见 §1.3),已用实际费率重算
|
||||
比 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` 里:
|
||||
|
||||
```python
|
||||
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 1m,300 时点,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 已跑完(step47,2026-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 现在唯一的风险就剩执行成本。**
|
||||
|
||||
@@ -721,10 +1028,164 @@ step41 首轮跑的是错误的 3/1bp(见 §1.3),已用实际费率重算
|
||||
用 **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.py`
|
||||
的 `AVAIL_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.concat`、`add_indicators`、`cal_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_indicators`
|
||||
> 和 `ChanKLC.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 → 754ms(2.6x),lean → 543ms(3.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.3s(full 模式 2.3x)**,与 2 万根时的 2.6x 一致,
|
||||
说明提速不随规模衰减。复现:
|
||||
|
||||
```bash
|
||||
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.20,16 万根 lean 4.2s。
|
||||
- **`add_indicators` 只占 1.3%**,删无用指标在这里几乎省不到时间。
|
||||
它有 11 个列(`bbup365`/`bblow30`/`bbp302` 等)Python 与前端都无人读取,
|
||||
但它们不进 KLU,唯一成本是 web 响应体积(约占 45 列中的 11 列)。
|
||||
- 实盘延迟已不是瓶颈:`append_bar` 约 32ms/根,对 800ms 告警线有 25 倍余量。
|
||||
**继续优化只对研究吞吐有意义。**
|
||||
|
||||
剩余热点(lean、8 万根口径):`cal_trend` 与 `set_indicators_from` 各约 0.36~0.59s。
|
||||
`cal_trend` 不能跳过——`bi.py:221` 读 `klc.trend`,笔的计算依赖它;
|
||||
它带序列状态(`last_trend` + 近 5 根窗口),向量化风险高,收益约 20%,暂不做。
|
||||
|
||||
---
|
||||
|
||||
## 6. 接下来要做的事(按优先级)
|
||||
@@ -1076,6 +1537,21 @@ API 限流风险隔离三个好处。
|
||||
- [x] **确认交易所与框架** → Bitget + Hummingbot,先只上 1m
|
||||
- [x] **测执行延迟** → 上游连接器 bug 已定位并修好,补丁后 lag 506~642ms、
|
||||
无条件漂移 0.50~0.87bp,占预算 6%。见 §6 第 2 步
|
||||
- [ ] **实盘信号计算改用增量**(§5.5,已验证一致且快 12x:286ms → 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.000,8/8 币全变差。
|
||||
**这条已关闭,不要重开。**
|
||||
- [ ] **查那 9.0% 的「中枢消失」是不是窗口左边界效应**(§5.41)。若是,则
|
||||
「回测用全量历史建中枢、实盘用 2000 根窗口」是比重画更根本的口径差。
|
||||
注意这条与 `bis[2]` 无关,**没有被 step47 否掉**,仍然要查
|
||||
- [ ] **深色信号大样本重画审计**,脚本已写:`research/step45_repaint.py`
|
||||
(逐根时点重建,替换掉 step39 那个随机抽点的无效测法)。
|
||||
§5.42 之后这条的意义变了:不再是为了「修掉重画」,而是为了**量化实盘
|
||||
会多开多少仓、那部分的质量如何**——重画本身已确认是必付代价
|
||||
- [ ] **写 V2 controller + 盘口缓冲,跑影子测量**(当前第一件事)。
|
||||
字段与统计口径见 §6 第 3 步,**三条硬要求别漏**:只统计过滤后的信号根、
|
||||
条件漂移与无条件漂移分开报、出场腿按 maker/taker 分开统计
|
||||
|
||||
Reference in New Issue
Block a user