numeraire-graphics
Grammar-of-graphics figures over numeraire's results and Output objects. Part of the numeraire ecosystem.
plotnine is primary. Every plot function returns a ggplot grammar object — it never draws,
shows, or saves. You compose the returned object freely (+ theme_numeraire() and friends) and,
when you are ready, hand it to the one explicit save surface, save_paper, for centimetre-exact
figures. Core numeraire stays visualization-free; this is a separate, optional package.
Two input families
The plots divide by what they consume:
- Family A — result-schema plotters (
numeraire_graphics.plots) read the tidy result table every evaluator emits (the columns below). They are the default surface: comparison figures assembled straight from a run's results. - Family B — Output/frame plotters (
numeraire_graphics.outputs) need richer inputs the tidy schema deliberately does not carry — a per-date × asset weight stream, a factor-loadings panel, a risk-return frontier trace. They take a numeraire Output object (e.g. aWeightsOutput) or a caller-supplied frame directly. The contract is otherwise identical (return aggplot, never draw or save); only the input differs.
The split is principled, not ad hoc: the tidy result schema has one row per (method, date, metric)
with a single scalar value and no asset/factor/frontier axis, so a figure that needs that axis
cannot be schema-fed and is a family-B plotter by construction.
Install
pip install numeraire-graphics # pulls in numeraire, plotnine, matplotlib, mizani
The result schema
Everything here consumes numeraire's tidy result table (the columns every evaluator emits):
run_id, method, date, metric, value, universe, capability, protocol, config_hash, data_vintage
Two idioms drive the figures: per-date rows (one row per date per method — e.g.
StrategyReturnEvaluator emits metric="strategy_return") feed the time-series plots, and
summary rows (one scalar row per method — e.g. metric="sharpe") feed the bar/curve plots.
Family A — result-schema plotters (numeraire_graphics.plots)
| function | reads | draws |
|---|---|---|
plot_cumulative(results, *, benchmark=None, recessions=None) |
metric == "strategy_return" per-date rows |
geometric wealth curve + drawdown facets, optional dashed benchmark line and geom_rect recession shading (dates supplied by the caller) |
plot_rolling(results, *, window, metric="sharpe") |
the same per-date returns | trailing-window rolling Sharpe / mean / vol, one line per method |
plot_metric_by(results, *, metric, x="method") |
a scalar summary metric |
bars across a grouping column, with CI whiskers when a confidence interval is derivable |
plot_complexity_curve(results, *, x, metric, ribbon=None) |
a scalar metric + a caller-joined numeric x |
metric-vs-complexity curve with an optional ribbon band |
plot_ic_decay(results, *, horizon="horizon", metric="ic", smooth=False) |
the ic rows (ICEvaluator) + a caller-joined numeric horizon |
information-coefficient decay curve by method, over a zero line, optional linear smooth |
x in plot_complexity_curve (a shrinkage intensity, parameter count, ...) and horizon in
plot_ic_decay are not part of the result schema — you join the column onto the frame yourself
and name it; the function will not invent it. For the IC decay curve you assemble the axis by running
forecasts at several horizons, running ICEvaluator on each ForecastOutput, and tagging every
resulting ic row with its numeric horizon before stacking the frames.
Family B — Output/frame plotters (numeraire_graphics.outputs)
| function | consumes | draws |
|---|---|---|
plot_weights_heatmap(weights_output, *, top=None, order="mean") |
a WeightsOutput / PanelWeightsOutput object |
a date × asset weight matrix as geom_tile, signed long/short (compose with scale_fill_numeraire(diverging=True)); top keeps the N largest-average-|weight| names, order sorts the asset axis |
plot_factor_loadings(loadings, *, x=None) |
a caller-supplied tidy loadings frame (factor, loading, an axis like date/entity) |
loading paths over x faceted/coloured by factor, or a loadings heatmap when x is absent |
plot_frontier(frontier, *, points=None) |
a caller-supplied risk/return frame |
the efficient-frontier curve, optionally overlaying named portfolios (points with risk/return/label) as labelled markers |
There is no standard core surface for a loadings panel (it is method-local — an IPCA Γ, a
rolling-beta panel) or a frontier trace, so those two take frames directly. The weights heatmap does
consume a first-class core object (WeightsOutput / PanelWeightsOutput from
numeraire.core.engine). mean_variance_frontier(mean, cov, *, n=50) is a small numpy-only
convenience (not core, not an optimizer) that traces a risk/return frame from a mean vector and
covariance for callers who lack a frontier of their own.
Helpers
theme_numeraire(base_size=8, base_family="serif")— the house theme (publication-oriented).scale_color_numeraire(palette="okabe_ito", greyscale=False)— a colourblind-safe discrete colour scale (Okabe-Ito by default;greyscale=Truefor monochrome print, paired with linetypes).scale_fill_numeraire(palette="okabe_ito", greyscale=False, diverging=False)— thefillcounterpart: a discrete Okabe-Ito fill for grouped bars (plot_metric_by), or, withdiverging=True, a continuous zero-centred fill for the signed weights heatmap (blue = short, vermillion = long).save_paper(plot, path, *, width_cm, height_cm, font_profile="latex")— the sole save surface; sizes the figure exactly in centimetres under a print font profile.
from numeraire_graphics import plot_cumulative, theme_numeraire, scale_color_numeraire, save_paper
fig = plot_cumulative(results) + theme_numeraire() + scale_color_numeraire()
save_paper(fig, "cumulative.pdf", width_cm=8, height_cm=6)
Conventions
Okabe-Ito palette by default, greyscale-safe linetypes, zero-reference lines, percent axis labels where the quantity is a return. Figure captions belong in the LaTeX document, not baked into the figure.
Roadmap
[altair]extra: a narwhals-native exploration surface (tooltips, selection, HTML sharing).[tables]extra: publication tables (great_tables) companion to the figures.- First-class loadings:
plot_factor_loadingsandplot_frontierare frame-fed because numeraire has no standard loadings/frontier surface today; if a core loadings accessor lands (e.g. a Γ panel accessor), the loadings plot can consume the object directly like the weights heatmap does.
Citation
numeraire-graphics is a companion to numeraire. If you use the ecosystem in your research, please
cite numeraire — see How to cite.
License: BSD-3-Clause.
Metadata
Release files for numeraire-graphics 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| numeraire_graphics-0.1.1.tar.gz | 34.4 kB | With provenance | Details for numeraire_graphics-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| numeraire_graphics-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for numeraire_graphics-0.1.1-py3-none-any.whl |
Total release size: 57.9 kB
Release files / numeraire_graphics-0.1.1.tar.gz
| Download URL | numeraire_graphics-0.1.1.tar.gz |
|---|---|
| Size | 34.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ff90b85073b54a9b3d668d3056b135683fff9d41ea38085a99006099e33ef116
|
|
BLAKE2b-256 checksum How to use checksums |
8781a7b7f84f5edcf3b92d0d204fd449e238781176f973e23478d69e15e6be35
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency logRelease files / numeraire_graphics-0.1.1-py3-none-any.whl
| Download URL | numeraire_graphics-0.1.1-py3-none-any.whl |
|---|---|
| Size | 23.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6d8c6dfa57f840e7a9101556ee75a9b3c4e1a826d43619d11284ebaa72a7a87
|
|
BLAKE2b-256 checksum How to use checksums |
0eb16364ae7c018c65e5474e853a62ba87041a5027fc67f0113a3c6e9554d028
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency logSecurity for numeraire-graphics 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for numeraire_graphics-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.