Skip to main content

numeraire

A research framework for backtesting, comparing, and replicating empirical asset-pricing and financial-econometrics methods.

PyPI Python versions CI Documentation License: BSD-3-Clause

Documentation · Quickstart · API Reference · PyPI · Citation


numeraire provides a stable, representation-agnostic spine for empirical asset pricing: a point-in-time data view, a walk-forward out-of-sample engine, a library of evaluators and statistical tests, and a tidy result schema. Its core never encodes a specific method's internal form — it defines capabilities (what a model can produce: portfolio weights, return forecasts, a priced cross-section), and dispatches on them. Linear-factor, nonlinear, neural, and distributional methods are therefore all first-class, and each plugs into the same views, the same engine, and the same schema as a peer.

The numéraire is the reference unit against which all prices are measured. The framework is oriented toward reproducible empirical asset pricing: results are produced out of sample, on a recorded data vintage, and scored with a metric matched to the model.

Why numeraire

Empirical asset-pricing results are sensitive to a few well-known failure modes: a signal that overlaps the return it predicts, a headline metric mismatched to the model, or preprocessing that is not recorded. numeraire is designed so these are addressed by the structure of the framework.

  • Out-of-sample by construction. A point-in-time view exposes only the data available at each decision date, and the walk-forward engine computes realised returns from the original data rather than from a model's output. A conformance test perturbs future data and verifies that earlier outputs do not change.
  • The metric matches the object. Evaluators dispatch on what a model produces — a timing strategy is scored by its Sharpe ratio, a return forecast by its out-of-sample R², a pricing model by its cross-sectional fit.
  • Every result carries its provenance. Each result row records the data vintage, a hash of the method and preprocessing configuration, and whether the number is in-sample or out-of-sample.

Underlying this, the core describes a model by its capabilities — the outputs it can produce (portfolio weights, return forecasts, a priced cross-section) — not by any specific internal form. Methods as different as linear factor models, neural predictors, and stochastic discount factors run through the same engine, evaluators, and result schema.

Installation

pip install numeraire

numeraire requires Python 3.11+. The base install is the spine plus the native evaluators; opt into the companion packages and integrations through extras:

pip install "numeraire[all]"        # + the plotting and data companion packages
pip install "numeraire[graphics]"   # + numeraire-graphics (grammar-of-graphics figures)
pip install "numeraire[data]"       # + numeraire-dataset (data loaders and builders)
pip install "numeraire[skfolio]"    # + the skfolio portfolio-optimizer adapter

Using uv:

uv add numeraire            # or: uv add "numeraire[all]"

Quickstart

Build a point-in-time view, run a walk-forward out-of-sample backtest, and evaluate it — on synthetic data, no external source required:

import numpy as np
import pandas as pd

from numeraire import SharpeEvaluator, TimeSeriesView, WalkForwardSplitter, backtest
from numeraire.baselines import EqualWeight

rng = np.random.default_rng(0)
dates = pd.date_range("2000-01-31", periods=120, freq="ME")
returns = pd.DataFrame(rng.normal(0.01, 0.05, (120, 4)), index=dates, columns=list("ABCD"))

view = TimeSeriesView(returns)
splitter = WalkForwardSplitter(min_train=60, test_size=12)
result = backtest(EqualWeight(), view, splitter, method="equal_weight")

print(SharpeEvaluator().evaluate(result)[["method", "metric", "value", "protocol"]])

backtest reads the fitted model's capability and the view type and dispatches to the right typed driver; SharpeEvaluator emits rows of the standard tidy schema. See the quickstart for the full walk-through, including a forecasting example.

The ecosystem

numeraire is the spine of a small, deliberately decoupled family of packages. The core ships only tiny public example slices and no bundled methods; everything else is an optional, first-class peer.

Package Role Install
numeraire The spine: views, engine, evaluators, result schema, statistical tests. pip install numeraire
numeraire-graphics Grammar-of-graphics figures over the result schema and Output objects. pip install numeraire-graphics
numeraire-dataset Open, reproducible data loaders and point-in-time builders. pip install numeraire-dataset

Reproductions of published methods, and a lab's own unpublished methods, live in separate packages that register through the numeraire.methods entry-point group and pin numeraire — they are discovered at install time without any edit to core. A public reproduction collection is in preparation.

What you can do with it

  • Research — reproduce a published result within a tolerance band, and compare competing pricing models on one shared panel of test assets in the Fama–French / GRS tradition, with the corresponding significance tests.
  • Backtesting — construct portfolios and score them out of sample, turn a target-weight stream into realised net returns through an accounting simulator with explicit cost conventions, and evaluate with risk-adjusted, information-coefficient, and exposure measures.

Documentation

Full documentation — installation, a runnable quickstart, the architecture, the extension guide, and the API reference — is at https://numeraire.py-numeraire.org/.

How to cite

If you use numeraire in your research, a citation is appreciated. The repository ships a CITATION.cff (GitHub renders a Cite this repository button from it), and the equivalent BibTeX is:

@software{wu_numeraire,
  author  = {Wu, Yuheng},
  title   = {{numeraire: a research framework for backtesting, comparing,
             and replicating empirical asset-pricing methods}},
  year    = {2026},
  version = {0.2.1},
  url     = {https://github.com/py-numeraire/numeraire},
  license = {BSD-3-Clause}
}

Contributing

Contributions to the spine — evaluators, statistical tests, and engine or view improvements — are welcome. Methods are distributed as separate packages rather than added to core: a method is any object with fit(view) -> model that advertises a capability, registered through the numeraire.methods entry point and self-certified with numeraire.testing.check_estimator (see the extension guide).

Development uses uv, ruff, basedpyright (strict on core), and import-linter for the architecture boundary:

uv sync --extra dev
uv run ruff check . && uv run ruff format --check .
uv run basedpyright src/numeraire/core     # strict types on the spine
uv run lint-imports                        # architecture boundary
uv run pytest                              # tests (public / synthetic data only)

License

BSD-3-Clause. Author: Yuheng Wu. Tests use public or synthetic data only; never commit CRSP / WRDS / proprietary data or credentials.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

numeraire-0.2.2.tar.gz (364.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

numeraire-0.2.2-py3-none-any.whl (81.8 kB view details)

Uploaded Python 3

File details

Details for the file numeraire-0.2.2.tar.gz.

File metadata

  • Download URL: numeraire-0.2.2.tar.gz
  • Upload date:
  • Size: 364.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for numeraire-0.2.2.tar.gz
Algorithm Hash digest
SHA256 b9569c1916cb7ef0bc0c0d113f36440c9bb6f3923fb26d72a69903bcd4284133
MD5 94a2a71501ff15807cb748d73a1318fb
BLAKE2b-256 a5b93c32428ed070c37efbc69d00a7e94c8ba41a73ec95eb8c5ec5b651f3035e

See more details on using hashes here.

Provenance

The following attestation bundles were made for numeraire-0.2.2.tar.gz:

Publisher: publish.yml on py-numeraire/numeraire

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file numeraire-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: numeraire-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 81.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for numeraire-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2d4fd7e554b6ceab9489a734c11618a98db5d847eb8d57e3c64d07466bf42eea
MD5 74653c75cabdd6b24f674ed089357cd9
BLAKE2b-256 5de57fa88ec8928e9adcd8a437d666c68055d68a88965349f81ea1e33c946f93

See more details on using hashes here.

Provenance

The following attestation bundles were made for numeraire-0.2.2-py3-none-any.whl:

Publisher: publish.yml on py-numeraire/numeraire

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page