Commit Graph
10 Commits
Author SHA1 Message Date
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
jackandCursor 3b14bba247 离线验证信号时刻流动性不更差,免掉攒 30 笔信号的 17 天等待
三币过完三滤网只有 1.72 笔/天,攒 30 笔要 17 天。但滑点本来每根都在记,信号
时刻的测量只多回答一个问题:信号那一刻的流动性是否比普通根差。这个问题可以
用 210 天历史离线回答。

关键是必须做匹配对照。信号按 ATR ≥ 8bp 门控,信号根天然比平均根波动大,直接
和全体根比一定会「发现」一个我们自己施加的差异。所以对照组按「同时段 × 同
ATR 十分位」抽取,并排除距信号 48 根内的根(持仓期不独立)。自检 ATR 比值
0.976~1.004,匹配成立。

结果三币一致,方向与担心的相反:信号根成交额是对照的 2.1~2.6 倍、Amihud 非
流动性只有 0.47~0.60 倍、Roll 有效价差三个币都不显著。信号跟在突破后面,
突破自带成交量。所以全体根测出的冲击与价差偏保守而非偏乐观。

唯一真实差异是根内波幅宽 25~28%,但那是波动而非流动性,对应漂移而非冲击,
且可直接当缩放系数:1 秒延迟点漂移上调后仍只占预算 1.4%/3.0%/4.5%。

判读按流动性与波动分两组。初版把 range_bp 当成流动性红旗,会得出「信号时刻
更差、必须等样本」的相反结论——它是波动度量,且 ATR 已匹配。
检验用置换而非 t:成交额跨几个数量级,右尾太重。scipy 未安装,也不宜在采集
运行中动环境,所以用 numpy 自己实现。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 03:52:23 +08:00
jackandCursor 75fbf4167b 修掉 gzip 追加会毁掉整个文件的数据丢失,并分开买卖两侧的成交分布曲线
两件事,都是「静默出错」那一类。

一、BookLog/TapeLog 追加到同一个 .gz,进程被 SIGKILL 时当前成员停在 deflate
块中间,下一轮追加的新成员接在垃圾字节之后。顺序解压在损坏点抛 invalid
block type,该点之后全部读不出来——包括后续每轮写进去的。而读侧的异常处理
把这个当成「正常的尾部截断」静默跳过,于是只读出 21 行还不报错。
原 docstring 里写的「只丢最后一个缓冲块,不会毁掉整个文件」是错的,已证伪。

写侧改成每轮运行一个文件;读侧按 gzip 成员边界扫描、坏成员单独跳过并出声
报告,同时把同前缀的多轮文件一并读入。旧损坏文件因此多恢复出 31/21 条
(tape)与 132/95 条(books)。

二、tape_shape 只统计主动买、只自区间顶部累积,这条曲线只适用于多头止盈。
exit_fill 两侧共用它,等于把空头的可成交量按多头分布高估。实测二者不对称:
主动买在顶部 20% 内已占 40%,主动卖在底部 20% 内只有 18%。分成 SHAPE_F 与
SHAPE_F_SHORT,avail_at 按方向查各自曲线。

两条曲线只有 45 根成交流样本,所以补了 --sensitivity:把空头可成交量砍一半,
10 万仓位下 BTC/ETH 预算完全不动、SOL 动 0.07bp。结论不依赖这 45 根样本。
顺带撤掉 step43 docstring 里已作废的「成交率 30%/16%/1.5%」。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 03:23:07 +08:00
jackandCursor 54792fe015 把 compute_ms 拆成排队与纯计算,据此否掉换机器这个方向
compute_ms 一直是「提交进程池到拿到结果」的墙钟时间,排队和纯计算混在一个
数里,所以「加核有没有用」只能靠猜——这也是原先打算在 AWS 开第二台比 CPU
的依据。

worker 内部自己计时,连同父进程传入的提交时刻一起回传,拆出 queue_ms 与
inner_ms。实测中位 3ms / 695ms:2 个 worker 跑 3 个币并不排队,因为三个币的
收盘消息错峰到达。瓶颈全在单线程,加核压不到。

顺带把 README 里的内存数据从臆测的 1.5GB 改成实测 410MiB,并注明跨站点比
CPU 收益有限。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 03:02:06 +08:00
jackandCursor 95f2b614a2 延迟瓶颈实测为本机 CPU 而非机房位置,跨站对比主指标改为 compute_ms
用户指出本机选新加坡是因为 Bitget 机房在新加坡。查证下来 ws.bitget.com 解析
到的是 CloudFront(dxotqhr62n6z4.cloudfront.net),落在新加坡 AS16509
(Amazon),即连的是 AWS 的 CDN 边缘而非 Bitget 自有机房。

腾讯云 ap-singapore(AS132203)到该边缘实测:ICMP 往返 2.1ms、TCP 握手
3.3ms、TLS 完成 9.0ms、首字节 87.8ms。首字节减 TLS 那约 79ms 是 CloudFront
回源开销,与我们的位置无关。

延迟构成(33 根样本):数据到达中位 506ms、信号计算中位 646ms、合计 1315ms。
随机房位置变化的只有那 2ms 往返,占总延迟 0.15%。而 646ms 的信号计算是每根
在 2000 根 1m 加 800 根 5m 上重建缠论结构,本机 2 核、2 个计算进程,三币同时
收盘时第三个还要排队——这才是有改善空间的一项。

因此:
- 新增 deploy/netprobe.sh,把网络那一段单独量出来并入运行元数据。用到达
  延迟去比两个机房等于用公斤秤称克,必须把可变的那段拿出来单独看。
- compare_sites.py 主指标改为 compute_ms,lag_data_ms 降为自检项(两站应当
  接近;若差很多,先怀疑时钟而非网络)。元数据表加 nproc/cpu_model/往返。
- README 改写:第二台机器该测 CPU 规格而非地理位置,WORKERS 按核数减一给,
  币数多于 worker 数时排队时间直接计入 compute_ms。

另修正站点标签:本机是腾讯云而非 Hetzner,sg-hetzner → sg-tencent,标错的
33 行数据已清掉重采。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 02:51:51 +08:00
jackandCursor 1661bbbac9 gitignore: 运行元数据属采集产物,不入库
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 02:40:57 +08:00
jackandCursor 631d97e493 加跨地部署脚本与站点对比,数据全表加 site 列
目的是在第二台机器(AWS)上跑一套完全相同的采集,看不同地理位置的数据差异。
滑点里最大的一项是延迟漂移,而延迟含网络传输,所以机房选址是可优化参数。

数据侧两处必需改动:

- 全部输出加 site 列(三张 CSV 加 gzip 里的盘口与成交流)。没有这一列,两台
  机器的数据合起来就分不清来源。为免四处 writerow 漏加一处产生静默空值,
  改在 _SiteWriter 里统一注入。
- start.sh 在时钟未同步或偏移超 10ms 时**拒绝启动**。所有延迟数字都是
  「本地时钟 − 交易所 K 线收盘」,时钟偏 50ms 就全部同向偏 50ms,且不报错,
  只会让跨地对比得出一个干净且完全错误的结论。

deploy/ 下四个文件:setup.sh(docker + chrony + 拉镜像)、start.sh(校验时钟、
写运行元数据、起容器)、status.sh(健康速查)、README。运行元数据记 git commit、
镜像摘要、时钟偏移——两地数据对不上时,这三项任一不同都足以解释差异。

compare_sites.py 做配对对比:只取各站都有的 K 线(不取交集可能在比不同时段,
而延迟对市场活跃度敏感),并报配对差的符号占比而非两个中位数相减。已用注入
120ms 的合成数据验证能精确还原。另有一条自检:同一固定延迟点上两站漂移应当
相同——漂移是市场性质,若也差很多则先查时钟与时段对齐。

status.sh 里按列名取字段下标而非写死数字:加 site 列时字段整体右移过一次,
写死 $8 会静默变成读 lag_signal_ms 而非 lag_data_ms。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 02:39:47 +08:00
jackandCursor 01c4a4ab4d 主口径仓位定为 10 万 USDT,并量出限价单前方的排队量
用户 2026-08-28 确认资金规模不会更大,故仓位档改为 25k/50k/100k/200k
(上下留档是为了读出局部斜率,单点看不出再大一倍会怎样)。该规模下两条
约束都不绑定:冲击占预算 0.1~11.1%,成交量效应使预算降幅不足 1%。

新增 queue_ahead:排队是唯一还没建模的成本项,exit_fill 假定我们能吃到该
价位的全部对手方成交量。10 万仓位相对最优档为 BTC 0.2 倍、ETH 0.7 倍、
SOL 69.7 倍。SOL 畸高是 tick 更细所致(同样的量摊到约 10 倍价位上),
对它应看 5bp 档(0.17 倍),但仍是三币中排队压力最大者。

同时在 shadow_depth 模块头标注:composite_fill 只算首次触及那一根的可成交
量,系统性偏悲观,不作为成交率结论——真实成交率见 lib/exit_fill.py。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 02:39:47 +08:00
jackandCursor 28075173af 出场模型改为按成交量结算止盈限价单,并出预算对仓位规模的曲线
exit_model.walk_exits 给止盈记的毛收益是 target*a/entry,即假定限价单全额
成交在目标价。新增 lib/exit_fill.py:两张挂单常驻(半仓 3ATR、半仓 8ATR),
每根按该根在限价之上的可成交量逐步吃进,未成交部分继续持有,止损触发时
市价平掉剩余。可成交量 = 形状函数 f(k) × 该根主动买成交额,f 由影子成交流
实测(近似线性,即区间内均匀分布,故结论对形状假设不敏感)。

结果:预算对仓位规模远比预期稳健。到 100 万名义额,BTC 10.97→10.69、
ETH 15.34→15.20、SOL 17.21→15.83bp。原因是挂单常驻多根而非只在首次触及
那一根成交,且价格决定性穿过限价时整根成交量都可用。

首版实现有个静默 bug 值得记:avail_above 里有个 `hi <= 0` 的守卫,而空头
用「价格取负」处理,负价格空间里 hi 恒为负——所有空头挂单的可成交量一律
判 0,空头全被拖到 48 根超时收盘。下跌段里那比 3ATR 目标赚得多,于是预算
反而偏高 0.76bp,表现为「一个看似合理的模型差异」。已改为显式方向参数,
并加 assert_converges:仓位趋近 0 时必须逐笔收敛到 walk_exits,不符即抛错。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 02:39:47 +08:00
jackandCursor 181bca303f 影子测量改用框架吃单原语,并补齐容量与 maker 成交率两项测算
吃单查询换成 Hummingbot 的 OrderBook.get_vwap_for_volume:手写的 walk_book
返回的是按计价币吃单的加权均价,但框架的 get_price_for_quote_volume 返回
边际价、get_vwap_for_volume 收基础币量,两者语义不同。改为按基础币下单
(真实委托与 PositionExecutor.amount 均是基础币计价),深度不足由
query_volume/result_volume 判定,框架此时返回 nan 而非一个看似正常的
部分成交均价。

落盘完整盘口(双边 50 档)。此前只记三个固定名义额的成交价,这批数据的
寿命就等于那几个档位的寿命;存完整深度后任意资金量级的冲击都能离线重算。
仓位档同时从 1k/5k/20k 提到十万量级,此前低估真实仓位约两个数量级。

订阅成交流,按根按价位聚合。买卖分开存——多头在目标位挂卖出靠主动买盘
成交,混在一起会把成交率高估约一倍。BTC 每根总成交额中位与 210 天历史
的 volume×close 差 0.3%,可确认采集完整。

新增两项测算:
- 冲击不是绑定约束。32 万仓位单边冲击 0.19~2.39bp,对 8.58~20.64bp 的
  预算只占 1.6~14.2%,冲击反推的资金上限 100~500 万。
- maker 成交率才是。止盈位被首次触及时,限价在该根价格区间中的位置
  中位 k=0.28(63.9 万次触及,三币一致);合并每根成交额后,32 万仓位
  的全额成交率仅 30.1%/15.6%/1.5%。要 80% 全额成交,仓位须 ≤ 4.7 万
  /1.4 万/0.26 万——比冲击反推的上限低 40~370 倍。

回测把这些止盈按「全额成交在目标价」计,故预算所依据的收益流本身需重估。

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