numeraire.testing#

Conformance suite — a reusable check_estimator any method self-certifies against.

Extension authors (in numeraire-zoo, numeraire-yourlab, or a standalone numeraire-<method> package) run check_estimator() on their estimator to prove it is a well-behaved framework citizen before wiring it into the engine. It is the sklearn-style analogue of sklearn.utils.estimator_checks.check_estimator: plain functions that raise AssertionError on the first violation, no base class to inherit.

This module is core infrastructure, not a method — it is exempt from the boundary rule’s methods/adapters import ban (it lives in numeraire proper, not numeraire.core, and imports only numeraire.core + numpy/pandas). It knows the two concrete core view types (TimeSeriesView, CrossSectionView) so the no-look-ahead check can build a future-perturbed twin generically.

The checks#

Given an estimator and a deterministic view_factory (a zero-arg callable returning an equivalent view each call — synthetic data with a fixed seed):

  • check_capabilities()fit returns a Model whose capabilities() intersect the core set {to_weights, to_forecast, to_pricing}, and every crystallized capability it declares has its method (to_weights / forecast / expected_returns).

  • check_output_shapes() — weights columns ⊆ view.assets and index ⊆ view.calendar (wide) or a [date, asset] MultiIndex (panel); a forecast is a pd.Series indexed by view.assets; pricing expected_returns is a (date x asset) frame with columns ⊆ view.assets and index ⊆ view.calendar.

  • check_determinism() — same estimator + same view ⇒ identical output, twice.

  • check_no_lookahead() — the property test for ``to_weights`` and ``expected_returns``. Both hand the model a multi-date view and require it to window internally, so its rows up to t must be invariant to mutating data strictly after ``t``; a model that peeks past a prediction date fails here (one leak channel, shared by a weight stream and a priced cross-section). to_forecast is deliberately not probed: the forecast-origin engine only ever hands forecast() a prefix-truncated view.window(origin), so a forecast at origin d is structurally incapable of seeing data after d — perturbing the future can’t change it, so a probe here can never fail (it would be dead code). That PIT guarantee is exercised where a leak actually surfaces: the zoo’s mandatory engine ≡ vectorized equality test, where a contemporaneous / off-by-one forecast leak makes the hand-written full-sample path disagree with the prefix-truncated engine path (see tests/test_testing.py for the mechanism).

  • check_engine_roundtrip() — the estimator runs through the matching walk-forward driver without error and an evaluator emits rows conforming to the result schema.

A pricing method (to_pricing, e.g. an IPCA adapter) now exercises the full suite: its expected_returns surface is crystallized, so the shape, determinism, no-look-ahead, and engine-round-trip checks all apply to it exactly as they do to a weights method.

check_estimator

Run the full conformance suite; raise AssertionError on the first violation.

check_capabilities

fit returns a Model with a recognized capability and its crystallized method(s).

check_output_shapes

Weights/forecast outputs obey the shape contracts (columns ⊆ assets; forecast index).

check_determinism

Same estimator + same (deterministic) view ⇒ bit-identical extractable output, twice.

check_no_lookahead

to_weights / expected_returns up to t are invariant to mutating data after t.

check_engine_roundtrip

The estimator runs through its matching walk-forward driver; result rows validate.