Changelog¶
All notable changes to ob-analytics are documented in this file.
The format is based on Keep a Changelog.
[0.1.0] - 2026-06-26¶
First public release (PyPI). The Python port of the R obAnalytics package, reworked into a pipeline API with pluggable formats, flow-toxicity metrics, L2/L3 visualization, and Matplotlib/Plotly backends — plus the packaging, documentation, and distribution that make it installable. The sections below also record how the API was deliberately de-bloated and unified during the port (the pipeline's numeric output is unchanged — the regression fingerprints pass; only the shape of the public API moved). See Extending ob-analytics.
Packaging & distribution¶
- The bundled Bitstamp sample ships gzip-compressed (
orders.csv.gz, ~23 MB → ~2.9 MB installed);sample_csv_path()returns the.gzpath, read transparently by pandas. No API change. - Published documentation site (GitHub Pages),
CITATION.cff, an explicit GPL-2.0-or-later license section, and a "Scale envelope" doc. - PyPI release workflow (
release.yml, trusted publishing), package classifiers and project URLs, andob_analytics.__version__. - Fixed quickstart and API-reference documentation drift.
Breaking¶
- Pydantic models removed.
ob_analytics.models(OrderEvent,Trade,DepthLevel,OrderBookSnapshot) deleted; the data contract is now column-list constants +validate_events_df/validate_trades_df/validate_depth_dfinob_analytics.schemas. metrics/package removed.ToxicityMetric,Vpin,Ofi,KyleLambda,register_metric, andlist_metricsare gone. Callcompute_vpin,compute_kyle_lambda, andorder_flow_imbalanceonresult.tradesdirectly.Pipeline(metrics=...)removed. Metrics are no longer a pipeline stage — compute them after the run.PipelineConfig.vpin_bucket_volumeremoved — passbucket_volume=tocompute_vpin.PipelineResultslimmed to exactlyevents,trades,depth,depth_summary, andconfig. Thevpin,ofi,metrics,metadata, andextrasattributes are gone.- The thirteen
plot_*wrappers removed → oneplot(name, *, backend="matplotlib", ax=None, **data)dispatcher keyed by(plot_name, backend); renderers self-register intoRENDERERS. - Global theme state removed.
set_plot_theme/get_plot_theme/_current_themedeleted; passtheme=PlotTheme(...)toplot(). - Exception hierarchy collapsed to
ObAnalyticsError+ConfigError.InvalidDataError,MatchingError,InsufficientDataError, andConfigurationErrorare removed. - Top-level
__all__trimmed to ~22 orchestration names. Low-level helpers now import from their submodules —ob_analytics.bitstamp,ob_analytics.lobster,ob_analytics.analytics,ob_analytics.depth,ob_analytics.data,ob_analytics.visualization,ob_analytics.flow_toxicity. Formatis now atyping.Protocol— there is no base class to inherit; any conforming object is recognised structurally.- Low-level helpers no longer re-exported from the package root (e.g.
depth_metricsis nowfrom ob_analytics.depth import depth_metrics). RunContext.extrasandFormat.collect_extrasremoved. LOBSTER trading halts are read fromLobsterLoader.trading_haltsand composed into the gallery viaextra_panels=.DepthMetricsEngine.update()removed → the public hot-path method isupdate_side(price, volume, side, out).
Added¶
ob_analytics.schemas— the single data contract: column-list constants (EVENT_COLUMNS,TRADE_COLUMNS,DEPTH_COLUMNS) plus thevalidate_*functions, run at the pipeline's Protocol boundaries. Replaces the Pydantic model layer.- One generic
Registry[K, V](ob_analytics._registry) backs the format, writer, capturer, and renderer registries. Register through the public helpersregister_format,register_writer,register_capturer, andRENDERERS.register/register_plot_backend. - Unified
plot()dispatcher +RENDERERSregistry keyed by(plot_name, backend), so new plots and backends plug in without a wrapper function. The HTML gallery composes custom panels viaextra_panels=. ob_analytics.live— optional sub-package for live order-book capture: theLiveCapturerprotocol (with an optionalSupportsDiagnosticscapability),CaptureConfig,CaptureResult,CaptureSink, and a generic asyncio runner. Capture output drops straight into the pipeline (orders.csvschema unchanged). Install withpip install "ob-analytics[live]".ob-analytics capture <venue>CLI verb with a built-inbitstampcapturer (ob_analytics/live/bitstamp.py);--listshows registered capturers.scripts/collect_bitstamp_btcusd.pyis now a thin wrapper around it.TradeSourceprotocol andBitstampTradeReader— read an authoritative companiontrades.csvand join it to events via thefillcolumn.RunContextdataclass (ob_analytics.protocols, re-exported at the top level) for per-run parameters such as LOBSTERtrading_datethat don't belong on long-livedFormatinstances.- Docs —
docs/extending.md(add a data source / writer / plot / metric / capturer). - Tests —
test_bitstamp.py,test_cli.py(subprocess smoke tests for all CLI subcommands),test_exceptions.py,test_data_registry.py, a regression snapshot suite pinning demo Parquet hashes + the Kyle-λ baseline, andob_analytics/__main__.py(python -m ob_analytics).
Changed¶
- Bundled sample —
ob_analytics/_sample_data/now shipsorders.csvandtrades.csvfrom a modern BTC/USD live capture (replaces the legacy 2015 orders-only slice). - Demos consolidated into
ob_analytics._demos;scripts/bitstamp_demo.py,scripts/lobster_demo.py, and thebitstamp-demo/lobster-demoCLI subcommands are now thin argparse wrappers. Behaviour unchanged. - Performance — the LOBSTER book is maintained as a
SortedDict(no per-event re-sort), Bitstamp trade→event resolution is indexed, LOBSTER depth uses a single strategy, the Plotly import is memoised, and depth metrics sum active levels into bps bins. Numeric output is unchanged (pinned by the regression snapshots). compute_kyle_lambdacomputes its OLS vianp.linalg.lstsq(was hand-rolled; agrees with the prior implementation tortol=1e-10).- Internal modules reorganized (renames from the 0.x line): e.g.
event_processing.py→bitstamp.py, validation/time helpers →_utils.py, and the visualization modules split into avisualization/subpackage. - Type checking is Astral's
ty(not mypy); lint and format are Ruff.
Removed¶
pacmanorder type. A legacy artifact of the 2015 Bitstamp HTTP API, where a singleorder_idcould appear at multiple prices over its lifetime. Modern Bitstamp WS v2 and LOBSTER do not produce this pattern (price-modifies become cancel + new id). ThetypeCategorical no longer includes"pacman", the set-subtraction classification path is gone, andLobsterLoaderno longer renumbers hidden-execution ids (raw type 5 now retains the native LOBSTERid=0).- Bitstamp trade inference. A companion
trades.csvnext toorders.csvis now required. Removed: Needleman–Wunsch matching,BitstampMatcher,BitstampTradeInferrer, theMatchingEngine/TradeInferrerprotocols,NeedlemanWunschMatcher, and thematch_cutoff_ms/price_jump_thresholdfields onPipelineConfig. - Zombie detection —
get_zombie_idsand thezombie_offset_seconds/skip_zombie_detectionconfig fields. - LOBSTER
LobsterMatcher— removed;LobsterTradeInferrerrenamed toLobsterTradeReaderwithload(events, source). - Legacy Bitstamp-only wrappers
load_event_data,event_match,match_trades,process_data, andplot_price_levels_faster. - 12 unused runtime dependencies (scikit-learn, scipy, jupyter, bokeh, …) and stale dev dependencies (black, flake8 + plugins, darglint).
Fixed¶
depth_metricsno longer overflows for prices > $9,999.99 — dynamicdict[int, int]state replaces the fixed array.best_bid/best_askare tracked correctly from the first event (were initialised with dataset-wide max/min).datetime_to_epochuses.astype("int64")instead of the deprecated.view("int64").- All
print()replaced withlogurulogging; all bareassertstatements replaced with raised exceptions;plt.show()removed from plot functions (callers control display).