mcpField
O
odb-microstructure-forensics

odb-microstructure-forensics

github.com/terrylica数据与数据库158 次安装今天更新
代码仓库

关于 odb-microstructure-forensics

用于从 ClickHouse 结果追踪到 Parquet 原始成交数据,调查 Open Deviation Bar 异常的取证工作流。帮助数据和交易分析人员区分算法缺陷与市场微观结构现象。

主要功能

  1. 01三层逐步追查柱线至成交数据
  2. 02检测阈值超限和零持续时间柱线
  3. 03分析时间戳突发和订单流
  4. 04分类市场现象与数据根因

适用场景

  1. 01调查异常高大或过短的 ODB 柱线
  2. 02判断阈值超限是否由数据特性导致
  3. 03从成交记录追查疑似数据缺口

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/terrylica/cc-skills --skill odb-microstructure-forensics

安装后在 Claude Code 中输入/odb-microstructure-forensics确认已加载。

附带文件references/clickhouse-schema.mdreferences/evolution-log.md

详细介绍

ODB 微观结构取证

通过从 ClickHouse 缓存追溯到原始 Parquet 成交数据,系统地调查 Open Deviation Bar 异常。区分算法正确性问题与市场微观结构现象(强平级联、订单簿扫单、撮合引擎批处理效应)。

自我演进的技能:此技能会在使用过程中不断改进。如果指令有误、参数发生漂移,或需要变通方案,请立即修复此文件,不要拖延。仅针对真实且可复现的问题进行更新。

适用场景

  • ODB 柱在相同阈值下,视觉上比相邻柱更大(更高或更宽)
  • 柱的持续时间为零或接近零,但价格范围极大
  • abs_dev_dbps 超过阈值(例如,100 dbps 的柱达到 22 dbps)
  • 单个时间戳出现微型柱集群
  • 判断异常是数据错误还是市场微观结构现象
  • 调查 Flowsurface 图表 UI 标记的特定时间窗口

数据源

来源位置架构访问方式
ClickHouse 缓存 上的 opendeviationbar_cache.open_deviation_bars76 列,参见架构参考ssh <gpu-host> 'curl -s http://localhost:8123/ -d "..."'
Parquet 成交缓存 上的 /home/<user>/.cache/opendeviationbar/ticks/{SYMBOL}/{YYYY-MM-DD}.parquetagg_trade_id, price, quantity, first_trade_id, last_trade_id, timestamp, is_buyer_maker使用 Polars 执行 ssh <gpu-host> 'cd /home/<user> && uv run --python 3.14 python3 -c "..."'

访问方式:始终通过 SSH 直接查询 。SSH 隧道(localhost:18123)仅供 Flowsurface 应用运行时使用,取证查询应直接访问。

调查方法

调查分为 3 层逐步深入:ClickHouse 概览 → 逐柱异常检测 → Parquet 成交级根因分析。

第 1 层:ClickHouse 柱概览

查询可疑时间窗口内的柱。检查结果集中的异常信号。

-- Adjust symbol, threshold, and time window to match the investigation
SELECT
    toDateTime64(close_time_us / 1000000, 3) AS close_ts,
    toDateTime64(open_time_us / 1000000, 3) AS open_ts,
    open, high, low, close,
    round((high - low) / open * 10000, 1) AS range_dbps,
    round(abs(close - open) / open * 10000, 1) AS abs_dev_dbps,
    agg_record_count AS n_agg,
    individual_trade_count AS n_trades,
    round(duration_us / 1e6, 1) AS dur_s,
    first_agg_trade_id AS first_id,
    last_agg_trade_id AS last_id,
    is_orphan, is_liquidation_cascade AS is_liq
FROM opendeviationbar_cache.open_deviation_bars
WHERE symbol = '{SYMBOL}'
  AND threshold_decimal_bps = {THRESHOLD}
  AND close_time_us >= toUnixTimestamp('{START_UTC}', 'UTC') * 1000000
  AND close_time_us <= toUnixTimestamp('{END_UTC}', 'UTC') * 1000000
ORDER BY close_time_us
FORMAT PrettyCompact

需要标记的异常信号:

信号列模式含义
超阈值abs_dev_dbps >> threshold / 10单笔成交越过阈值
持续时间为零dur_s = 0整个柱在一个撮合引擎周期内形成
极端范围range_dbps > 2 * threshold / 10价格越过阈值很远
微量成交计数高范围且 n_agg < 10巨大的单笔成交吃掉了订单簿
突发聚集多个柱出现在同一秒流动性扫单被拆分到多个柱中
第 2 层:隔离异常

筛选出异常柱,获取用于深入检查 Parquet 的 agg_trade_id 范围:

-- Bars with threshold overshoot or zero duration
SELECT close_ts, dur_s, open, high, low, close,
    range_dbps, abs_dev_dbps, n_agg,
    first_agg_trade_id, last_agg_trade_id
FROM (... Layer 1 query ...)
WHERE dur_s < 1.0 OR abs_dev_dbps > {THRESHOLD / 10 * 1.5}

记录 first_agg_trade_id 和 last_agg_trade_id 的范围——它们是 Parquet 查找键。

第 3 层:Parquet 成交级根因分析

在 上使用 Polars 分析原始成交。按顺序执行以下 3 项分析:

3a. 时间戳突发检测

按时间戳对交易分组,以查找撮合引擎批次(数百笔交易共享完全相同的微秒时间戳):

import polars as pl

df = pl.read_parquet("/home/<user>/.cache/opendeviationbar/ticks/{SYMBOL}/{DATE}.parquet")

burst = df.filter(
    (pl.col("agg_trade_id") >= {FIRST_ID}) &
    (pl.col("agg_trade_id") <= {LAST_ID})
).sort("agg_trade_id")

# Group by timestamp to find single-cycle batches
ts_groups = burst.group_by("timestamp").agg([
    pl.col("price").min().alias("min_price"),
    pl.col("price").max().alias("max_price"),
    pl.col("quantity").sum().alias("total_qty"),
    pl.len().alias("count"),
]).sort("timestamp")

关键诊断:如果同一时间戳下有数百笔交易,且价格覆盖整个区间,那么这就是撮合引擎批次(单笔大额订单扫过订单簿)。

3b. 订单流分析

判断扫单以买入还是卖出为主:

buys = burst.filter(~pl.col("is_buyer_maker"))   # taker buy
sells = burst.filter(pl.col("is_buyer_maker"))    # taker sell

print(f"Taker buys:  {len(buys)} trades, {buys['quantity'].sum():.4f} BTC")
print(f"Taker sells: {len(sells)} trades, {sells['quantity'].sum():.4f} BTC")

清算级联通常有 95% 以上的交易方向一致(全是吃单卖出或全是吃单买入)。

3c. 价格跳空分析

查找价格大幅跳变的单笔交易——它们是阈值超调的直接原因:

with_gap = burst.sort("agg_trade_id").with_columns([
    (pl.col("price") - pl.col("price").shift(1)).alias("price_diff"),
    (pl.col("timestamp") - pl.col("timestamp").shift(1)).alias("ts_diff_us"),
])

# Trades with gaps exceeding threshold dollar equivalent
threshold_dollars = open_price * threshold_dbps / 10000
big_jumps = with_gap.filter(pl.col("price_diff").abs() > threshold_dollars)

如果单笔交易之间的价格跳空超过阈值,ODB 算法就无法在单个 agg_trade 内拆分——超调不可避免,且符合预期。

根因分类

完成 3 层分析后,对发现的问题进行分类:

分类证据模式处理方式
清算级联95% 以上交易方向一致,50-100+ BTC,同一微秒时间戳,扫过 $200+Oracle 位级精确——无需修复。记录该事件。
订单簿稀薄导致的扫单交易笔数较少,但不同价位之间存在较大的价格跳空Oracle 位级精确——当时订单簿较为稀薄。
孤立 K 线ClickHouse 中 is_orphan = 1已知现象——写入器边界伪影。分析时跳过。
算法错误交易分布正常、没有突发,但 K 线仍然超调在 opendeviationbar 上游提交问题。
数据缺失相邻 K 线之间的 agg_trade_id 不连续Parquet 数据缺失。检查采集流水线。

阈值超调机制

ODB 算法按顺序处理 agg_trades。当第一笔交易相对于 K 线开盘价的偏离超过阈值时,K 线就会收盘。超调机制如下:

  1. K 线以价格 P₀ 开盘,阈值为 T(例如,100 dbps = 0.1%)
  2. 算法扫描交易:P₁、P₂、... Pₙ
  3. 在交易 Pₖ 处:|Pₖ - P₀| / P₀ ≥ T——K 线以 Pₖ 收盘
  4. 如果 Pₖ₋₁ 仍在阈值范围内,而 Pₖ 大幅跳出阈值范围,则超调 = |Pₖ - P₀| / P₀ - T

阈值越低,超调越大,因为:

  • BPR10 阈值 = $70(BTC 价格为 $70k 时)。订单簿出现 $150 的价差 → 超调 2 倍。
  • BPR50 阈值 = $350(BTC 价格为 $70k 时)。同样的 $150 价差 → 仍在阈值范围内。

这是离散交易数据固有的特性——不是错误。

相关技能

技能关联说明
opendeviation-eval-metrics评估 ODB 信号质量(输出指标)。此技能用于调查输入数据质量。
exchange-session-detectorClickHouse 中的交易时段标记。级联事件通常集中在交易时段边界(纽约时段开盘/收盘)附近。

执行后复盘

此技能完成后,在结束前检查:

  1. 查询是否成功? — 如果 ClickHouse 架构发生变化(列重命名、新增列),请更新第 1 层 SQL 模板。
  2. Parquet 架构是否发生变化? — 如果 tick 缓存列发生变化,请更新 Polars 代码片段。
  3. 是否发现了新的根因模式? — 将其连同证据模式和处理措施添加到根因分类表中。
  4. 阈值超调机制的说明是否成立? — 如果发现了新的超调机制,请将其记录下来。

仅在问题真实且可复现时更新,不要基于推测更新。

评论

支持 Markdown