Skip to content

Metric registry

A metric measures a finished run and draws as a level-less plot. Every metric registers here under a name; third-party metrics load through the ob_analytics.metrics entry-point group (see Extending). A registered value is a Metric instance — a metric needs no per-run construction, so the object registered is the object called.

The name is also the plot concept the metric draws under, so a renderer registered at (name, None, backend) is the metric's face. A registered metric shows up in available_concepts(), renders through result.plot(name), and gets its own gallery card — with no edit to ob-analytics.

Metrics run on demand, not during Pipeline.run: use PipelineResult.metric for one, PipelineResult.metrics() for every metric that applies to the run's resolution. Settings are keyword arguments: result.metric("vpin", n_buckets=20), or result.plot("vpin", n_buckets=20, threshold=0.8), where each keyword goes to compute or prepare, whichever names it.

Built-in metrics

Name Measures Wraps
l1_ticker Best bid, best ask and last trade. Draws the three over time, or the quote card at at=. the depth summary and the trades
vpin VPIN per volume bucket compute_vpin
kyle_lambda Kyle's λ regression compute_kyle_lambda
order_flow_imbalance Order flow imbalance per window order_flow_imbalance
ofi_horizon Order flow imbalance over several horizons ofi_by_horizon

Each uses the defaults of the function it wraps. The gallery and result.plot give a metric the result in display units (quote currency, base asset); result.metric gives it the result as stored (integer ticks and lots), so a size setting such as bucket_volume is in those units there.

L1TickerMetric

The Level 1 quote: best bid, best ask and last trade through the run.

The table has one row each time the touch or the last trade changes. Its face draws the three prices over time, or, given at=, the quote card for that instant (see :func:~ob_analytics.visualization._data.prepare_l1_ticker_data).

compute

compute(result: Any) -> pd.DataFrame

Return timestamp, the touch prices and sizes, and the last trade.

Columns: timestamp, best_bid_price, best_bid_vol, best_ask_price, best_ask_vol, last_price, last_volume. Each row carries every value forward from the rows before it, so a row is the whole quote at that time. last_price is NaN before the first trade, and a side with no orders has a NaN price and size (the depth summary writes 0 there).

prepare

prepare(frame: DataFrame, **options: Any) -> dict[str, Any]

Payload for the face; options are those of prepare_l1_ticker_data.

VpinMetric

VPIN, from :func:~ob_analytics.flow_toxicity.compute_vpin.

compute

compute(
    result: Any,
    *,
    bucket_volume: float | None = None,
    n_buckets: int = 50,
    sign_method: str | None = None,
) -> pd.DataFrame

Return the per-bucket VPIN table; the settings are compute_vpin's.

prepare

prepare(
    frame: DataFrame, *, threshold: float = 0.7
) -> dict[str, Any]

Payload for the face; threshold is the alert line.

KyleLambdaMetric

Kyle's λ, from :func:~ob_analytics.flow_toxicity.compute_kyle_lambda.

The table is the per-window regression data. The fit itself is in the table's attrs: lambda_, t_stat, r_squared, n_windows, ci_low, ci_high, ci_level and diagnostics, as on :class:~ob_analytics.flow_toxicity.KyleLambdaResult.

compute

compute(
    result: Any,
    *,
    window: str = "5min",
    n_boot: int = 1000,
    ci_level: float = 0.95,
    seed: int | None = 0,
) -> pd.DataFrame

Return the regression table; the settings are compute_kyle_lambda's.

prepare

prepare(frame: DataFrame) -> dict[str, Any]

Payload for the regression scatter.

OrderFlowImbalanceMetric

Order flow imbalance, from :func:~ob_analytics.flow_toxicity.order_flow_imbalance.

The table adds last_price, the last trade price in each window, which the face draws as a price line behind the bars.

compute

compute(
    result: Any,
    *,
    window: str = "1min",
    sign_method: str | None = None,
) -> pd.DataFrame

Return the per-window table; the settings are order_flow_imbalance's.

prepare

prepare(frame: DataFrame) -> dict[str, Any]

Payload for the bars, with the window prices as the price line.

OfiHorizonMetric

Order flow imbalance over several horizons, from :func:~ob_analytics.flow_toxicity.ofi_by_horizon.

compute

compute(
    result: Any,
    *,
    horizons: tuple[str, ...] = OFI_HORIZONS,
    grid: str = "5s",
    sign_method: str | None = None,
) -> pd.DataFrame

Return the grid table; the settings are ofi_by_horizon's.

prepare

prepare(
    frame: DataFrame,
    *,
    start_time: Timestamp | None = None,
    end_time: Timestamp | None = None,
) -> dict[str, Any]

Payload for the horizon graph, for the steps from start_time to end_time.

Registry

register_metric

register_metric(metric: Metric) -> None

Register metric under its own :attr:~ob_analytics.protocols.Metric.name.

Case-insensitive; overwriting an existing registration is allowed (handy for tests and for a plug-in that intentionally shadows a built-in).

list_metrics

list_metrics() -> list[str]

Return a sorted list of registered metric names.

get_metric

get_metric(name: str) -> Metric

Return the metric registered under name (case-insensitive).

Raises:

Type Description
KeyError

If no metric is registered under name; the message lists the registered names.

load_metric_plugins

load_metric_plugins(*, force: bool = False) -> list[str]

Discover and register metrics advertised via entry points.

Scans the :data:ENTRY_POINT_GROUP entry-point group; each entry's value is loaded to a :class:~ob_analytics.protocols.Metric class, instantiated with no arguments, and registered under its own name. This is what lets a metric live in a separate installable package without editing ob-analytics.

Idempotent: the scan runs once per process unless force is set (the test suite forces a re-scan after monkeypatching the entry points). A plug-in that fails to import is logged and skipped, so one broken package cannot stop the rest from loading.

Returns:

Type Description
list of str

The names newly registered by this call.