From 34a8f37b39bc23f935555d5082fce8677064d1a0 Mon Sep 17 00:00:00 2001 From: jack Date: Fri, 28 Aug 2026 06:19:00 +0800 Subject: [PATCH] =?UTF-8?q?HANDOFF=EF=BC=9A=E6=9B=B4=E6=AD=A3=20cal=5Ftren?= =?UTF-8?q?d=20=E4=BE=9D=E8=B5=96=E9=82=A3=E5=8F=A5=EF=BC=8C=E8=A1=A5=20?= =?UTF-8?q?=C2=A75.6=20=E5=A2=9E=E9=87=8F=E8=90=BD=E5=9C=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原先写「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 --- research/HANDOFF.md | 54 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/research/HANDOFF.md b/research/HANDOFF.md index 9470c58..3c64b20 100644 --- a/research/HANDOFF.md +++ b/research/HANDOFF.md @@ -1392,12 +1392,60 @@ python step46_engine_parity.py --check --rows 200000 --out step46_baseline_big.j - **`add_indicators` 只占 1.3%**,删无用指标在这里几乎省不到时间。 它有 11 个列(`bbup365`/`bblow30`/`bbp302` 等)Python 与前端都无人读取, 但它们不进 KLU,唯一成本是 web 响应体积(约占 45 列中的 11 列)。 -- 实盘延迟已不是瓶颈:`append_bar` 约 32ms/根,对 800ms 告警线有 25 倍余量。 +- 实盘延迟已不是瓶颈:`append_bar` 约 32ms/根。 **继续优化只对研究吞吐有意义。** + > 「对 800ms 告警线有 25 倍余量」这个说法要小心,两处口径不对:单币的 + > `append_bar` 不是信号总延迟(`compute()` 全程 108ms,chan 构建只占约 + > 22ms),而多币是同一秒一起收盘、要串行清空的(十币 247ms)。另外 + > 800ms 哨兵测的是**数据到达**(本地接收 − K线收盘,实测 268~898ms), + > 计算是叠加在它之上,不共享那条预算。见 §5.6。 + 剩余热点(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.5ms(34%,为加一根重算 2001 行)+ +`cal_bi_list` 整表重扫 11.1ms(51%)+ `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 +构建收益有限,要继续压得看下游那三个。 ---