HANDOFF:更正 cal_trend 依赖那句,补 §5.6 增量落地

原先写「cal_trend 不能跳过——bi.py:221 读 klc.trend,笔的计算依赖它」。这条
不成立:221 行在 cal_trend 自己的循环里,读的是它自身的序列状态,不是
cal_bi_list 的依赖。1,800 根对拍定论——增量追加的 klc 其 trend 恒为 UNKNOWN,
与批量构建(trend 有值)逐字段相同。这处偏差是读代码读出来的,对拍一次就
定论了,同类判断优先用对拍。

另标注「append_bar 32ms 对 800ms 有 25 倍余量」的口径问题:单币构建不是信号
总延迟,多币要串行清空,且 800ms 哨兵测的是数据到达、不与计算共享预算。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jack
2026-08-28 06:19:00 +08:00
co-authored by Cursor
parent 0a0fd2f682
commit 34a8f37b39
+51 -3
View File
@@ -1392,12 +1392,60 @@ python step46_engine_parity.py --check --rows 200000 --out step46_baseline_big.j
- **`add_indicators` 只占 1.3%**,删无用指标在这里几乎省不到时间。 - **`add_indicators` 只占 1.3%**,删无用指标在这里几乎省不到时间。
它有 11 个列(`bbup365`/`bblow30`/`bbp302` 等)Python 与前端都无人读取, 它有 11 个列(`bbup365`/`bblow30`/`bbp302` 等)Python 与前端都无人读取,
但它们不进 KLU,唯一成本是 web 响应体积(约占 45 列中的 11 列)。 但它们不进 KLU,唯一成本是 web 响应体积(约占 45 列中的 11 列)。
- 实盘延迟已不是瓶颈:`append_bar` 约 32ms/根,对 800ms 告警线有 25 倍余量 - 实盘延迟已不是瓶颈:`append_bar` 约 32ms/根。
**继续优化只对研究吞吐有意义。** **继续优化只对研究吞吐有意义。**
> 「对 800ms 告警线有 25 倍余量」这个说法要小心,两处口径不对:单币的
> `append_bar` 不是信号总延迟(`compute()` 全程 108mschan 构建只占约
> 22ms),而多币是同一秒一起收盘、要串行清空的(十币 247ms)。另外
> 800ms 哨兵测的是**数据到达**(本地接收 − K线收盘,实测 268~898ms),
> 计算是叠加在它之上,不共享那条预算。见 §5.6。
剩余热点(lean、8 万根口径):`cal_trend``set_indicators_from` 各约 0.36~0.59s。 剩余热点(lean、8 万根口径):`cal_trend``set_indicators_from` 各约 0.36~0.59s。
`cal_trend` 不能跳过——`bi.py:221``klc.trend`,笔的计算依赖它; 它们带序列状态(`last_trend` + 近 5 根窗口),向量化风险高,收益约 20%,暂不做。
它带序列状态(`last_trend` + 近 5 根窗口),向量化风险高,收益约 20%,暂不做。
> **更正(2026-08-28**:原先此处写「`cal_trend` 不能跳过——`bi.py:221` 读
> `klc.trend`,笔的计算依赖它」。**这条不成立。** `bi.py:221` 在 `cal_trend`
> **自己**的循环里,读的是它自身的序列状态(前几根已处理 KLC 的 trend),
> 不是 `cal_bi_list` 的依赖。
>
> 实测定论:`init_stream/append_bar` 从不调 `cal_trend`(它只在
> `get_klc_list` 里),所以增量追加出来的 klc 其 `trend` 恒为 `UNKNOWN`
> 而批量构建的有值。`verify_incr_parity.py` 三币 1,800 根对拍两者**逐字段
> 相同**。所以 `cal_bi_list` 不依赖 `klc.trend``cal_trend` 对「bi → 中枢
> → fast_bsp」这条链是可跳的。
>
> 这处偏差值得记:它是读代码读出来的(把一个函数的内部自引用误当成外部
> 依赖),而对拍一次就定论了。同类判断优先用对拍。
### 5.6 增量在影子路径上的落地(2026-08-28)
`shadow_signal.compute` 已改为按 `(symbol, timeframe)` 缓存流式对象。
**前提必须先验。** `init_stream/append_bar` 没有 trim`dataframe`
`pd.concat` 无界增长,所以增量必然让窗口每根 +1,只能周期性重建拉回,两次
重建之间窗口是 `[W, W+500]` 而非恒定 `W`。若 `compute()` 输出随窗口长度变,
增量就等于静默换掉一批信号。`verify_window_sens.py` 三币 75 个信号窗口、
`+200/+500/+1000` 三档逐字段一致,前提成立。注意 §5.4 说的是「命中率在
2000 根**饱和**」——饱和不等于不变,那是两回事。
**重建不要用 `init_stream`。** 它逐行 `dataframe.iloc[idx]`,正是提速刚修掉
的反模式:2001 根要 238.5ms,批量 `TF_DF(df, lean=True)` 只 74.3ms,慢
3.2 倍。第一版用它重建,十币启动时各来一次,清空反而从 560ms 涨到 1686ms。
`append_bar` 能接在批量构建的对象上,`_ensure_stream_state` 会补出
`_klc_feed_last_klu`
**实测(2001 根窗口):** `append_bar` 21.8ms vs 批量 lean 重建 77.7ms =
3.56x。拆解 = `add_indicators` 全表 7.5ms34%,为加一根重算 2001 行)+
`cal_bi_list` 整表重扫 11.1ms51%+ `concat` 1.4ms。这两项都在引擎侧,是
下一步提速的着力点。
**十币 / 2 核的效果:** 清空 560→247ms,排队 92→10ms,纯计算 219→108ms
内存 597→598MiB(20 条缓存流的开销在噪声里)。
**瓶颈已经换位置了:** `inner_ms` 108ms 里 chan 构建只占约 22ms,其余 86ms
`build_htf_zones` / `find_fast_bsp3` / `attach_htf_context`。再压 chan
构建收益有限,要继续压得看下游那三个。
--- ---