Skip to content

ump_spec.rules.dependence

module ump-spec

Dependence envelope for portfolio sums (G-DEP-01) and aggregation rules (G-UNC-01).

Summing per-channel intervals without joint draws: the median is taken under independence; the interval is the envelope between the independent sum (normal approximation from each channel’s interval) and the comonotone sum (quantiles add exactly when channels move together). Quantiles never sum as if they were draws: under quantiles/interval representations a sum is reported as these bounds.

class

class ChannelEstimate

Fields

NameTypeDefaultDescription
channelstr
medianfloat
intervalInterval | NoneNone
Methods and properties (1)

init constructor

ChannelEstimate(
self,
channel: str,
median: float,
interval: Interval | None = None,
) -> None

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 26

class

class DependenceEnvelope

Fields

NameTypeDefaultDescription
medianfloat
independentInterval
comonotoneInterval
envelopeInterval
methodstr
fallbackslist[FallbackEntry]field(default_factory=list)
noteslist[Note]field(default_factory=list)
Methods and properties (1)

init constructor

DependenceEnvelope(
self,
median: float,
independent: Interval,
comonotone: Interval,
envelope: Interval,
method: str,
fallbacks: list[FallbackEntry] = list(),
notes: list[Note] = list(),
) -> None

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 33

class

class DrawsEnvelope

Result of :func:dependence_envelope_draws.

For sum and mean the two coupling intervals are equal-tailed intervals of the per-draw output; for a scalar output (p10, CVaR, P(beat), regret, EVOI) each coupling gives one value, held as a zero-width interval, and envelope spans the two. point is the output under the independent coupling (for sum/mean, the median of its per-draw values).

Fields

NameTypeDefaultDescription
outputstr
envelope_kindEnvelopeKind
pointfloat
independentInterval
comonotoneInterval
envelopeInterval
seedint
fallbackslist[FallbackEntry]field(default_factory=list)
Methods and properties (1)

init constructor

DrawsEnvelope(
self,
output: str,
envelope_kind: EnvelopeKind,
point: float,
independent: Interval,
comonotone: Interval,
envelope: Interval,
seed: int,
fallbacks: list[FallbackEntry] = list(),
) -> None

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 135

function

def comonotone_sum(intervals: list[Interval]) -> Interval

Perfectly correlated channels: lower quantiles add, upper quantiles add.

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 44

function

def independent_sum(medians: list[float], intervals: list[Interval]) -> Interval

Independence, normal approximation per side (keeps skew: lower and upper half-widths are combined separately in quadrature).

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 51

function

def dependence_envelope(
channels: list[ChannelEstimate],
dependence: str = 'per_channel',
*,
level: float = 0.9,
mode: Literal['fallback', 'strict'] = 'fallback',
joint_draw_totals: list[float] | None = None,
) -> DependenceEnvelope

Sum channel estimates under the declared dependence (spec §7 table).

  • joint_draws with joint_draw_totals: per-draw quantiles, no fallback.
  • joint_gaussian / declared_assumption: run, labelled (note), still reports the envelope.
  • per_channel: median under independence, interval = envelope [independent, comonotone], fallback DEPENDENCE_ASSUMED (G-DEP-01).
  • none: impute each missing interval (UNCERTAINTY_IMPUTED, G-UNC-01), then as per_channel.

Strict mode raises DEPENDENCE_ASSUMED (422) where a fallback would be needed.

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 61

function

def dependence_envelope_draws(
channel_draws: Mapping[str, Sequence[float]],
*,
seed: int,
output: str = 'sum',
statistic: Callable[[list[float]], float] | None = None,
level: float = 0.9,
mode: Literal['fallback', 'strict'] = 'fallback',
) -> DrawsEnvelope

Portfolio output from per-channel draws that are not aligned (per_channel, spec §7 G-DEP-01).

  • Independent coupling: each channel’s draws permuted by one random.Random(seed), channels taken in sorted name order, so the result is reproducible and the seed is recorded.
  • Comonotone coupling: each channel’s draws sorted by value.
  • Per-draw totals are summed across channels (mean divides by the channel count). statistic maps a coupling’s per-draw totals to a scalar; it is required for cvar, monotone, p_beat, regret, evoi and non_monotone; p10 and quantile default to the 10th percentile (type 7).
  • envelope_kind is bound for sums, means, CVaR and monotone functions of sums, range otherwise. The fallback DEPENDENCE_ASSUMED carries it. Strict mode raises instead.

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 154

function

def allowed_aggregations(representation: str) -> dict[str, str]

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 251

function

def check_aggregation(
representation: str,
op: str,
*,
allow_points: bool = False,
) -> str

Return the rule for op or raise UNCERTAINTY_IMPUTED-family problems when not allowed.

Source: packages/ump-spec/src/ump_spec/rules/dependence.py, line 258

NameTypeValueDescription
JOINT_KINDSfrozenset[str]frozenset({'joint_draws', 'joint_gaussian'})
LABELLED_KINDSfrozenset[str]frozenset({'joint_gaussian', 'declared_assumption'})
BOUND_OUTPUTSfrozenset[str]frozenset({'sum', 'mean', 'cvar', 'monotone'})Sums, means, CVaR and monotone functions of sums: the union of the two couplings is a bound.
RANGE_OUTPUTSfrozenset[str]frozenset({'p10', 'quantile', 'p_beat', 'regret', 'evoi', 'non_monotone'})Quantile-type, non-monotone outputs and EVOI: the union is a range, never a bound.
EnvelopeKindLiteral['bound', 'range']
AGGREGATION_RULESdict[str, dict[str, str]]{'draws': {'sum': 'per_draw', 'mean': 'per_draw', 'difference': 'per_draw', '...Quantiles never sum: bounds_only means a sum is reported as dependence bounds (G-UNC-01).