Skip to main content

Pramaa

CI License: MIT Python 3.12+

Pramaa is a conformal forecasting library for panels of time series. It makes point forecasts at many origins, reconciles them over a hierarchy, and calibrates bands and bounds from out-of-sample residuals.

Install

Install pramaa from PyPI:

pip install pramaa
# or
uv add pramaa

The vendor model adapters need an extra: stats (statsforecast), ml (mlforecast), or neural (neuralforecast).

pip install "pramaa[stats]"

Quick start

import numpy as np
import pandas as pd

from pramaa import Absolute, BottomUp, Hierarchy, LeadTime, Panel, SeasonalNaive, Signed
from pramaa import SplitQuantile, Step, replay, rolling_forecasts
from pramaa.metrics import coverage

rng = np.random.default_rng(0)
series = np.array(["a", "b", "c"])
periods = pd.date_range("2024-01-01", periods=120, freq="D")
panel = Panel(series, periods, rng.poisson(5.0, (3, 120)), "D")
hierarchy = Hierarchy.from_attributes(
    series, pd.DataFrame({"group": ["x", "x", "y"]}, index=series)
)

origins = np.arange(60, 113)  # each origin is the index of the last observed period
run = rolling_forecasts(panel, hierarchy, SeasonalNaive(7), BottomUp(hierarchy), origins, 7)
actuals = hierarchy.aggregate(panel.values)

calibrator = SplitQuantile(0.9, window=28)
bands = replay(run, actuals, target=Step(), score=Absolute(), calibrator=calibrator)
bound = replay(run, actuals, target=LeadTime(7), score=Signed(), calibrator=calibrator)
print(coverage(bands.target, bands.lower, bands.upper))

Concepts

Shapes use these axes: B bottom series, T periods, N nodes with bottoms first, S forecast series (B for BottomUp, N otherwise), O origins, H forecast steps, and C target columns (H for Step, 1 for LeadTime).

Panel and Hierarchy go to the Forecaster, base forecasts to the Reconciler, points to the Calibrator, bounds to order_up_to and settle

Stage Names
Data Panel, Hierarchy, Covariate
Forecast Forecaster, Reconciler (BottomUp, Identity, WlsStruct), rolling_forecasts
Calibrate Target (Step, LeadTime), Score (Absolute, Signed), Loss (Miss), Calibrator (SplitQuantile, ACI, QuantileTracker, RiskControl), step, replay
Decide critical_ratio, order_up_to, settle
Measure pramaa.metrics: coverage, width, interval score, pinball, cost

Two rules hold everywhere. A model reads only its window, so a later value cannot change a point unless a covariate declares it known ahead. A calibrator sees a score only once its target is known, and before the origin that knows it issues.

Architecture has the shapes and the modules.

Write a calibrator

A calibrator owns its target, a level or a loss, and is three functions of an explicit state. pramaa.online handles the origins, the delays, and the indexing. A new method is one file in pramaa/conformal/calibrators/ that imports only calibrators.base, calibrators.ranks, and conformal.losses. This is the whole of a quantile tracker:

import numpy as np

from pramaa.conformal.calibrators.base import Calibrator


class Tracker(Calibrator):
    def __init__(self, level, lr):
        self.level = level
        self.lr = lr

    def initial_state(self, n_nodes, n_columns):
        return {"q": np.zeros((n_nodes, n_columns))}

    def update(self, state, feedback):
        q = state["q"].copy()
        for row, column in enumerate(feedback.column):  # one row = one origin, one column
            miss = feedback.scores[row] > feedback.issued[row]
            q[:, column] += self.lr * (miss - (1 - self.level))
        return {"q": q}

    def threshold(self, state):
        return state["q"].astype(np.float32)

Keep the state in numpy arrays. Then a product can save it after each origin with pramaa.online.state.flatten and continue from it.

Models

Model Kind Install
pramaa.forecast.models.naive.SeasonalNaive local core
pramaa.forecast.models.statsforecast.StatsForecastModel local, any statsforecast.models model pramaa[stats]
pramaa.forecast.models.mlforecast.MLForecast global regressor with lags and covariates pramaa[ml]
pramaa.forecast.models.neuralforecast.NeuralForecast global network from neuralforecast.models pramaa[neural]
from lightgbm import LGBMRegressor
from pramaa import BottomUp, Covariate, rolling_forecasts
from pramaa.forecast.models.mlforecast import MLForecast

model = MLForecast(
    LGBMRegressor(), lags=[7, 14, 28], features=["price"], fit_periods=365, lookback=84
)
price = Covariate(prices, known_ahead=True, aggregate="mean")  # [B, T + H]
run = rolling_forecasts(
    panel,
    hierarchy,
    model,
    BottomUp(hierarchy),
    origins,
    28,
    refit_every=7,
    covariates={"price": price},
)

Benchmarks

bench/ is a folder of scripts. They load benchmark data from a directory, run benchmark protocols, and compare calibrators. They import the installed pramaa. Raw data is not in Git.

Script Content
vn2.py load(path): weekly VN2 sales with the out-of-stock mask, hierarchy, and starting stock. play(data, bounds): six orders up to the bounds, eight settled weeks, holding 0.2 and shortage 1.0
m5.py load(path): daily M5 sales and the 12-level hierarchy (42,840 nodes). prices(horizon): the sell price covariate
compare.py compare(forecasts, actuals, calibrators, target, score, level): one row of metrics per method, on the cells where each method was ready

vn2_conformal.py runs the whole VN2 path in about one second:

uv run python bench/vn2_conformal.py data/vn2

Documents

Development

uv sync --group dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run ty check src/
uv build --no-sources

See Contributing.

License

MIT

Metadata

Release files for pramaa 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pramaa 0.1.0
File Size Uploaded Provenance Actions
pramaa-0.1.0.tar.gz 27.1 kB Without provenance Details for pramaa-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pramaa 0.1.0
File Interpreter ABI Platform Actions
pramaa-0.1.0-py3-none-any.whl Python 3 none any Details for pramaa-0.1.0-py3-none-any.whl

Total release size: 68.4 kB

Release files / pramaa-0.1.0.tar.gz

Download URL pramaa-0.1.0.tar.gz
Size 27.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1cfe59b097f71ed9a47bb641d5203b94b198b0f5a29e06b8fdb18777958e04b5
BLAKE2b-256 checksum
How to use checksums
86bd4fe13813caa8576852cf325d7d266757157656d4ab6d06e51c28319eeacb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / pramaa-0.1.0-py3-none-any.whl

Download URL pramaa-0.1.0-py3-none-any.whl
Size 41.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
29f64c49eb8340742786a9f085b28b5df8fc25bca0cfdf0135471b6182863899
BLAKE2b-256 checksum
How to use checksums
818e2c378a40f69e608b0d5f1e6d6fbf062219ec3e2c6a74357942a37a6d2a8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for pramaa 0.1.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A 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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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