 jackyu66gitandCursor
|
84ee59ecfb
|
research: B4 时点干净,但实盘做的不是回测那批单(实盘口径 PF 0.73 vs 回测 4.21)
step63 因果回放:B4 的时点完全干净——100% 召回、100% 准时、零滞后,
一类那个把 PF 从 2.35 打到 0.92 的坑(§3.396)B4 没有。
但回放多产出 592 个全量口径里不存在的信号,PF 0.46 / t −5.03。
step68 按实盘口径复测(2001 根滚动窗口、每 500 根 init_stream、只做当根收盘,
逐行对齐 shadow_signal.py),并把三道滤网全测一遍:
无过滤 789 笔,额外占比 75%,PF 0.64
三道全开 195 笔,额外占比 74%,PF 0.73
滤网把成交量砍掉 75% 却几乎不改变额外信号占比——按同比例刷掉好的和坏的。
拆开看:回测里也有的 51 笔 PF 4.21/t+5.90,回测里没有的 144 笔 PF 0.26/t−6.21。
即回测报的 4.21 拿不到:那 51 笔要事后全量重算才能识别,实盘当下分不出来。
机制是重画——实时算出的中枢,数据变多后被修正掉。与 §3.396 同类:
一类错在时点,B4 错在存在性。
顺带闭掉一条待办:2001 根窗口与 2万→4万根增长窗口跑出完全相同的 789/197/592,
窗口左边界效应判为否。
限定:本轮是 5m/30m 而实盘跑 1m,需单独复验;同向过滤器被开了未来函数后门
(HTF 时间线用全量算),真实盘只会更差。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 23:46:19 +08:00 |
|
 jackyu66gitandCursor
|
93ed315a4b
|
research: 一类线门槛量化——全局只有一个变量,精度需 67~73%
把 §3.3992 的天花板换成实时可算的 ext_run 选样配结构止损:5m 0.51、15m 0.48,
对比上界 2.29/4.11,兑现不了。但数字对不上(Q4 真端点浓度已 44%),拆开后
得到本轮最有价值的一张表:
ext_run 在真端点**内部**毫无反向选样(5m 各档 2.53/1.80/2.61/2.22 持平,
15m 单调递增到 6.10),在非真端点内部也毫无区分力(恒在 0.11~0.18)。
全局只有「是不是真端点」这一个变量在起作用,其余特征都是它的噪声代理。
这也修正了 §3.399:ext_run 的符号翻转不是拟合,它确实提纯(28.7%→44%),
只是幅度远远不够。
于是 PF 退化为两组按精度 p 的混合,解出盈亏平衡精度:5m 72.6%、15m 67.1%。
即要求实时判「这是不是那个底」的准确率达七成,而现在是 28.7%。
顺带解释了为什么 B4 能做而一类不能:B4 是突破后的延续信号,不需要判断反转;
一类的全部难度集中在这一个二分类上。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 23:17:48 +08:00 |
|
 jackyu66gitandCursor
|
ed741c16b8
|
research: 一类线重开——病根是选样×止损的交互,不是没机会
用户问「修改 B1/B2 的识别规则呢」,查下来推翻了 §3.399 的关闭结论。
step65 先量机会本身:直接取 seg_list(不经过检测器),线段中位幅度 11.4 ATR,
扣掉 2.9 ATR 确认成本还剩 8.5,是止损的 4.26 倍,93% 的线段装得下。
五币四级别一致。**滞后不是瓶颈**,与原先预期相反。
但这与 §3.397 矛盾(空间在却拿不到),step66 给出解答:之前六次进攻每次只动
一半。完美选样配 2ATR 止损是 0.70/0.83,无选样配结构止损是 0.36,
**两个一起是 2.29(5m)/4.11(15m)**,胜率 36%→63% / 44%→70%。是交互不是叠加。
机制来自 MFE/MAE:真底那批逆向行程中位仅 2.24 ATR,2 ATR 止损打掉了 51~58%
的好单;非真底那批逆向行程中位 4.76,放宽只是亏更多。固定 2 ATR 同时做错两件事。
⚠️ 上界含两个未来函数(线段端点选样、sure_time 入场),是靶子不是策略。
顺带证伪一个我自己的猜测:step58 首轮用 r_scale=True 把 3.9 ATR 止损对应的
runner 目标推到 15.6 ATR(比整段行情还长)。加 --abs-targets 改绝对目标重跑,
PF 仍是 0.36,与 r_scale 版完全相同。首轮结论正确,只是理由错了。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 23:09:38 +08:00 |
|
 jackyu66gitandCursor
|
380d6d61cd
|
research: 二类买卖点定性为无信息,一二类线整体关闭
用户提出悖论:二类按定义依赖一类(引擎里 B2 确实被 first_bsp_bi_div 门控),
一类既已证否,二类凭什么好。当时有个值得测的反驳——二类多要求「确实反弹」
且「回踩守住 B1 低点」,这是「底是真的」的事后确认,而 §3.397 的诊断恰恰是
一类缺这个确认。若成立,二类反而是一类里被验证过的子集。
测下来悖论成立,但机制不同:二类不是继承了一类的错,是信息为零。
一类 t = −17~−22(强烈指反,有信息只是方向被滞后翻了面),二类原方向
t = −0.8~−2.4、反手 +0.2~+1.7,两边都贴着零,连反手都没有。
另一发现是几何:二类的天然止损位是 B1 的低点,但反弹加回踩之后入场价已在
其上方 4.87 ATR(一类 2.90),2 ATR 止损有 99~100% 落在结构内侧。
step58 在一类上放宽到结构位只把 PF 从 0.22 抬到 0.36,二类缺口大 68%。
⚠️ 报表里二类「命中线段顶点 0.0%」是我用错口径,已在文档标注:二类按定义
是反弹后的更高低点,与线段顶点不可能重合,该指标只对自称在极值的一类有效。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 22:54:31 +08:00 |
|
 jackyu66gitandCursor
|
7292ef5dd4
|
research: 低滞后+质量过滤组合失败,过滤器符号翻转,一类线关闭
把 step62 的 ext_run 质量过滤接到 step56 的低滞后版上——两者各解决一半约束,
是唯一同时处理滞后和识别精度的路径。
失败,且失败方式本身是判据:过滤器符号反了。5m 上延伸度分档在滞后版是
Q1 0.12 / Q4 0.46(越延伸越好),在低滞后版是 Q1 0.58 / Q4 0.33(越短越好)。
叠加后 PF 从 0.37 掉到 0.30~0.33,比不过滤更差。div 同样翻转。
同一批信号、同一个特征,换个入场时点最优方向就反过来,说明这些过滤效果是
入场时点的交互产物而非信号的稳定属性,继续挑阈值就是拟合噪声。
一类线六次独立进攻全部止步 1.0 以下:引擎原生 0.24、反手 0.92(因果回放后)、
实时重写 0.41、结构止损 0.36、用未来函数选样 0.83、质量过滤 0.54、
低滞后+过滤 0.33。第五项尤其说明问题——即使选样做到完美也只到 0.83。
判定关闭。病根是入场价已在结构底上方 2.9 ATR、实盘再晚 15 根,来自「等笔确认」
机制本身而非参数。识别可以优化(精度能翻倍),但识别从来不是瓶颈。
fast_bsp1 顺带补 ext_atr 字段,用 ATR 归一才与 step62 的 ext_run 同口径。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 22:03:59 +08:00 |
|
 jackyu66gitandCursor
|
5695d8e983
|
research: 趋势末端识别(step62),ext_run 单调区分但 PF 仍不过 1
用户指出很多一二类实际在趋势中途被识别而非末期,若真在末期即使有延迟也该走出
行情。用 step60 的线段顶点当标签找实时可算的区分特征。
ext_run(极值越过中枢边界几个 ATR)单调有效:5m 上四分位的命中率是
12.0/22.1/37.0/43.8%,PF 0.12/0.11/0.22/0.46。短延伸那批就是趋势中途被识别的,
占一半且 PF 仅 0.11。最佳组合 ext_run≥P75 且 div≥中位:命中率 47.9%、PF 0.54,
相对基准 28.7%/0.22 精度接近翻倍。
两个反直觉结果:背驰越强反而越差(div Q1 命中 17.0%/PF 0.13,Q4 37.5%/0.28),
是对 MACD 面积判据的直接证伪;趋势级数无区分力(命中率 28.5/30.6/28.6/25.5%
基本持平)。
另修正一个我先前的猜测:以为引擎漏了缠论「趋势 vs 盘整」前提,实测该条件在
2504 笔上恒为 True——B1 要求 enter_bi.dir == leave_bi.dir == DOWN,中枢向下进
向下出本身就定义了它嵌在下跌趋势里,引擎已隐含强制,过滤器无从添加。
zs_count 也不可用,它是全局中枢序号而非趋势内序号。
结论:识别可优化且幅度不小,但不是瓶颈,瓶颈是入场时点。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 22:00:52 +08:00 |
|
jackyu66git
|
78708ddeee
|
research: 极值点波动率(step61),观察成立但既不解释滞后也不解释亏损
用户提出一二类长在极值点、该区域波动大、这可能是确认慢的原因。拆成三条
子命题分别测。
① 成立:5m 上 B1 的 atr_z 中位 1.224、74% 高于基准,而所有笔端点的基准恰好
落在 50%(构造正确的旁证)。但二类是镜像——B2/S2 的 atr_z 中位 0.94~0.97、
仅四成高于基准,长在低波动区,因为它是首轮反转冲动之后的回抽。所以
「一二类都在极值点」对一类成立、对二类不成立。
② 只沾边:corr(atr_z, lag_bars) 仅 +0.10,滞后中位在四个 atr_z 分档里是
8/7/8/9 根,几乎不动。滞后是结构性的,笔要等分型确认,与波动率基本无关。
③ 回落属实但不是死因:入场后 48 根平均 ATR 是入场时的 0.896,目标确实按虚高
ATR 定、绝对价格高估约 10%。但一类只有 9.4% 走到 3ATR 减仓(三类 30.7%),
81.3% 直接止损、超时仅 17.9%。若死因是目标够不着,超时占比该很高。所以一类
不是走不动,是入场后立刻反向——与 §3.397 的诊断一致。
|
2026-08-28 21:51:59 +08:00 |
|
 jackyu66gitandCursor
|
e137d92b50
|
research: 因果回放推翻一类反手(step59),线段顶点验证识别有效但不够(step60)
step59 逐根回放:init_stream 预热后逐根 append_bar,每根重算笔中枢与 bsp,
记录信号首现根并按它入场。信号身份用「类型+极值KLC时刻」而非 sure_time,
后者正是会被重画的字段。必须逐根,分段重建等于多给信息。
结果把 §3.395 推翻了:召回 100%、幻影 0,即存在性是因果的;但首现根比全量
sure_time 晚中位 15 根、P90 31 根,0% 能准时拿到。按真实首现根入场,
B1 反手 PF 2.35→0.92、S1 2.75→1.30,t 0.20/0.64 完全不显著。
教训:sure_time 是引擎事后标注的确认时刻,不等于可执行时刻。任何拿它当
entry 的回测都要先过逐根回放。
step60 用线段终点当标准答案验证识别本身。对照组取所有同向笔端点——B1 按构造
就长在笔低点上,不设这个基准任何绝对命中率都无法解读。5m 上 B1 命中 30.3%
对基准 15.0%,提升 2.02 倍,S1 1.81 倍;B3/S3 恰为 0%,符合三类长在趋势
中段的预期,两者互为标签有效性旁证。
所以识别是对的,但精度只有 30%,且那 70% 噪声 PF 只有 0.08。更关键的是即使
用未来函数把精度提到 100%,命中组也只有 PF 0.70~0.83,仍不赚钱——因为入场价
已在结构底上方 2.90 ATR。一类线三层逐层否定后到此为止。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 21:38:59 +08:00 |
|
 jackyu66gitandCursor
|
9efbae6ade
|
research: 结构止损对照(step58),止损确实太紧但不是主因
用户提出 B1 做多的止损可能挂在 B2 低点上方,于是在那次正常回抽处被打掉。
观察成立且比预估严重:入场价到结构极值中位 2.90 ATR,2ATR 止损落在结构位
内侧 0.90 ATR,88.6% 的一类做多价格不用回踩到前低就已出局。
修掉有改善但救不活:结构位外侧 1.5ATR 止损把胜率从 16.7% 抬到 33.1%、
PF 从 0.22 到 0.36,仍深度为负。同口径下反手做空 PF 2.15~2.53。
做这个对照时目标必须随止损等比放大(恒定 1.5R 减半/4R 收尾),否则放宽止损
却不放大目标会把盈亏比压到 1 以下,测出来的「放宽无效」是自证的。故
walk_exits 不能用,自带了逐笔止损的模拟器。
最有说服力的读法是结构+1.5 那档:止损宽达 4.4 ATR 仍有 67% 被打掉,即
三分之二的一类信号会在 48 根内跌破结构低点再多走 1.5 ATR。缠论里「B2 回踩
不破前低」在本市场多数时候不成立,趋势确实越过第二类买卖点继续走原方向。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 20:31:06 +08:00 |
|
 jackyu66gitandCursor
|
be3602f5ba
|
research: 一类反手(step57),六年五币双向全正,PF 2.3~3.0
用户问一类二类的识别是不是错了。查下来是代码没写错、信号该反着用。
先排除一个错误猜测:check_bi_div 只比 MACD 面积、不检查创新极值,等于把
缠论背驰定义丢了一半。看着像致命缺陷,实测 93% 的离开笔本来就创了新极值,
解释不了 PF 0.2。
真正的线索是胜率方向:B1 胜率 18.6%,而 SL2/TP3 随机入场约 40%,远低于
随机说明样本带信息只是指反了。拿相反方向重跑出场(路径依赖,不能取负号),
5m/15m 上 PF 2.35~3.03、t +10~+13。
step57 三关全过:5 币全正、前后半段 2.81/2.81 与 2.55/2.51 几乎不变、
2021~2026 连续六年全正、多空两边都正。余量 15m 33~76bp,B4 只有约 3bp。
机理是滞后把信号变成了相反的交易:信号在 leave_bi.sure_time 发出,中位滞后
8~9 根,此时价格已从低点反弹 1.68 ATR。引擎想说抄底,它给的时间戳对应的却是
反弹已走完——在下跌趋势里于此处做空是标准的顺势回调入场。与 B4 的突破延续
是不同的入场原型,可能互补。
三项验证未做完前不许上实盘:因果性(中枢右边缘已知会重画,需流式回放)、
消融(是不是反弹就做空都赚)、与 B4 的重叠度。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 20:12:11 +08:00 |
|
 jackyu66gitandCursor
|
409dc2f020
|
research: 实时版一类(step56),证明滞后不是病根,一类没有边
step55 判定引擎 B1/S1 不可用后,照 B3→B4 的路子做了实时版:把「中枢已成 /
向下离开 / 背驰 / 触发」四步全换成当根可判的代理,滞后从 8~9 根压到 ≤1 根。
背驰能实时判的关键是进入段面积在中枢确认时已是历史,只有离开段需要逐根累加。
没救回来。5m 上 fastB1 一买 PF 0.38 / 一卖 0.36,15m 同量级,比引擎版的
0.20~0.24 有改善但离 1.0 很远。
真正的价值在对照组和滞后分档两处:
- 同数据同出场同管线,fastB3 跑出 PF 1.83~2.06 / t +8.5~+10.7,排除了
「管线接错所以为负」。
- lag ≤1 根(≈买在极值上)那一档 PF 仍只有 0.40。即滞后清零也救不活,
§3.393 里「等 8 根导致几何劣势」的解释只对了一半。
结论与 §3.4 消融、§3.391 的 mom60 相互印证:这族信号的 alpha 在顺势延续上,
不在反转上。把反转信号提前,它还是反转信号。一类到此为止。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 19:55:23 +08:00 |
|
 jackyu66gitandCursor
|
30592889aa
|
research: 一二类买卖点可行性探针(step55),结论为不可用
用户提出把 B4 的研究思路搬到第一/第二类买卖点,并指定 5m/15m 测。
滞后先于收益测,结论是用户判断正确:B1/B2/B3 滞后中位都是 8~9 根,
三类共用 find_all_bsp 的「中枢 is_sure + 笔 is_sure + sure_time」,
滞后不是区分它们的变量。
收益全负,一类最差:5m 上 B1 PF 0.24 / 胜率 18.6% / t −17.3,
S1 PF 0.20 / 胜率 14.8% / t −22.3,15m 同量级。B3 跑出 0.64/0.76、
HANDOFF §4 记的是 0.66,口径校验通过,所以 B1/B2 的数可信。
一类烂得彻底是几何决定的:等 8 根后价格已朝上跑 1.68 ATR,新入场价往下
2 ATR 的止损落在比原始低点还低 0.3 ATR 处,几乎贴着极值。同样的滞后在
顺势突破上只是追高,在逆势反转上是加倍惩罚。
探针里修掉两个会静默出错的地方:cdf.date 是 datetime64[ms] 而
Timestamp.value 是纳秒,手工转 int64 比较会让 searchsorted 全部落到末尾
且不报错(这是之前跑出 0 条的原因);速率对照未按币归一,拿 5 币的数去
比 10 币的 B4 基线等于凭空打对折。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 19:48:59 +08:00 |
|
 jackyu66gitandCursor
|
6d93975e67
|
用 7 年长样本复核 step54:时段坐实无效,周日效应符号翻转、撤回
用户追问"你用的是长时间周期分析的?"。原答案是 1m / 18.5 个月 / 3941 笔,
而上一轮的结论是"没效果"——没效果最怕样本不够,这个追问戳到了点子上。
改用 step41 那份 5m/15m/30m 复核:2019-09 → 2026-08,2525 天,8168 笔。
口径能对上——keep = (h1_agree==1) & push 就是深色过滤,出场配置
s2_so8_k2_m48 正是实盘那套 2/3/8/2/48(cfg_name 的分批命名,scale_at 默认 3)。
唯一差异是没加 ATR≥8bp 门控,而 §3.5 实测它在这些周期上几乎不触发
(30m 0%、15m 0.16%、5m 2.6%)。
① 时段坐实无效。段间毛R极差的置换 p:5m 0.6185、15m 0.6687、30m 0.3105、
合并 0.6445,全部远离显著。1m 那个 p=0.0895 现在看清楚了,就是零分布里运气
略好的一条尾巴。
② 周末效应没复现,而且符号翻转。1m 上周末−工作日是 -0.132(p=0.0246),
长样本上 5m +0.014、15m +0.142、30m -0.006、合并 +0.041;周日从 -0.199
(p=0.0079)变成 +0.033。这不是严格的样本外复现——1m 与 5m 是不同的信号
总体——但若"周末流动性薄所以吃亏"是真的市场结构效应,它没有理由只在 1m 上
出现、在 5m 上还反号。
所以上一提交里"周日效应统计上真实"那句要撤回。本步一共跑了约 35 个分组比较
(24 小时 + 两套时段定义 + 7 个星期 + 周末/周日),冒出一个 p=0.008 恰是多重
比较的期望产物。HANDOFF 里已把该结论标为撤回并记下两条教训:报告"无效"之前
先确认样本量撑得起这个"无";在几十个分组里挑出的最显著那个,默认它是噪声,
除非能在另一个总体上复现。
实践结论不变且更硬:不加任何时间维度的过滤,mom60≥7 仍是唯一值得上的开关。
复核走 --long,复用 step41 已有 feather,未重跑采集。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 19:29:26 +08:00 |
|
 jackyu66gitandCursor
|
1ffc4fbb18
|
时段(亚/欧/美)是噪声,周日效应真实但与 mom60 过滤不可加
用户问哪个时段更容易盈利。答案分两半:时段这个切法本身无效,换成星期几才
有东西,而那东西不该做成新过滤。
① 亚/欧/美三等分(UTC 0/8/16),毛R 1.127 / 1.006 / 1.079,段间极差 0.122,
置换检验 p=0.0895——随便把 24 小时切三份,9% 的概率能切出这么大的差。更要命
的是美盘两个时期反号:样本外 1.158(最好)→ 发现期 0.885(最差),噪声的
典型指纹。按真实开盘时刻切五段、把欧美重叠单列,结论一样。
这里不是输给 ATR 混淆。亚盘 ATR 中位确实最低(12.5 vs 14.1),本来最该是
混淆源,但控 ATR 后段间极差 0.101/0.108,和无条件的 0.122 几乎一样——时段
不是 ATR 的代理,它本来就小。
② 星期几有信号,集中在周日:毛R 0.893、胜率 66.6%、PF 2.76、余量 13.08bp,
对照周五 1.228 / 74.7% / 4.78 / 23.44。置换检验周日 p=0.0079、周末 p=0.0246,
两个时期方向一致,10 个币里 7 个周末更差(BTC 最甚 -0.336)。但幅度在发现期
塌了大半(-0.168 → -0.039)。
③ 关键在重叠。施加 step53 的 mom60<7 之后,周末差从 -0.132 缩到 -0.058、
周日从 -0.199 缩到 -0.104。重叠不在笔数上(mom60≥7 在周末占 22.9%、工作日
21.3%,几乎一样),是伤害重叠:周末真正亏钱的是那些追已走完行情的单子。
周末流动性薄,追高的代价被放大——这和 §3.391「势不能过头」是同一件事在另一
个维度上的投影。
④ 所以不加。决策表(发现期总R)显示 mom60≥7 + 周日 在 0~20bp 每一档都输给
mom60≥7 单用(5bp: 574 vs 658;10bp: 343 vs 394;15bp: 113 vs 131),叠加
只是白丢 10% 笔数。单用砍周日也要 12bp 以上才赢过等权。
这一步的价值是排除。「美盘流动性好该更赚」这种直觉很难自证伪,跑完才知道它
连随机切分都跑不赢;而顺手捞到的周日效应统计上真实,却因与已有过滤重叠而
不可加——显著和值得做是两件事,中间隔着一张决策表。
分析全部复用 step53 的 feather,未重跑采集。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 19:23:39 +08:00 |
|
 jackyu66gitandCursor
|
17fe965a7c
|
HANDOFF 跟上服务端:5.72 标题回退到旧结论,四条待办已完成
拉取后对表,文档有几处和代码脱节:
1. §5.72 标题还写「inner_ms 的 3.3 倍是争抢」,而正文经 af029bc 已更正为
1.49x。扫标题的人会被带偏,改成 30ms 地板 + 37ms 缓存浪费 + 1.5x 争抢。
2. 「实盘信号计算改用增量」已上线(§5.7,清空十币 560→247ms),标完成,
并把「重建不要用 init_stream」这个坑记在同一条上。
3. 「shadow_report 的 BUDGET_BP」和「live 补中枢阶梯 + ATR 门控」都已做完
(前者改为从 lib/shadow_budget import,后者见 shadow_signal.py:11-18),
标完成并保留当初的理由,那两条的判断过程比结论有用。
4. §5.72 新发现的两个杠杆之前只在正文里,没进待办,补上:按币绑 worker
(省 inner_ms 三分之一)与 add_indicators 增量化,并写明二者是叠加不是
二选一,以及后者的拦路石是 Wilder RSI 的 avg_gain/avg_loss 状态。
另外给 mom60≥7 那条待办补一句现状:live 路径的三道过滤是同向 + 阶梯 +
ATR 门控,mom60 连算都没算,要上得先在信号侧补出这个字段。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 19:23:39 +08:00 |
|
 jackandCursor
|
15f4aa088e
|
加 Telegram 通知,并修好一道死掉的闸
接 Telegram 时查出 Guard.realized() 定义了但全仓库没有调用点——pnl_day
恒为 0,MAX_DAY_LOSS 完全不生效。三条硬约束里最重要的一条是死的。
根因是止损与止盈都挂在交易所侧成交,本进程收不到通知,而 sweep 只在 48
分钟到点才查持仓。连带第二个后果:execs 条目不清,MAX_OPEN 把已出场的
仓位继续算在场,新信号被白挡到截止时刻。
补 watch() 循环(10s):持仓消失即判出场,去 history-position 取
netProfit(= pnl + 资金费 + 开平手续费)记回闸并释放名额。盈亏取交易所的
数而不自己按标记价估——估会漏掉费用且方向总偏乐观。历史未落库时留到下轮,
不会漏记。字段名按文档与官方 TS 类型的差异同时兼容 ctime/cTime。
Telegram(live/tg.py,stdlib + aiohttp):推开仓、平仓带已实现盈亏、被硬
约束挡住、报错、对账平仓、跨日结算、启动与停机。不推信号过期跳过(常态,
搬运重连会重放旧信号)与心跳,否则真事会被淹掉。启动那条兼作通道自检。
研究侧 tg_notify.send 改为复用生产的传输层,方向与 signal_bus 一致。
status.sh 增加一条判读:开过仓但 pnl 仍为 0 就是 watch() 出了问题。
实测:8 类消息渲染、_match_hist 的过早/方向不符/币不符/驼峰字段/取最近
五种情形、100 USDT 下 SOL 与 ADA 的端到端空跑(两腿等量,50/50 精确)。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 17:30:11 +08:00 |
|
 jackandCursor
|
335d891478
|
生产与研究分家:实盘执行器独立成 live/ 子树,加 AWS 部署
实盘要跑在 AWS(API key 绑了 IP 白名单),而信号在新加坡那台算。借这次
把生产从研究侧摘出来,四条具体代价里第一条已经咬过:
1. live_state.json 原先落在 research/out/,而那里 shadow_hb 会自动 rename
归档、研究脚本会写、人也手工清过。那文件装的是 MAX_DAY_LOSS 累计与已
处理信号键,被清掉不报错,只是两道闸静默失效。改到 LIVE_HOME。
2. 采集器十币清空 300~560ms 直接叠在信号到达执行器的延迟上。
3. 研究侧探针 OOM 过一次(14.9GB),当时若有仓位在场会连坐执行器。
4. 为读两个常量 import 研究侧 step43,把 numpy/pandas/pyarrow 拖进实盘
进程。抽出 stdlib-only 的 live/exit_params.py,install.sh 加断言挡回归。
新增 live/ship_signals.py:AWS 侧 ssh tail 拉总线,每次重连从文件头重放
+ 按幂等键去重,断线期间的信号自愈;旧信号由 staleness 闸挡掉不补做。
带时钟倒流检测——两机时钟不同步会让那道闸静默放宽。
部署件:systemd 两单元(搬运挂了执行器仍管在场仓位的超时平仓)、
install.sh、dryrun.sh(验密钥/白名单/时钟/ssh/取整)、status.sh、README。
验证:live_exec 重构后端到端空跑,SOL 多头与 ADA 空头的止损/两级止盈/
数量取整逐项核对正确,isolated + post_only + reduceOnly 都在;搬运的去重、
重启不重复追加、脏数据跳过、断线重连重放均已测。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 17:03:03 +08:00 |
|
 jackandCursor
|
af029bc26e
|
更正上一提交:争抢是 1.5x 不是 3.3x,并发现按币绑 worker 可省三分之一
上一提交的 3.3x 基线是废的:离线每次喂同一窗口,append_bar 一根没追
(实测 6 次调用 stream 2001→2001 零增长),测的只是信号链地板 30ms,
拿它比在场 inner_ms 又是一次口径不对齐——和刚撤回的 22/86 同一类错。
对齐后:在场每次平均追 2.81 根(2 worker 各存一份缓存、各自漏掉对方
处理过的根),离线同口径 67.3ms,在场 100ms → 争抢 1.49x。
顺带修正「重建占 21.5%」:真重建只有 0.31%,此前把换 worker 的小幅
回退误判成重建。
新杠杆:symbol 固定到同一 worker,每次只追 1 根,离线 67.3 → 45.0ms,
在场约省 33ms/币(inner_ms 三分之一)。心跳判定改指这一刀。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 16:23:02 +08:00 |
|
 jackandCursor
|
cef894376c
|
定位 inner_ms 的 3.3 倍:是争抢不是算法档,撤回 22/86 拆分
服务端跑 probe_inner.py 与本机对表:分档占比一致(TF_DF 两腿 68~74%,
信号链 16~21ms),此前报的「chan 构建 22ms / 信号链 86ms」是无效减法
——孤立环境的 1m append 减在场十币的 inner_ms,还漏了 5m 腿。
真实构成:inner_ms 100ms = 约 30ms 计算 × 3.3 倍争抢。逐个排除
_rebuild(1.6ms)、币种差异、周期重建(21.5%/1.5x)、批内次序(相关-0.083)
后,用外生的到达密集度确认(67→117ms),并以注入合成负载复现
(2 个满载进程 2.68x,3 个 2.86x,在场实测 2.24~3.34x)。
心跳判定不再推荐「继续压算法」,改为加核或减币。
第一版用 t_signal-inner_ms 反推并发区间得相关 0.533,是循环构造,
已废弃并在 §5.72 记下这个坑。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 16:19:25 +08:00 |
|
jack
|
be442783a1
|
Merge branch 'chan' of ssh://git.jackyu66.com:2222/jack/chan into chan
|
2026-08-28 16:07:28 +08:00 |
|
 jackandCursor
|
f11c6507b0
|
实盘执行改走 Bitget v2 REST,止损挂到服务端
丢掉 Hummingbot 的 PositionExecutor。它的连接器只暴露 LIMIT / LIMIT_MAKER /
MARKET,没有触发单,于是 control_stop_loss() 只能本地盯价、触发时才发市价单
——**进程一死仓位就是裸的**。而交易所本身支持 place-order 带
presetStopLossPrice,下单时就把止损挂到服务端。绕过连接器不是图省事,是为了
消掉一整类故障。顺带 TripleBarrierConfig 只有单级止盈,装不下两级,自己写更短。
## 三条出场腿各自挂在哪
止损 交易所侧(presetStopLossPrice,随入场单一起到)→ 进程死了仍在
止盈 交易所侧(post_only reduce-only 限价) → 进程死了仍在
超时 本进程,48 分钟到点市价平
所以进程死掉只会让持仓超过 48 根,不会变成裸仓,退化是良性的。
## 止盈不能用 presetStopSurplusPrice
它触发后按市价执行,而成本模型里止盈是 maker——那 60% 的出场不吃滑点、按
maker 费率计(LEG_IS_TAKER)。用 preset 会让这部分变成 taker,预算就不成立。
所以止盈单独挂 post_only + reduceOnly 限价单。止损反过来必须市价:stop-limit
在急跌里可能不成交,损失远大于省下的费。
## clientOid 是交易所级幂等,但要小心两个坑
信号键形如 SOL:1787904388411:+1,`:` 和 `+` 未必被接受,带过去直接拒单——而
拒单发生在入场腿上,等于这笔信号静默漏掉。
清洗时不能简单把非字母数字换成下划线:那样 `+1` 和 `-1` 都变成 `_1`,同一根上
的多空信号得到相同 oid,第二笔被当重复拒掉。方向显式编码为 L/S。
用 clientOid 而非只靠本地去重,是因为「已发出但没收到回复」这种情况本地判不了,
重试就会开两次仓。
## 空跑要走完 open_position
第一版在 on_signal 里 `if dry: return`,结果数量取整、价位对齐 tick、请求体
构造全都没被验到。现在空跑走完整条路径,不下真单由 Bitget(dry=True) 负责。
实测两笔:SOL 多头 entry 106.706 / ATR 11bp → 止损 106.471、止盈 107.058 与
107.645;BTC 空头 → 止损在上方 79747.5、止盈在下方。半仓精确一半(SOL 2.3+2.3、
BTC 0.0031+0.0031)。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 16:07:28 +08:00 |
|
 jackyu66gitandCursor
|
bfdb2f2e2a
|
引擎四处「算了没人要的东西」,append_bar 13.9ms → 6.6ms
服务端把增量上线后回传两个热点:add_indicators 为加一根重算全表(占 34%)、
cal_bi_list 整表重扫(51%)。顺着查下来四处都不是算法慢,是算了没人读的结果。
1. cal_trend 挂到 lean 下。它不是笔的依赖(bi.py:221 在它自己的循环里读自身
序列状态),服务端 verify_incr_parity 三币 1800 根已对拍定论。web 走非
lean,klc_trend 图层不受影响。
2. check_fx_pattern 删掉拼完就丢的字符串。它把 klu.to_string() 拼成 p 只为
一行注释掉的 print——2000 根上近 3 万次 f-string 加 6 万次 enum 格式化,
而且在 cal_bi_list 内层。klu.pattern 只被 cal_klu_pattern 自己的双K/三K
判定读,不出模块不进 web,所以整个调用在 lean 下也跳过。
3. ChanBI.add_klc 去二次方。去重原本线性扫 klc_list,且每加一根就把整笔所有
KLU 的 macdhist 重累一遍,往一笔加 k 根是 O(k²)。改成下标集合加
macd_hist/macd_div 惰性求值。这两个值只有背驰判定(bsp.py)读,lean 下
bsp 根本不算。
4. add_indicators 批量挂列。2001 行上 TA 计算合计只有 2.5ms,而 30 多次
df['x']= 要 3.6ms——开销大头是 BlockManager 逐列插入不是计算,改为一次
concat。cal_volume_ratio 里为算一列 rolling 而 copy() 整张 40 列表,一并去掉。
实测(本机,2001 根窗口。服务端基线 21.8ms 是另一台机器,别直接比绝对值):
append_bar 13.9 → 6.6ms
└ rebuild_bi_zs 8.7 → 2.8ms
└ add_indicators 4.4 → 3.5ms
TF_DF lean 49.8 → 32.9ms
TF_DF full 72.7 → 64.9ms
对拍用 git worktree 检出改动前的提交,同一份 BTC 1m 4000 根跑 38 项指纹:
full 模式 19 项全部一致(web 那条路没动);lean 模式差 2 项,正是设计要它差
的 klc.trend 和 klu.pattern,而 lean 下 bi/zs/seg/bsp/dataframe 全部一致——
这就是「这两个字段没人读」的实测证据:打空它们,下游一位不变。
瓶颈已经换位置了。新增 probe_inner.py 拆 inner_ms 分档:本机 TF_DF 两条腿占
70%、build_htf_zones 13%、htf_fx_timeline 6%,而服务端报的是 chan 构建 22ms /
信号链 86ms,机器差解释不了这个四倍差距。曾怀疑是 payload 反序列化,实测
_rebuild 只有 1.0ms,假设不成立。两边跑同一探针对分档表才能定位。
HANDOFF 顺带修掉一处 5.6 重号(增量落地那节改为 5.7,本节挂 5.71)。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 16:01:26 +08:00 |
|
 jackyu66gitandCursor
|
06928d1d5f
|
开仓前那段:量要小、势要有但不能过头,换掉 vr60 那个开关
用户提出看开仓之前的量与趋势方向。这是第三个位置——step50 管信号根、
step52 管持仓中,这里管入场前。step48 采集端补 vpre10/vpre30/mom10/mom60。
先纠正一个错的心智模型(我和用户都以为的):B4/S4 不是回抽后进场。mom10
中位 +3.47 ATR,为负的只占 6%。信号触发时价格在前 10 根里已经顺着你的方向
走了三个多 ATR,2 ATR 止损是架在一段已经走完的行情后面。这也解释了 step50:
信号根是突破根,放量 = 追在最后一棒上。
① 入场前的量单调,越小越好(样本外毛R,Q1→Q4):1.474 / 1.266 / 1.156 /
0.573。控 vr60 后仍成立(低量层 −0.284、高量层 −0.541),与 vr60 相关只有
+0.301,不是同一件事换个说法。
② 入场前的动量是驼峰形,不是单调(mom60 样本外毛R,Q1→Q4):1.252 /
1.473 / 1.141 / 0.603。势要有——完全没动过的 Q1 也不如 Q2;但不能过头——
Q4 在发现期余量只剩 1.44bp,等于不能做。
驼峰形意味着中位数二分法会把它测没:控制表里 mom10 的毛R差是 +0.044,
看着无效,那是二分把 Q1+Q2 和 Q3+Q4 各自平均了。对非单调因子不要用中位数
分层做检验。
③ 砍 mom60≥7 全面优于 §3.39 定的砍 vr60≥4(发现期):
等权 保留 100% 盈亏平衡 13.5bp R夏普 0.325 回撤 16.8 总R 596.6
砍 vr60≥4 保留 69% 盈亏平衡 15.6bp R夏普 0.411 回撤 10.8 总R 514.9
砍 mom60≥7 保留 78% 盈亏平衡 17.5bp R夏普 0.476 回撤 7.7 总R 657.7
每一项都赢,还多留 9 个点的笔数。更要紧的是总R 比不砍还高——被砍掉那 22%
期望为负,砍掉不是花钱买稳健,是纯赚。样本外同向。所以这个开关不需要等
影子测量:它在 0~20bp 每一档都不输等权。
附滑点决策表:5~12bp 区间砍 mom60≥7 通吃,只有 ≥15bp 才该上「三个都砍」,
而那时策略本身已在生死线上。
阈值 7 和 1.5 是贴着 Q4 边界取的整数,不是搜出来的,但也不是完全无关于数据
(看过分位表才取的整),上线前应确认阈值附近没有断崖敏感。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:55:49 +08:00 |
|
 jackyu66gitandCursor
|
431e776905
|
持仓中放量不是出场信号,恰恰是最好那批单子的标记
用户问:既然 step50 证明入场根放量是接盘,那持仓中出现放量根是不是也说明
这一波走完了、该直接平掉?测下来方向是反的,且比入场那条还干净。
规则:持仓期间任一根 vr60 ≥ 阈值就收盘市价平掉(taker)。同根内优先级
止损(盘中)> 目标(盘中)> 放量平仓(收盘)。10 币 3941 笔:
基线(不看量) 毛R 1.068 R夏普 0.627 PF 3.80 余量 18.45bp 均持仓 30.0
vr60≥3 就平 毛R 0.617 R夏普 0.459 PF 2.81 余量 7.81bp 均持仓 11.1
vr60≥5 就平 毛R 0.858 R夏普 0.568 PF 3.37 余量 12.85bp 均持仓 19.8
vr60≥8 就平 毛R 1.009 R夏普 0.617 PF 3.69 余量 16.68bp 均持仓 26.3
阈值越高、触发越少就越接近基线——这条曲线的最优点是「永不触发」,规则纯扣分。
「浮盈才平」的变体把胜率抬到 74.4%(基线 71.7%)而毛R 掉到 0.655,是过早
止盈的教科书特征:胜率上升、期望下降。
根因:vr60≥5 触发的 1769 笔若不平,止盈率 45.7%、止损率 16.6%,而全体基线
是 30.1% / 33.1%。持仓中的放量根标记的是最好的那批单子,平掉每笔让出 +0.484R。
幸存者偏差已控——按基线持仓 ≥K 根分层后 5/5 档同向,放量组止盈率约为无量组
两倍(K=5 时 41.2% vs 19.8%)。
同一个事件入场为负、持仓为正,区别只在站在它的哪一边:入场那根放量你是买方,
持仓中那根是资金来接你的货。用户「有资金的趋势才是好趋势」的直觉成立,
作用点在持仓期而非入场点。
自带逐根模拟器不走 walk_exits,所以先与它对拍基线(毛收益差 <1e-12、出场
原因零分歧),10/10 币通过才往下算。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:55:49 +08:00 |
|
 jackandCursor
|
360e4e1c41
|
自动化实盘执行器:信号总线 + 两个半仓分解 + 四条硬约束
## 架构:影子发信号,实盘执行,两个进程
不让实盘自己算信号。前两个理由是资源与隔离(2 核上再来一份十币计算会把清空
从 247ms 推到 500ms+;实盘崩溃不该影响正在采的数据集),第三个最要紧:
**实盘交易的必须是影子测量的那一个信号**。各算一份会让两边悄悄分叉,之后就
没法把实盘实际成交和影子测的滑点曲线对照——而那个对照是整件事的目的。
总线用 append-only JSONL + fsync:崩溃安全,且「影子在跑、实盘没在跑」会表现
为信号在攒着,而不是静默丢弃。
## 出场结构精确分解成两个半仓
TripleBarrierConfig 只有单级止盈,装不下 3ATR 减半 + 8ATR 目标。但已核实
exit_model.py:151 的 runner_stops 是从**入场价**算的(ret = (entry-low)/a),
且 RUNNER_STOP == SL == 2.0,所以两半共用同一个不动的止损,可精确分解为:
半仓 A 市价入场 · TP 3ATR · SL 2ATR · 48min
半仓 B 市价入场 · TP 8ATR · SL 2ATR · 48min
止损先到则两半都在 -2ATR 出场;3ATR 先到则 A 出场、B 继续且止损仍在 2ATR。
与回测逐情形一致。assert_decomposable() 在启动时挡住 RUNNER_STOP != SL 的
改动,否则实盘会跑另一个收益结构且不报错。
## 硬约束是这个文件的重点
一笔止损只亏约 1 USDT,所以「亏损可控」对单笔成立。但三类故障的代价**不随
仓位缩小**,必须显式封住:失控下单(MAX_OPEN=3 / MAX_DAY=15)、亏损累积
(MAX_DAY_LOSS=20)、裸仓(重启对账)。状态落盘且原子替换——不落盘的话反复
重启就等于反复重置日上限,而失控下单恰好常伴随反复重启。
已验:幂等去重、并发上限、日开仓上限、日亏损上限、跨日归零且保留 done 键、
重启后计数不清零、状态文件损坏时不抛异常。
## 重启对账选择平掉而非接管
崩溃重启后交易所可能还有仓位,而 executor 全没了,那些仓位没有任何止损在盯。
接管需要重建入场价/ATR/剩余半仓状态/已过根数,任一项猜错就让出场结构变成
另一个东西;平掉的代价只是一笔小额亏损,且行为确定。
## 已知风险:止损在机器人侧
Bitget 连接器只支持 LIMIT / LIMIT_MAKER / MARKET,无触发单。
PositionExecutor.control_stop_loss() 是本地盯价、触发时才发市价单,所以进程
一死仓位就是裸的。10x 下强平需逆向 10%(约 100 个 ATR),48 分钟内极不可能,
单次代价仍封在保证金内。下一步用 Bitget 服务端 TP/SL 计划单做兜底。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:52:03 +08:00 |
|
 jackandCursor
|
f716ddd149
|
推送带杠杆与保证金,名义额默认抬到 500
杠杆只影响占用保证金,**不改**名义敞口、手续费、滑点、盈亏绝对值——费与滑点
都按名义额收。所以「用杠杆所以可以很小额」这个方向要说清:杠杆省的是本金
占用,不是成本。
它真正的用处是让「抬名义额」几乎免费,而抬名义额正好压掉步长取整。实测
取整到步长偶数倍后最差币的名义偏差:100U → 6.7%(SOL)、500U → 1.8%、
1000U → 0.6%。所以默认名义改 500、杠杆 10x,每笔占 50 USDT 保证金。
止损在 2 ATR ≈ 0.2%,而 10x 的强平约需逆向 10% = 100 个 ATR,差 50 倍。
这个止损紧到杠杆几乎不引入强平风险,所以这里没有「杠杆换风险」的取舍。
仍建议逐仓,让每笔最大损失被保证金封住。
推送里加上占用保证金与「触止损亏多少 USDT / 占保证金百分之几」,手工执行时
不必自己换算。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:44:39 +08:00 |
|
 jackandCursor
|
c57adc8cb0
|
推送按合约规则取整,减半腿精确一半
100 USDT 的仓位在 Bitget 上不是最小下单量的问题(minTradeUSDT=5、
minTradeNum 极小,10U 都能下),是**步长取整**的问题:
SOL 步长 0.1 币 ≈ 10.7U → 50U 腿只能取 0.4 币 = 42.7U,偏 14.6%
LINK 步长 1 币 ≈ 11.7U → 4 币 = 46.8U,偏 6.4%
BTC 步长 0.0001 ≈ 8.0U → 0.0006 = 47.8U,偏 4.4%
减半腿变成全仓的 43% 而非 50%,剩下 57% 暴露在 8ATR 目标上,而回测的收益
结构假设 50/50。小额下这不影响机制验证,但会让 P&L 读不出回测那个结构。
解法是入场量取到**步长的偶数倍**,这样一半天然落在步长上。实测十个币减半腿
全部精确 50%,名义额落在 93.6~106.7 USDT——小额实盘无所谓。
同时把价位对齐到 tick(priceEndStep × 10^-pricePlace),否则限价单会被拒。
规则拉一次缓存;拉不到就退化为不取整并打日志,不阻断推送。
费率一事已核实无需改动:预算假设的挂牌 taker 0.040% / maker 0.016% 正是
Bitget VIP2 的官方档(返 50% 后 2.0 / 0.8bp)。合约接口返的 6bp/2bp 是 VIP0
基础档,不适用。8bp 门控阈值不变。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:42:17 +08:00 |
|
 jackandCursor
|
97457b0518
|
过滤网信号推 Telegram,供手工小额实盘
自动执行链一行都还没写(下单/持仓状态/跨重启持久化/对账/熔断),而过全部
滤网的信号只有约 5.3 笔/天——低到人手能接。先手工跑一批,就能在写自动化
**之前**拿到真实费率档、真实成交价、真实出场行为,让执行链的每个假设都有
实测对照,而不是写完再发现出场模型不对。
推送内容按手工执行需要给全:参考成交价(回测口径的次根开盘)、按 2/3/8 ATR
换算的绝对价位、下单数量、该币滑点预算,以及一句「偏离超过预算就不值得做」。
剩余半仓止损保持 2ATR 不移成本,这是回测参数,移了就不是同一个收益结构。
时效是这条路最大的风险,所以起点取 kline_ts 而不是信号产生时刻——参考价就是
在 kline_ts 那一刻存在的,从信号时刻起算会漏掉数据延迟加计算那 0.5~1.5s,而
那段不可压缩。超过 TG_STALE_S 直接标记已失效,不让人自己判断:宁可漏做,不
要在偏离预算之外入场。
三条防线:lag 退化时不推(与「停开新仓」同一条规则,不能只在自动化里执行);
按 (币, K线时刻, 方向) 去重,避免补根或池重建重放导致开两次仓;无预算的币
(如 TRX)不推。推送任何失败只打日志,不连坐采集——已验假 token 下降级为
HTTP 401 日志而非抛异常。
凭据走 tg.env(已 gitignore),给了 tg.env.example 说明怎么拿 token 和 chat id。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:35:17 +08:00 |
|
 jackandCursor
|
0745e73b4f
|
判定要知道增量开没开,否则会推荐已经在做的事
上线 9 小时后实测踩到:清空 326ms 触发「币数 > 核数」那一支,于是继续输出
「唯一出路是走增量」——而增量已经生效。同一个分支在增量前后给同一个答案,
等于没有判定。
现在分开:增量未开就指向开增量;已开则指出单币 102ms 里 chan 构建只剩约
22ms,其余是 build_htf_zones / find_fast_bsp3 / attach_htf_context,要继续
压得改这三个或减币。顺带把「宽裕」阈值从 300 提到 400ms——清空 326ms 在
数据到达中位 347~558ms 面前不是瓶颈。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 15:24:31 +08:00 |
|
 jackandCursor
|
545fcc7c77
|
补验多 worker 交错下的一次追加多根
原对拍每根都只追加 1 根,覆盖不到多 worker 交错的实际路径:
ProcessPoolExecutor 不保证同一个币落到同一个 worker,所以每个 worker 隔 nw
根才再见到这个币,一次要补 nw 根。「补 nw 根等价于连续追加 nw 次」是推理,
没实测过。
--interleave N 用 N 份独立缓存轮流接同一个币。BTC/SOL 各 300 根、2 份缓存,
逐字段零分歧,各缓存末窗 2299 根。
顺带记清亲和性的性质:缓存是 worker 进程内的 dict、键含 symbol,不存在
「worker A 的状态被 B 读到」或「拿到别的币的状态」。亲和性影响的是内存
(每个 worker 最终缓存全部币)与补根次数,不影响正确性。实测内存
597→598MiB,代价在噪声里。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 06:24:51 +08:00 |
|
 jackandCursor
|
34a8f37b39
|
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>
|
2026-08-28 06:19:00 +08:00 |
|
 jackandCursor
|
0a0fd2f682
|
影子信号走增量:清空十币 560ms → 247ms
compute() 每根新建 TF_DF 换成按 (symbol, timeframe) 缓存的流式对象。worker
进程被复用,所以缓存跨根存活;2 worker 轮流拿 10 币,每个 worker 最终缓存
全部 20 条流,实测内存开销落在噪声里(597→598MiB)。
## 前提先验,否则整个改动建立在沙子上
init_stream/append_bar **没有 trim**,dataframe 靠 pd.concat 无界增长。所以
增量必然让窗口每根 +1,只能周期性重建拉回,两次重建之间窗口是 [W, W+500]
而非恒定 W。于是必须先证明 compute() 输出对窗口长度不敏感——否则增量等于
静默换掉一批信号,不报错不崩。
verify_window_sens.py:三币 75 个信号窗口,+200/+500/+1000 三档全部逐字段
一致。step39 说的是「命中率在 2000 根饱和」,饱和不等于不变,这是两回事。
## 对拍
verify_incr_parity.py:三币 1,800 根、21 个命中、各跨 1 次重建边界,逐字段
零分歧。不能引用 HANDOFF §5.5——那验的是 bsp_list 那条链的整体哈希,而这里
是 find_fast_bsp3 那条链,且流式对象跨根复用,状态污染只会让信号悄悄换一批。
对拍顺带定论一件读代码定不了的事:cal_bi_list **不依赖** klc.trend。
init_stream/append_bar 从不调 cal_trend(它只在 get_klc_list 里),所以追加
出来的 klc 其 trend 恒为 UNKNOWN,而批量构建的有值;两者结果逐字段相同。
HANDOFF §5.5 那句「bi.py:221 读 klc.trend,笔的计算依赖它」不成立——221 行
在 cal_trend 自己的循环里,读的是它自身的序列状态。
## 重建不走 init_stream
init_stream 是逐行 dataframe.iloc[idx],正是引擎提速刚修掉的反模式:2001 根
要 238.5ms,而批量 lean 只 74.3ms,慢 3.2 倍。第一版用它重建,10 个币启动时
各来一次,清空反而涨到 1686ms。改用 TF_DF(df, lean=True) 重建,append_bar
靠 _ensure_stream_state 就能接上。
## 实测
append_bar 21.8ms vs 批量 lean 重建 77.7ms = 3.56x,与研究侧测的 3.7x 一致。
拆解:add_indicators 全表 7.5ms(34%,为加一根重算 2001 行)+ cal_bi_list
整表重扫 11.1ms(51%)+ concat 1.4ms。这两项都在引擎侧,值得反馈。
十币 / 2 核:清空 560→247ms,排队 92→10ms,纯计算 219→108ms。判定从
「加 worker 无用,唯一出路是增量」变成「宽裕,无需优化」。
注意 inner 108ms 里 chan 构建只占约 22ms,其余是 build_htf_zones /
find_fast_bsp3 / attach_htf_context。**瓶颈已不在 chan 构建**,再压增量收益
有限。
stream_bars 落到 latency CSV:恒等于 2001 说明缺口判定在每根都回退重建、
增量静默失效,这一点从耗时上看不出是哪一环。实测窗口稳定长大。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 06:17:47 +08:00 |
|
jack
|
c8a0062707
|
Merge branch 'chan' of ssh://git.jackyu66.com:2222/jack/chan into chan
|
2026-08-28 05:19:15 +08:00 |
|
 jackandCursor
|
f5f456c523
|
计算判定改看「清空全部币」,并挡掉空窗口
判定原先比逐根的 queue_ms 与 inner_ms,结构上错了两处,十币下直接指反:
判据错。要紧的是一个收盘时刻清空所有币要多久,不是单币的 q 或 i。币同一秒
收盘,币数超 worker 数时后面的币串行等待,这笔代价不出现在任何单根的 q 或 i
里。现在按 kline_ts 聚合取各币最大 compute_ms,落到 clear_hist。
出路错。「排队为主 → 加核」只在还有空闲核时成立。worker 已等于核数时加
worker 不增吞吐,只把等待从 queue 挪到 inner。十币实测正是如此:inner 被
争抢从 144 抬到 192ms 反超 queue 135ms,于是判定落到「量级已低、无需优化」
——而此时最后一个币已在 1376ms。现在币数超核数就直接指向增量路径。
顺带修一个瞬时故障:WS 重连瞬间 feed 的 deque 可能为空,空窗口放行会让
worker 抛「DataFrame for 1m is empty」,白占一个计算槽(币数超核数时会推迟
后面所有币),而报错文本还会让人以为是缺历史数据。加 MIN_BARS 守卫。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 05:19:14 +08:00 |
|
 jackyu66gitandCursor
|
d4fbe9d905
|
量因子该做成开关不是权重;前序因子不该进仓位
把 step49/50 两个分层结论做成仓位因子做组合层面评估,结果与分层表给人的印象
不一致,两个因子的命运相反。
方法上设了三道约束——分层结论转仓位规则最容易在这三处翻车:
1 阈值取整数(vr60 切 1/2/4)、权重取整数比,一个参数都不搜。观测到的四分位
边界在不同时段并不一致(样本外 0.63/1.26/2.28/5.34、发现期 0.62/1.48/
3.11/7.97),用样本分位数等于在同一批数据上既发现又调参
2 权重归一化到均值 1,各方案投出去的平均资金相同,均R 才可比
3 判据是四项一起看:均R / R夏普 / 最大回撤 / 峰值加权并发。只看均值必然误判
全样本 3941 笔,假定滑点 5bp/taker 腿:
盈亏平衡滑点 R夏普 回撤R 峰值并发 总R/峰值并发
等权(现状) 16.7bp 0.420 17.3 7.00 371.4
仅量因子(加权) 18.2bp 0.442 12.7 7.98 367.4
仅前序因子 17.0bp 0.421 19.2 8.46 312.6
硬砍高量档(vr60≥4) 18.6bp 0.496 11.2 6.00 389.3
硬砍 + 前序权重 19.0bp 0.500 11.0 7.19 332.1
① 前序因子不能做仓位。+6bp 余量在 5bp 滑点假设下只值约 0.011R,而这批信号
按定义 100% 发生在别的币已有仓位时——加权就是在敞口最集中的时刻加杠杆。
盈亏平衡只买到 +0.3bp,峰值并发 7.00→8.46、回撤 17.3→19.2,按峰值保证金归一
后是净负的(371→313)。§3.31 里「可用于加仓位权重」那句作废。出路可能是改用
放宽 ATR 门控兑现(多做几笔而非每笔做大),未测。
② 量因子「不做」优于「少做」。硬砍付笔数 −22%、总R −10%,换回撤 −35% 和峰值
并发 7→6。并发这一项单独就值:§3.31 已把峰值敞口列为扩币的前置约束。
③ 优势的形态是削尾不是抬均值。均R 差在各滑点档几乎恒定(0.085→0.082),但
基数在塌,所以相对优势随成本上升放大:15bp 处总R/回撤 2.57→11.86,靠的是回撤
从 150.5 掉到 60.3。这两个因子买的是尾部风险,不是收益。
可操作口径要用发现期:盈亏平衡滑点样本外 18.2bp、发现期只有 13.5bp(硬砍后
15.6bp),差距就是 2026 的 ATR 压缩。13.5 与 shadow_budget 的 15.19bp 同量级,
互为印证。影子测量要对标 13.5 / 15.6,不是 18.6。
开关先不上:只是 live 信号路径加一行,随时能加。等实测滑点出来再定——远低于
13.5bp 则等权就够,贴着 13.5bp 则这 2.1bp 就是生死线。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 05:08:34 +08:00 |
|
 jackyu66gitandCursor
|
ef584b8d49
|
成交量假设方向是反的:高量入场毛R 0.794,低量 1.421
用户假设「有资金的趋势才是好趋势」,预期开仓根成交量越大越好。成交量在信号根
收盘时可知,符合 step48 立的「只用开仓时已知信息」纪律,是合法的可交易切法。
10 币 × 80 万根、实盘口径 3941 笔,结论与假设相反。
按 vr60(当根量 / 前 60 根均量)四分位:
量最低(中位 0.63) 毛R 1.421 余量 27.18bp ← 样本外
量最高(中位 5.34) 毛R 0.794 余量 13.47bp
单调递减,且样本内外、两套量比基准(前 10 根 / 前 60 根)全部同向。稳健性达到
step49 那条的标准:ATR 四分位 4/4 同向、逐时段 7/7 同向,不是 ATR 换脸。
机制在出场结构里,伤害全在止损命中率:
量最低 止盈 33.5% 止损 22.5% 超时 44.0% 赢时均R 1.830 亏时均R −1.098
量最高 止盈 26.1% 止损 45.3% 超时 28.6% 赢时均R 1.651 亏时均R −1.106
亏损幅度四档全是 −1.10(止损就是止损),赢时均R 只降 10%,止损率翻倍是全部
损失来源。这里有个判别点:若只是「2 ATR 止损相对突然放大的波动太窄」的尺度
错配,超时单应按原比例分流进止盈和止损两侧;实际是超时(−15.4pp)和止盈
(−7.4pp)一起流进止损(+22.8pp)。方向本身在变差,不只是止损太窄。
为什么直觉会反:B4/S4 在突破根上进场。大量根意味着这一冲已经由别人的资金
完成,你在它的收盘价接手。「有资金」要能获利必须在资金到达之前进场,不是同时。
与「有前序」是两件独立的事(有前序组 vr10 中位 1.76 vs 无前序 1.46),可叠加:
低量 × 有前序 253 笔,毛R 1.398、余量 31.00bp,是目前见过最宽的执行容忍度。
step48 的采集加 vr10/vr60 两列。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 05:08:03 +08:00 |
|
jack
|
2b9a837a58
|
Merge branch 'chan' of ssh://git.jackyu66.com:2222/jack/chan into chan
|
2026-08-28 04:50:16 +08:00 |
|
 jackandCursor
|
ef2a85dd8c
|
币池可配,实测十币的排队代价;标出漂移的 tick 地板
加 --syms(start.sh 传 SYMS),默认仍是三币。TRX 不进十币池:实盘口径 208 天
只有 5 笔,ATR 门控几乎全刷掉。
十币实测(对比三币):
queue_ms 2 → 169ms(P90 519ms,每刻最大排队中位 533ms)
inner_ms 144 → 196ms(CPU 争抢也拖慢了纯计算)
lag_signal_ms 621 → 958ms;同一收盘时刻最后算完的币中位 1376ms
排队从可忽略变成主项,与「10 币 × 196ms ÷ 2 核 ≈ 640ms 突发」吻合。这也是
之前「加核没用」那个结论唯一会翻转的场景:CPU 占用率只有约 3%,问题纯粹是
所有币同一秒收盘的突发,加核压的是并行度而非单币耗时。
但 800ms 哨兵不受影响——它喂的是 t_data − kline_ts(数据腿),十币下逐币
154~532ms 全在线内。加币不碰那道闸。
另外发现一个会被静默误读的东西:ADA/AVAX/DOGE/LINK/LTC 的漂移中位精确等于
半个 tick 且在四个延迟点上完全相同。那不是漂移,是中价的最小变动量——ADA 半
tick 就有 2.34bp。拿这个数去比预算会误判某币不可做。shadow_report 加了
tick_floor() 标注;方向上安全(真实漂移只会更小,这些是上界)。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:50:09 +08:00 |
|
 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 |
|
jack
|
7c13781f90
|
Merge branch 'chan' of ssh://git.jackyu66.com:2222/jack/chan into chan
|
2026-08-28 04:35:17 +08:00 |
|
 jackandCursor
|
d13a0f85bc
|
固化窗口召回率:2000 根窗口不丢信号(90/90)
全量历史找出的最近 30 笔信号,在 2000 根窗口里逐笔重算,BTC/ETH/SOL 各
30/30 全部复现且过全部滤网。这是窗口左边界效应的一半答案:窗口不丢信号。
另一半没答,且对实盘更危险——窗口会不会多造出全量历史没有的信号(会多开
仓)。那要反向扫描:遍历窗口找命中再回全量核对。lean 之后单窗 130ms,抽样
2 万个窗口约 43 分钟,已经可做,docstring 里记了。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:35:12 +08:00 |
|
 jackyu66gitandCursor
|
550eafdd9d
|
簇内顺序看着是圣杯,43% 的落差里有 34 个点是未来信息
用户提出研究多币同时段开仓的先后顺序。事后按位次切落差很大:簇内第 1 笔
胜率 81.6%、毛R 1.441,第 2 笔 1.085,第 3 笔 0.733,比孤立组 0.832 高 73%。
但「我是首发」的含义是「接下来 5 分钟没有别的币再发」,这是未来信息。首发
赢面大恰恰因为后面真跟出来了别的币、那波行情是真的,而会不会跟出来在下单
那一刻不可知。
换成开仓时真正可知的信息(过去 5 分钟有无别的币先发):
无前序 979 笔 (84%) 毛R 0.938 PF 3.19 余量 14.13bp
有前序 ≥1 个 182 笔 (16%) 毛R 1.021 PF 3.71 余量 21.88bp
43% 的落差塌成 8.8%,方向还反过来。但残留不是零,且滑点余量高 55%
(14.13 → 21.88bp),对 1m 是实打实的——1m 的生死线就在执行成本。
谁在领跑无稳定结构:首发率 BTC 8.6% ~ DOGE 18.4%,158 次首发摊到 10 个币
平均 15.8 次,离散度基本是抽样噪声。
给这个方向定了条纪律:组合空间大而样本只有 158 个簇,每个切法必须能写成
「开仓那一刻已知的信息」。凡用到簇共几个币、我是第几个、簇跨度多长的,
都含未来信息。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:27:43 +08:00 |
|
jack
|
99ae072cc6
|
Merge branch 'chan' of ssh://git.jackyu66.com:2222/jack/chan into chan
|
2026-08-28 04:24:54 +08:00 |
|
 jackandCursor
|
d37bfcb26b
|
心跳的优化建议改看绝对量级
lean + 新引擎后纯计算约 128ms,仍固定提示「需改增量计算」是误导:尾部已由
数据腿主导(lag_data P90 1482ms vs compute P90 237ms),压计算换不到东西。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:24:48 +08:00 |
|
 jackyu66gitandCursor
|
2a59dcb9dc
|
扎堆开仓反而更赚,但好处全在「错开几分钟」那一档,同分钟的最差
承接上一条:既然同时开的必然同向,那关键是这批交易比孤立的好还是坏。
11 币 / 1161 笔 / 实盘口径:
真孤立(±5 分钟内无同伴) 763 笔 胜率 65.5% 毛R 0.832 PF 2.83
错开:5 分钟内但不同分钟 240 笔 胜率 82.1% 毛R 1.443 PF 7.31
同一分钟撞在一起 158 笔 胜率 63.3% 毛R 0.777 PF 2.20
必须把两者分开——结论相反,混在一起会得出错误判断。错开的是全样本最好的
一档,同分钟的反而略差于孤立组。机制上:错开 = 行情从某个币扩散开,后发是
对先发的确认;同分钟 = 全市场同时被一个冲击打中,即追高。
簇级复核(±5 分钟合一簇,排除重复计数):多笔簇簇均毛R 1.180 vs 单笔簇
0.832,簇级 R 夏普 0.848 vs 0.459,结论不是重复计数撑起来的。多笔簇内
全赢 59.5%、全输 10.1%,簇内风险不可分散但偏度有利。
集中度上两类没差别(整簇同向 99.4%),差别纯在收益。所以「限制最多 N 个
并发仓位」把两类一视同仁是错的,它们期望收益差 1.9 倍。
注意:同分钟 vs 错开是看过数据后才划的切法,不是事先定的,208 天 158 个簇
容易切出噪声。当仓位规则用之前必须换一段时间验证。目前只有「扎堆整体更好」
是稳的(簇级也成立)。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:24:31 +08:00 |
|
jack
|
4a4f8727fd
|
Merge branch 'chan' of ssh://git.jackyu66.com:2222/jack/chan into chan
|
2026-08-28 04:24:22 +08:00 |
|
 jackandCursor
|
6c843639d5
|
影子路径开 lean 模式,实测完整链路 1410 → 683ms
拉到新引擎后在服务器侧直接实测,没有沿用 3.4 倍那个换算——那是在旧代码上量的。
先做等价性验证。不能直接引用 step46 的对拍结论:它固化的是 bsp_list 那条链的
哈希,而影子路径走 find_fast_bsp3 + build_htf_zones + htf_fx_timeline +
attach_htf_context,两条链读的东西不一样。所以新建 verify_lean_parity.py 在
这条路径上逐根对拍 compute() 的每个返回字段。
其中一个坑:随机取窗口测不到信号分支。信号密度约 1/2000 根,头 12 个窗口命中
0 个,「一致」只覆盖了早退路径。改成一半窗口对齐到已知信号根,命中率才上来。
最终 180 窗口 / 两模式各 90 命中 / 零分歧。
生产实测(inner_ms,容器内同口径):
compute_ms 646 → 132ms 4.89x
inner_ms 612 → 128ms 4.80x
lag_signal_ms 1410 → 683ms 完整链路,落回 800ms 线内
比 3.4 倍更好,因为是引擎 ~3.5x 叠 lean ~1.35x。
两点判读上的订正:
- lag_data_ms 那 576→490ms 是噪声,不要记在引擎账上。均值 721±36 vs
740±127,重叠;而且引擎本来就影响不到交易所与网络那一段。
- 仍有 44% 的根超 800ms,但尾部现在完全由数据腿主导(lag_data P90 1482ms
vs compute P90 237ms)。计算既不是瓶颈也不是尾部主因了,继续压计算换不到
尾部改善。800ms 那道闸取的是最近 30 根的中位数,683ms 已满足。
start.sh 加 SHADOW_LEAN(默认 1),设 0 可退回 full 复量两模式差异。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:24:08 +08:00 |
|
 jackyu66gitandCursor
|
9f4d7fec73
|
11 币的开仓时刻:不是同时开,但同时开的那批 100% 同向
用户问 11 个币的开仓时间差距。1161 笔 / 208 天 / 实盘口径(深色 ∧ ATR≥8bp):
相邻两笔间隔中位 122 分钟,62.8% 超过 1 小时,每天仅 5.58 笔。
同时持仓数:90.9% 的时间空仓,7.5% 只有 1 仓,≥2 仓合计 1.7%,峰值 8。
所以绝大多数时候不会撞车,但左尾是硬的:7.4% 与前一笔同分钟、20.7% 在
5 分钟内。而同一分钟出现多笔的 72 个时刻里,方向完全一致的占 100%
(§3.31 此前测到的是 92.7%,全样本下更极端)。
这批同时开的仓不是分散,是同一笔押注被拆到几个币上做——名义 3 个仓位,
实质 3 倍单向敞口。由此两条:保证金不是约束(91% 时间空仓,峰值并发只占
0.1% 的时间),真问题是资金闲置;并发上限必须按同向净敞口设,按仓位个数
设等于默许成倍的单向敞口。
另:TRX 在实盘口径下 208 天只有 5 笔,ATR 门控几乎全刷掉,应从币池剔除,
实际可用是 10 个币。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:17:19 +08:00 |
|
 jackyu66gitandCursor
|
d2fcb27d01
|
否掉 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>
|
2026-08-28 04:05:01 +08:00 |
|
 jackyu66gitandCursor
|
0b4d7693b8
|
缠论引擎提速 2.6x,瓶颈是逐行 Series 查找而非指标计算
原以为浪费在 add_indicators 算了太多用不到的指标,实测它只占全量构建的
1.3%——talib 是向量化 C 代码,便宜。真正的两处:
cal_kl_data 占 96%:每根 K 线 df.iloc[i] 新建一个 40 列 Series,再在其上做
几十次逐键查找。改为预取 ndarray 后 2 万根 1946ms → 824ms。
ChanKLC.cal_all_ema_status 占 25%:每次合并 KLU 都立即重算,而它产出的
ema_status / ema52_pos / ema52_status 全仓无任何读取方(含前端)。改为惰性
求值,保留属性形式以防将来有人读。顺带删掉 get_klc_list 里累加一整轮后直接
丢弃的 ema_up_list / ema_down_list。
另加 TF_DF(lean=True):只构建到中枢,跳过线段/走势中枢/MACD 状态机——这些
只服务 bsp_list 与 web 展示,笔和中枢不依赖。研究与实盘走这条快 3.6x。
结果 2 万根 5m:full 1946 → 754ms,lean → 543ms。
step46_engine_parity.py 是配套的安全网,改引擎前先跑一次 --save。它对 KLC
端点与分型、笔起止价与 is_sure、中枢 zg/zd/available_ts/阶梯、信号全部输出列,
以及 26 个被下游消费的 dataframe 列取哈希。本次三处改动逐步验证,另用
git stash 切回改动前代码在 20 万根 × 5 用例上做了跨版本逐位对拍,全部一致;
增量路径与 web API 也各验一遍。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-08-28 04:04:44 +08:00 |
|