agentsclimarketplace

Orderbook sanity

Skill paidaxing1234/latency-hunter-toolkit/skills/orderbook-sanity

5 quant-engineering skills for Claude Code: backtest audit, C++ ▎ low-latency hot-path review, Binance/OKX connector scaffolding, ▎ market-data quality audit & risk-config audit. No alpha, no keys.

Install
npx -y skills add paidaxing1234/latency-hunter-toolkit --skill orderbook-sanity

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

行情数据质量"照妖镜"——用户把订单簿/K线/tick 行情数据或数据采集/解析/落库/读取代码丢过来,逐项审查"会让数据悄悄变脏、进而毒害策略和回测"的工程坑(盘口交叉、深度缺口、checksum 失配、snapshot/增量衔接错误、序列缺口、K线缺失/重复/乱序、未闭合 bar 泄漏、时间戳单位混淆/漂移/时区、未来时间戳、symbol 归一化、幸存者偏差),定位到 文件:行,按严重度(致命/高危/中/低)输出一张"数据体检报告"。 触发词(中):订单簿审查、行情数据质量、数据照妖镜、交叉盘口、深度缺口、checksum 校验、增量衔接、K线缺失、时间戳乱序、重复 bar、未闭合 bar、未来 bar、时间戳单位、时区错误、时钟漂移、symbol 归一化、幸存者偏差。 触发词(英):orderbook sanity、market data quality、crossed book、checksum mismatch、snapshot delta splice、sequence gap、kline gap、duplicate bar、out-of-order timestamps、unit confusion、clock skew、survivorship bias、orderbook-sanity。 不适用:策略 alpha/信号逻辑/调参(那是策略层)、非数据问题的通用代码审查、实盘下单/风控逻辑本身的 bug、要你承诺数据"绝对干净/零脏数据"(工程审查只能降低风险,不能背书数据完美)。

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

21.2 KB, ~7.9k tokens by cl100k_base, as published. Nobody here has run it

orderbook-sanity / 数据照妖镜

核心理念

脏数据是静默杀手。盘口交叉、checksum 失配、K线缺口、时间戳漂移这类问题不会抛异常、不会让程序崩溃——它们只会让你的因子、信号和回测悄悄建在沙子上:回测曲线漂亮得不像话,实盘却怎么也对不上。

最危险的不是"明显坏掉"的数据(那种一眼能看出来),而是数值仍然合法、类型仍然正确、却语义错误的数据:一个落在 1970 年的毫秒时间戳、一根还在形成中的未闭合 bar、一个序列号连续却被错误应用、checksum 已经对不上的本地订单簿。它们能静默通过所有"非空校验",一路污染到 PnL。

本 skill 不写策略、不调 alpha。它只做一件事:像照妖镜一样,把会让数据悄悄变脏的工程坑逐个照出来,定位到 文件:行,告诉你为什么会脏、怎么自测确认、怎么修。

更高一层的铁律:命中可疑模式只是"线索"不是"判决"。 行情里大量"看起来脏"的现象其实是真实市场状态——停牌的真缺口、冷门 symbol 的零量桶、极速行情里一瞬的锁价、跨所聚合时 A 所买价高于 B 所卖价的真实套利。每条陷阱都标注了"合法例外",审查时务必读上下文区分真坑真实行情,否则报告会被假阳性淹没、失去可信度。

何时启用

  • 用户丢来行情数据样本(订单簿快照/增量、K线、逐笔成交)让你看"这数据干不干净"。
  • 用户丢来数据采集/解析/落库/读取代码(WS 订阅、REST 拉取、重采样、入库、DataFrame 加载)让你审质量坑。
  • 用户问:"为什么回测和实盘对不上 / 这数据能信吗 / 帮我查 K 线有没有缺口 / 时间戳是不是错了 / 盘口怎么会交叉 / 本地订单簿对不上交易所"。
  • 在数据进入因子库、回测引擎、实盘信号之前做一道体检。

不适用:求策略 alpha、信号调参、实盘下单/风控逻辑 bug、非数据的通用代码审查、要你保证数据"绝对干净"。

审查协议

  1. 定位数据流。先问清楚/读清楚数据走过的全链路:采集(WS/REST)→ 解析(字段映射/单位换算)→ 落库(去重/排序/主键)→ 读取(reindex/resample/join)。脏数据可能在任一环节注入,但常在解析和落库环节静默成型。
  2. 逐类过三遍。按下面三大类——① 订单簿/盘口、② K线/tick、③ 通用时间戳/对齐——逐条比对代码与数据,挑出命中的陷阱。
  3. 定位到 文件:行。每条发现必须指向具体 path/to/file.py:行号,并贴出触发的代码片段(code smell),不要泛泛说"可能有问题"。找不到证据的项标"未发现/需人工确认",绝不脑补。
  4. 过一遍"合法例外"再定罪。命中可疑模式后,必须回答:这是工程坑,还是真实市场状态(停牌/休市/无量/极速行情/跨所聚合)?判为合法用法的不写进问题清单,或写入"已排除"附注。
  5. 给出实测校验。每条都附可立即运行的自测断言/统计(如 df['open_time'].is_monotonic_increasingdf.duplicated(subset=['symbol','open_time']).sum()),让用户自己在真实数据上确认,而非只听你口述。
  6. 按严重度排序输出。用下面的"数据体检报告"模板,致命在前。

每一类的完整陷阱清单、检测代码与修复方案见 references/orderbook-pitfalls.md,下面只列每类最致命的几条作为审查锚点。

三大类陷阱(审查锚点)

详细的检测代码、code smell、修复方案见 references/orderbook-pitfalls.md,这里只给每类最该先抓的几条。每条格式:陷阱名 — 怎么发现(含合法例外) — 修复方向。

① 订单簿 / 盘口

  • checksum / CRC32 失配 (checksum mismatch):致命。OKX、Kraken、Bitstamp、Coinbase 等会对 top-N 档位下发 CRC32/checksum,这是交易所给你的、最强的本地簿一致性原语——专门用来抓"序列号连续、却被错误应用/丢档/精度截断"这类纯靠 sequence 检测发现不了的失同步。代码里订阅了带 checksum 的频道却不校验,或校验算法(拼接顺序、价格/数量格式化、参与档数)与交易所文档不一致 → 本地簿已脏却毫不知情。合法例外:Binance 现货增量本身不下发 checksum,此时靠 sequence(U/u/pu)衔接即可,不算漏校验——只对确实下发 checksum 的交易所判该坑。修:按交易所文档逐字复现 checksum(档数、价×量拼接顺序、定点格式化),每次应用增量后比对,失配即丢弃本地簿重拉 snapshot;价格用定点整数当 key 避免浮点拼接误差。
  • snapshot ↔ 增量衔接错误 (snapshot/delta splice):致命。盘口最常见的"出生即脏"——snapshot 与增量的拼接没按交易所铁律来。Binance:先订增量入 buffer → 再拉 REST snapshot → 丢弃 u <= lastUpdateId 的增量 → 首条应用的增量必须满足 U <= lastUpdateId+1 <= u,否则中间漏/重一段,本地簿从第一根就偏。合法例外:不同交易所衔接规则不同(OKX/Bybit 的 seq 字段语义、首帧是否含 snapshot 都不一样),按该所文档核对,别用 Binance 规则硬套别家。修:严格按交易所衔接规则,首条增量做 U/u/lastUpdateId 区间断言,断言失败即重拉。
  • 盘口交叉 (crossed book):best_bid >= best_ask。增量更新丢包/乱序后本地簿失同步的典型症状,任何基于盘口的报价、midprice、价差信号全错。合法例外:① snapshot 拼接窗口内、极速行情一瞬的锁价(locked, bid==ask) 在个别撮合/聚合口径下可短暂出现,需看是否瞬时自愈;② 跨交易所聚合簿里 A 所 best_bid > B 所 best_ask 是真实跨所套利机会,不是脏数据——只对单一交易所同一本地簿判交叉为坑。修:每次应用 update 后断言 best_bid < best_ask;单簿持续交叉即丢弃本地簿重拉 snapshot。
  • qty==0 删档语义错误 (zero-qty delete):增量里 qty==0 / size==0 / 空数组表示删除该价格档,不是"把价格置 0"、也不是"保留一个零数量档"。处理错会在簿里留下幽灵档 / 深度缺口,midprice、深度加权价全错。修:qty==0 一律 del book[price](档不存在则忽略),绝不写入零档。
  • 深度缺口 / 档位错乱 (depth gap):价格档位不连续、买卖档跳变。本地订单簿与交易所失同步的表征。合法例外:稀薄市场本就档位稀疏、价格档之间天然有"空隙",这是真实流动性形态不是缺口——别把"档少"当"档丢"。修:校验是增量应用错误(配合 checksum/seq)还是真实稀薄;前者重拉 snapshot,后者保留。
  • 序列缺口 (sequence gap):增量推送的 U/u/pu 序列号跳号,意味着漏掉了 update,本地簿必然偏离真实状态。修:逐条断言 next == prev+1(或该所衔接规则),缺口即丢弃本地态 + 重拉 snapshot;重快照本身也要退避+限频防死循环。

盘口类陷阱以本地簿失同步为核心,检测优先级:checksum 失配 > 衔接错误 > seq 缺口 > 交叉 > 深度缺口。有 checksum 的交易所务必优先校 checksum——它能抓到前几项都漏掉的"静默脏簿"。详见 references。

② K线 / tick

  • 使用未闭合 bar (unclosed/forming bar leakage):致命。把仍在形成中的 bar(is_closed=false / Binance WS 的 k.x=false)当终值用——回测里是典型未来函数,实盘会用一个"close 还会变"的 bar 触发交易,回测虚高、实盘对不上。合法例外:做实时盘中展示/监控(画当前正在走的那根)时用 forming bar 合法——只对"forming bar 的值进入信号/落库为终值/喂回测"判致命。修:仅 k.x==true 才采纳为终值;forming bar 标 provisional,永不入信号、永不当终值落库。
  • K线缺口 / 缺失 bar (kline gap):连续周期里某些时间桶没有 bar。下游 MA/ATR/动量会把缺口两端当相邻 bar,信号错位。合法例外(重点):停牌、交易所维护、休市(股票隔夜/周末/节假日)、冷门 symbol 在该桶内真没成交——这些是数据真实地不存在,不是采集丢数据,处理方式与"采集丢包"完全相反。绝不能盲目 ffill/回补把真空洞填成假数据。修:用期望时间网格 reindex 找缺口,先分类:真缺口(交易所有数据但你没采到)走 REST 回补;停牌/休市/无量(交易所也没有)标 halted/NaN 并在下游显式跳过,不参与 rolling 相邻关系。
  • 重复 bar / 重复成交 (duplicate kline / trade):同 open_time 多条、同 tradeId 多次。成交量被重复累加,VWAP 虚高。合法例外:REST 翻页边界重叠、WS 重连后重推本就是预期行为,正确姿势是幂等去重而非报警——别把"收到重复帧"本身当 bug,只对"重复数据被累加/重复计量"判坑。修:以 (symbol,interval,open_time) / tradeId 做幂等去重 + DB 唯一约束,入库 upsert 而非 append。
  • 时间戳乱序 / tradeId 缺口 (out-of-order / sequence gap):bar 或逐笔未按时间单调到达、tradeId 跳号。所有 rolling/shift/diff 假设有序,乱序则相邻关系全错;tradeId 缺口意味着成交永久丢失。合法例外:同一毫秒内多笔成交,transact_time 相等但 tradeId 递增属正常,需用 (transact_time, tradeId) 复合键判序而非单看时间戳。修:入库前强制按复合键排序,tradeId 缺口走 REST 回补。
  • OHLC 不变式破坏 (OHLC invariant violation):low <= min(open,close)high >= max(open,close) 被破坏,通常是字段映射 o/h/l/c 错位或聚合 bug。下游突破/ATR/止损全错。修:向量化断言硬性 reject 并定位映射代码。
  • 价格离群尖刺 (outlier spike / bad print):乌龙指、坏报价、小数点错位。合法例外:真实涨跌停、闪崩闪涨、巨型市价单 print、开盘跳空在纯阈值下与坏报价长得一模一样——别误删真实极端行情。修:用 MAD/Hampel 等稳健统计而非绝对阈值检测,命中只标记隔离待人工核查,绝不直接删。

tick 级额外关注:成交乱序需用 (transact_time, tradeId) 复合键;重复成交按 tradeId 幂等;活跃 symbol 的零量 bar 多为合成占位 bar(可疑),但冷门 symbol 的零量桶是真实无成交(合法)——按流动性区分,别一刀切。详见 references。

③ 通用时间戳 / 对齐

  • 时间戳单位混淆 (ms/s/ns/us unit confusion):致命。秒/毫秒/微秒/纳秒混用,时间被放大或缩小 10³~10⁹ 倍,bar 落到 1970 或遥远未来,所有对齐/排序/窗口彻底错乱——且因数值仍是合法整数而静默通过。入口统一归一为单一内部单位(建议 epoch ms),pd.to_datetime 永远带 unit,转换后跑年份范围 sanity check(2020s 秒级约 1.7e9、毫秒约 1.7e12、微秒约 1.7e15)。
  • 幸存者偏差 (survivorship bias in universe):致命。回测 universe 只用"当前还在交易"的 symbol,剔除了已退市/爆雷的合约,系统性高估收益。必须用 point-in-time universe——每个历史时点的成分由当时实际可交易标的决定,含后来退市的(crypto 含已下架币并记最后成交价)。
  • 未来时间戳 / 停盘 vs 真缺口混淆 (future ts / halt vs real gap):未来 bar——ts > now 的记录(本地写错单位、时钟漂移、交易所事件时间与接收时间混用都会造成)必须隔离待查,绝不能进训练/回测(等于看到未来)。数据为空时区分两种相反情形:交易所维护/停牌/休市(标 halted,不交易、不回补)vs 采集丢数据(真缺口,需回补)——两者处理完全相反,认错方向要么填进假数据、要么丢掉真信号。修:入口加 ts <= now()+容差 断言;空数据分类前不做任何 ffill/回补。
  • 时区错误 (timezone / naive-aware mismatch):把交易所 UTC 当本地、naive 与 aware 混用、按本地时区切日界。bar 整体偏移数小时、日线日界错位、DST 处出现重复/缺失小时。修:全链路内部统一 UTC tz-aware,只在展示层转本地。
  • 时钟漂移 (clock skew):本地与交易所时钟偏差。签名请求因 timestamp 超 recvWindow 被拒(Binance -1021)、延迟测量失真。修:周期请求交易所 /timeoffset = serverTime - localTime,签名补偿,本机 NTP 校时。
  • 时间戳漂移 / 非单调 (drift / non-monotonic event time):混用本地接收时间与交易所事件时间。修:分别存 event_timerecv_time,聚合/对齐用 event,延迟监控用差值。
  • 跨源对齐 / symbol 归一化 (cross-exchange alignment / symbol normalization):不同交易所日界、bar 对齐基准、符号(BTCUSDT vs BTC-USDT vs XBTUSD,spot vs perp)不同。合法例外:跨所聚合时盘口"交叉"是真实套利(见 ①),按 UTC 时间戳 join 时不同所同一时刻数据本就有差异,别把真实价差当对齐错误。修:按 UTC 时间戳 join 而非行号 zip,建符号映射表区分市场类型(spot/perp/季度),映射缺失 fail-loud 而非静默归并。

数据体检报告输出模板

审查结论按下面格式输出,可直接截图。严重度用 emoji + 中文档级(与本工具集 commands/orderbook-sanity.md 一致),每条带 文件:行 和实测校验,致命在前。命中可疑模式但读上下文后判为真实行情/合法用法的,写入"已排除"小节而非问题清单。

══════════════════════════════════════════
   数据体检报告 · orderbook-sanity
══════════════════════════════════════════
数据流: 采集(__) → 解析(__) → 落库(__) → 读取(__)
审查范围: <文件/数据样本清单>     扫描文件: N 个

总评: 🔴 致命 a 项 · 🟠 高危 b 项 · 🟡 中 c 项 · 🔵 低 d 项
判语: 「<这是干净行情,还是建在沙子上的脏数据?>」
      —— 一句不留情面但克制的整体结论;不背书"绝对干净"

────────────── 问题清单(按严重度) ──────────────

[🔴 致命] checksum 未校验(本地簿可能已静默失同步)
  位置: src/feed/orderbook_okx.py:––(订阅 books 频道但全文件无 crc32 比对)
  现象: OKX books 频道每帧带 checksum,代码只按 seq 衔接、从不比对 checksum
  毒害: seq 连续但档位被错误应用/精度截断时无法察觉 → 本地簿静默偏离
  实测: 复现 OKX 文档的 CRC32(top-25 档、bid/ask 价×量拼接)与帧内 checksum 比对;
        持续失配率 > 0 即本地簿有脏
  修复: 逐字复现 checksum,失配即丢弃本地簿重拉 snapshot;价格用定点整数当 key

[🔴 致命] 使用未闭合 bar 泄漏
  位置: src/feed/kline_ws.py:88
  现象: k.x 字段未判断,forming bar 的 close 直接入信号
  毒害: 回测未来函数 → 实盘对不上回测
  实测: last_bar.close_time > now() 即被使用了未闭合 bar
  修复: 仅 k.x==true 才采纳为终值;forming bar 标 provisional 永不入信号

[🔴 致命] 时间戳单位混淆
  位置: src/parse/ts.py:23
  现象: pd.to_datetime(ts) 未带 unit,秒级时间戳被当纳秒,bar 落到 1970
  实测: df['open_time'].dt.year.between(2017,2030).all() 为 False 即中招
  修复: 入口统一 epoch ms,to_datetime 永远带 unit,转换后跑年份 sanity check

[🟠 高危] snapshot/增量衔接未做区间断言 ...
[🟠 高危] K线缺口未分类(停牌真缺口 vs 采集丢包混处理) ...
[🟡 中]   活跃 symbol 零量占位 bar ...
[🔵 低]   缺缺口率/失配率监控埋点 ...

────────────── 已排除(命中但判为真实行情/合法用法) ──────────────
- 跨所聚合簿 A.bid > B.ask: 真实套利价差,非单簿交叉(aggregate.py:54)
- BTCUSDT 周末日线缺口: 该所 7×24 无此问题 / 或确认为休市非丢数据
- REST 翻页边界重复 bar: 已 upsert 幂等去重,非计量重复

────────────── 实测建议(请在真实数据上跑) ──────────────
说明: 以上是"代码里会让数据变脏的结构性坑 + 样本可静态看出的异常",
不等于全量数据扫描。命中是否成立、多严重,以你在真实数据上的实测数字为准。
建议断言: checksum 失配率、best_bid<best_ask 违例数、open_time 单调性与重复数、
          年份范围 sanity、ts<=now 违例数、缺口分类后真缺口/停牌占比。

优先处置: 先堵致命(checksum/未闭合 bar/单位混淆/衔接错误)→ 再修缺口分类与去重 → 最后补监控埋点。
══════════════════════════════════════════

报告原则:每条必带 位置;找不到证据的项标"未发现/需人工确认",不硬凑;命中可疑模式但读上下文后判为真实行情/合法用法的,写进"已排除"而非问题清单;判语克制、不羞辱、不夸张;绝不承诺"修完就绝对干净"——结论以实测数字为准。

严重度定义

严重度含义处置
🔴 致命静默注入未来函数或让数据语义彻底错乱,直接导致回测虚高/实盘对不上(未闭合 bar、单位混淆、幸存者偏差、checksum 失配、snapshot/增量衔接错误、未来 bar)必须修,修前别信任何基于该数据的回测结论
🟠 高危数据会偏离真实状态,污染因子/信号但不一定全错(序列/深度缺口、重复/乱序、盘口交叉、qty==0 删档错误、OHLC 破坏、时区错误);:纯 K 线缺口须先做"停牌真缺口 vs 采集丢包"分类——分类前不直接定高危,误把真实休市当丢数据回补本身就是新的脏数据源应尽快修,修前对受影响区间的结论打折
🟡 边缘场景或可恢复的质量问题(活跃 symbol 零量占位 bar、时钟漂移测量、离群尖刺隔离)建议修,至少加监控指标
🔵 健壮性 / 可观测性欠缺(缺数据质量埋点、缺缺口率/checksum 失配率统计)可选,有余力再补

判定基准:"这个值在该时点真能算出来吗?这根盘口/这桶 bar 是本地簿真实状态,还是失同步/采集错误的产物?这个时间戳单位/时区对吗?" ——同时反问"它会不会其实是真实市场状态(停牌/无量/极速/跨所)?" 两问交叉后再定罪。

重要说明

  • 这是工程审查,不是数据质检报告。本 skill 照的是代码里会让数据变脏的结构性坑数据样本里能静态看出的异常,它不能不会替你跑全量数据扫描后背书"你的数据绝对干净"。
  • 必须配合实测校验。每条发现都给了可运行的断言/统计,请在你的真实数据上跑一遍确认——审查能告诉你"这里有坑、这样去验",但最终是否命中、命中多严重,要靠你在真实数据上的实测数字说话。
  • 真实行情 ≠ 脏数据。停牌的真缺口、冷门 symbol 的零量桶、极速行情里一瞬的锁价、跨所聚合的真实价差,都是真实市场状态,不能当坑误删/误填。每条陷阱的"合法例外"就是为防这种误伤——审查时务必区分。
  • 不承诺数据完美。脏数据来源太多(交易所推送本身的 bug、网络重排、补数交叠、时钟问题),工程审查只能系统性降低风险、把已知坑堵上,无法保证零脏数据。任何"修完就绝对干净"的话术都不要信。
  • 不碰策略层。为什么这个信号不赚钱、参数怎么调、alpha 在哪——不在本 skill 范围。本 skill 只保证喂给策略的数据本身不是脏的(已知坑层面),且这种"保证"也只是"未发现本清单覆盖的坑",不是"绝对干净"的背书。

What ships with it: 1 file

44.2 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 326,970. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.