Skip to content

Contracts

The frozen types every layer speaks. contracts is one of only two modules other layers may deep-import (the other is leads).

Frozen contracts shared by every layer: variables, matrices, and the Blender protocol.

This module and leads are the only modules other packages may deep-import from. Blenders import contracts only, never the dataset layer.

VariableSpec dataclass

One canonical forecast variable in normalized metric units.

ProductSpec dataclass

Temporal contract for one emitted product.

ContractViolationError

Bases: ValueError

A dataclass invariant in this module was violated.

MixedProvenanceError

Bases: ValueError

Live and synthetic rows were combined without explicit consent.

ForecastMatrix dataclass

Aligned per-row source forecasts handed to a blender.

values is (n, k) float64 with NaN where a source is unavailable; availability is its explicit ~isnan so blenders never re-derive it inconsistently. features carries aligned context columns (calendar, lead, source ages, issue-time observations) and never truth columns.

build classmethod

build(
    sources: tuple[str, ...],
    values: FloatArray,
    lead_hours: FloatArray,
    features: DataFrame,
    product: Product = Product.HOURLY,
) -> Self

Construct with availability derived from the NaN pattern.

SupervisedSlice dataclass

Training data for one variable: a matrix plus non-null truth.

BlendResult dataclass

A blender's output: points, optionally with predictive quantiles.

Blender

Bases: Protocol

One forecasting method; baselines included. Fresh instance per fit.

fx_col

fx_col(source: str, variable: str) -> str

Forecast column for one source and canonical variable.

fxd_col

fxd_col(source: str, variable: str) -> str

Daily-forecast column for one source and canonical daily variable.

age_col

age_col(source: str) -> str

Hours-since-fetch column for one source.

finite_number

finite_number(value: object) -> float | None

A real, finite number, or None for missing/non-numeric/NaN/inf.

The single numeric guard for operator-facing evidence. isinstance admits NaN (and bool), and every NaN comparison is False, so a raw isinstance check silently renders a broken signal as healthy.

provider_age_is_fresh

provider_age_is_fresh(
    value: object, cap_hours: float
) -> bool

Whether a provider age is a real age inside the serving cap.

Bounded below as well as above. An age is the gap between a fetch and the snapshot that selected it, so a negative one is not fresher-than-fresh — it means the fetch is stamped in the future, which is a clock or provenance fault, and reporting it as healthy hides exactly that.

obs_col

obs_col(variable: str) -> str

Station observation at issue time (leakage-safe past data).

truth_col

truth_col(
    variable: str, semantics: TruthSemantics | None = None
) -> str

Truth column, optionally with dual-semantics suffix.

parse_fx_col

parse_fx_col(column: str) -> tuple[str, str]

Invert :func:fx_col/:func:fxd_col into (source, variable).