Check data quality with validate¶
ob-analytics validate <source> runs the pipeline and prints a per-run
data-quality summary — the health signals worth checking before you trust a
feed. Point it at the same source you would pass to process:
ob-analytics validate orders.csv
ob-analytics validate data/ --format lobster --trading-date 2012-06-21
ob-analytics validate orders.csv --json # machine-readable, for CI
Text output looks like this (bundled Bitstamp sample):
Data quality summary
feed type : diff_feed
events / orders : 314,057 / 156,902
trades : 284
crossed resting book : 92.02% of session (6348 episode(s)) [expected for a diff feed — faithful replay, not a bug]
unmatched trades : 0.70%
duplicate event ids : 0
duplicate created ids : 0
pre-existing orders : 13
Reading the metrics¶
| Field | Read it as |
|---|---|
| feed type | matched_book (LOBSTER/MBO) or diff_feed (Bitstamp) — sets expectations for the next line |
| crossed resting book | Share of session time with best_bid > best_ask. ~0% for a matched book; high is normal and faithful for a diff feed |
| unmatched trades | Trades with no resolvable maker/taker resting order |
| duplicate event ids / created ids | Should be 0; anything else is a feed defect worth chasing |
| pre-existing orders | Orders already resting when the capture began (no created row) — structurally unclassifiable, not errors |
A high crossed resting book number on a diff_feed is expected — see
Data quality: matched book vs diff feed for why, and for
the uncross= option that cleans the book up for display without touching
the data you analyse. On a matched_book, a non-zero figure is a red flag.
From Python¶
from ob_analytics import Pipeline, BitstampFormat, FeedType, data_quality_summary
result = Pipeline().run("orders.csv")
summary = data_quality_summary(
result.events, result.trades,
feed_type=BitstampFormat().feed_type, # or getattr(fmt, "feed_type", FeedType.UNKNOWN)
depth=result.depth, # faithful depth; not depth_summary
)
print(summary.render())
summary.to_dict() # JSON-serialisable
Pass depth, not depth_summary
Crossing is measured from the faithful resting book. depth_summary is
already uncrossed by the depth engine, so passing it would always report
~0%. Omit depth and it is recomputed from events.
Related¶
- Data quality: matched book vs diff feed — the concepts behind these numbers
- Run from the command line — every CLI verb
data_quality_summaryreference