Independent Bayesian regularization

method=‘independent’: prior, model and consensus precision

Scope and names

The reference calls this method independent. Its implementation is IndependentBayesianRegularizedPredictionSignal in Exabel’s Bayesian signal. postforecast.bayesian_kpi_predictions implements its mathematics over a tidy estimate panel. It reads the panel at an explicit UTC as_of moment.

  • Independent: Combines a prior and independent noisy readings using inverse variances.
  • Correlation adjusted: Conditions a joint Gaussian distribution on both readings; see the separate mathematical reference.
  • Bias correction: An option applied to consensus levels before either method.
  • Dispersion/count weighting: Options for independent consensus precision.
  • Backtests/predictions/combined: Output selections, not different estimators.

The existing BayesianPosterior remains the earlier tutorial API. Its input is a prepared subject frame. It has different missing-model-precision semantics and uses underscore column names. The complete reference workflow uses the original hyphenated output names and stdev_weighted_consensus argument.

Growth coordinates

Let \(y_t\) be realized KPI level and \(b_t\) the latest nonmissing actual with a period end strictly before \(t\). For model level \(a_t\) and consensus level \(c_t\):

\[ x_{A,t}=\frac{a_t}{b_t}-1,\qquad x_{C,t}=\frac{c_t}{b_t}-1,\qquad \widehat y_t=b_t(1+\widehat\theta_t). \]

  • Zero base: Growth is unavailable when \(b_t=0\).
  • Realized growth: The historical prior sample is \(g_t=y_t/y_{t-1}-1\).
  • Missing observations: Only aligned nonmissing observations enter an error sample.
  • Training start: start_date truncates levels before growth is calculated.
  • History selection: Historical model and consensus observations are anchored before their actual’s first publication; later revisions cannot change them.

Prior and error precision

With \(n\) realized growth observations, the prior is

\[ \mu_0=\frac1n\sum_i g_i,\qquad s_0^2=\frac{1}{n-1}\sum_i(g_i-\mu_0)^2,\qquad \tau_0=\frac1{\max(s_0^2,\varepsilon)},\quad \varepsilon=10^{-12}. \]

At least \(\max(2,\texttt{minimum_observations})\) observations are needed for this sample variance. Source precision uses mean squared error, not a centered sample variance:

\[ e_{j,i}=|x_{j,i}-g_i|,\qquad v_j=\frac1{n_j}\sum_i e_{j,i}^2,\qquad \tau_j=\frac1{\max(v_j,\varepsilon)},\quad j\in\{A,C\}. \]

use_absolute_errors=False instead uses

\[ e_{j,i}=\left|\frac{x_{j,i}-g_i}{|g_i|}\right|. \]

Zero realized growth is excluded from that relative-error sample. Each source needs minimum_observations errors; its default is 3 and its permitted minimum is 1. The prior still needs at least two realized growth observations.

  • Backtests: Expanding prior and error moments are shifted by one observation. A target’s actual and error cannot affect its own posterior. Moments are aligned to the original observation indexes; missing historical precisions are not filled forward.
  • Predictions: The complete realized training sample is fitted once and its moments are held fixed across the forward horizon.
  • Combined: Each output column takes historical values strictly before that column’s first nonmissing forward value, then appends its forward values.

Independent posterior

Assuming an independent normal prior and normal observations:

\[ \theta\sim N(\mu_0,\tau_0^{-1}),\qquad x_A\mid\theta\sim N(\theta,\tau_A^{-1}),\qquad x_C\mid\theta\sim N(\theta,\tau_C^{-1}), \]

\[ T=\tau_0+\tau_A+\tau_C,\qquad \widehat\theta=\frac{\mu_0\tau_0+x_A\tau_A+x_C\tau_C}{T},\qquad s_\theta=T^{-1/2},\qquad w_j=\tau_j/T. \]

Adding an independent precision reduces the computed variance under these assumptions. It does not guarantee better predictive accuracy with correlated errors or misspecified variances.

  • Model excluded: include_model=False uses \(T=\tau_0+\tau_C\) and reports model weight zero. Model growth and model precision cannot be requested.
  • Missing historical model precision: An enabled model with unavailable precision prevents a historical posterior.
  • Missing fixed model precision: The reference’s forecast update becomes prior plus consensus. Its diagnostics still report missing model precision, total precision, weights and interval. The prediction can therefore exist without an interval. This asymmetry is preserved and tested.
  • Missing prior or consensus precision: No posterior is available.

Consensus dispersion and analyst count

With positive level-space dispersion \(d_t\) and positive contributor count \(n_t\):

\[ s_{C,t}=\frac{d_t}{|b_t|},\qquad v_{C,t}=m s_{C,t}^2,\qquad v_{C,t}^{\mathrm{count}}=\frac{m s_{C,t}^2}{n_t^\alpha},\qquad \tau_{C,t}=\frac1{\max(v_{C,t},\varepsilon)}. \]

  • Activation: stdev_weighted_consensus=True tries this precision first.
  • Calibration: consensus_stdev_variance_multiplier is \(m>0\), default 1.
  • Count weighting: consensus_count_exponent is \(\alpha\), default unset.
  • Fallback: Missing or nonpositive dispersion/count uses the historical consensus error precision, if available.
  • Configuration: Count weighting and a nondefault multiplier require dispersion weighting. These options are unavailable for correlation adjusted.

Consensus bias correction

Bias correction happens in level space before growth, using relative consensus errors against actuals:

\[ r_t=\frac{c_t-y_t}{y_t},\qquad z_t=r_{t-1}. \]

A local-level Kalman filter processes the shifted errors. For process variance \(Q\) and measurement variance \(R\):

\[ P_t^-=P_{t-1}+Q,\qquad K_t=\frac{P_t^-}{P_t^-+R},\qquad \beta_t=\beta_{t-1}+K_t(z_t-\beta_{t-1}),\qquad P_t=(1-K_t)P_t^-. \]

  • Initialization: The first finite observation sets \(\beta=z\) and \(P=R\).
  • Missing error: State is held; variance is not advanced on missing observations.
  • Defaults: consensus_bias_process_noise=1, consensus_bias_measurement_noise=0.5, consensus_bias_lambda=0.
  • Adjustment: For \(\lambda\in[0,1]\), \(c_t^*=c_t/(1+\lambda\beta_t)\).
  • Invalid scale: An unavailable or nonpositive scale retains the original consensus, matching the reference’s declared bias behavior.
  • Diagnostic: consensus-bias-pct is \(100\beta_t\), in percentage points.
  • Zero strength: Requesting the bias diagnostic still runs the filter when \(\lambda=0\); consensus remains unchanged.
  • Forecast hold: The reference shifts errors on the joint historical index, then forward-fills the filtered bias onto consensus timestamps. Its final realized error is not assimilated again at the first forecast timestamp.

Both methods use \(c^*\) for the consensus growth and error history. Neither reinterprets dispersion around the adjusted level.

Student-t intervals

The interval is a calibrated Student-t band around posterior growth, using the normal update’s standard deviation:

\[ q_L=t_\nu^{-1}((1-p)/2;\ell,s),\qquad q_U=t_\nu^{-1}(1-(1-p)/2;\ell,s), \]

\[ \theta_L=\widehat\theta+s_\theta q_L,\qquad \theta_U=\widehat\theta+s_\theta q_U. \]

  • Defaults: \(p=0.90\), \(\nu=1.5\), \(\ell=0.5\), \(s=2.75\).
  • Growth bounds: posterior-growth-lower and posterior-growth-upper.
  • Level bounds: Convert both with \(b_t(1+\theta)\), then sort them so a negative base cannot reverse prediction-lower and prediction-upper.
  • Interpretation: These configured heavy-tailed intervals are not the conjugate Gaussian posterior’s ordinary credible interval.

Reference output names

Output Quantity
prediction \(b_t(1+\widehat\theta)\)
prediction-lower Lower sorted level bound
prediction-upper Upper sorted level bound
model Raw model level
consensus Raw consensus level
posterior-growth \(\widehat\theta\)
posterior-growth-lower \(\theta_L\)
posterior-growth-upper \(\theta_U\)
model-growth \(x_A\)
consensus-growth Growth of adjusted consensus
actual-growth Realized growth
prior-mean \(\mu_0\)
prior-precision \(\tau_0\)
model-precision \(\tau_A\)
consensus-precision \(\tau_C\)
total-precision \(T\)
posterior-growth-stdev \(T^{-1/2}\)
prior-weight \(w_0\)
model-weight \(w_A\)
consensus-weight \(w_C\)
consensus-stdev Level dispersion
consensus-stdev-growth \(d_t/\lvert b_t\rvert\)
consensus-count Analyst count
adjusted-consensus \(c_t^*\)
consensus-bias-pct \(100\beta_t\)

Growth outputs are fractions, not percentages. Only consensus-bias-pct uses percentage points. Raw levels and consensus-derived levels remain distinct from relative outputs; requesting a level may have licensing implications for the caller’s publication policy.

Publication-relative reads

  • Fixed horizon: relative_to="publish", relative_days=h, with \(h\le0\). The pd alias is accepted. Omitting the horizon selects zero days.
  • Latest horizon: relative_days="latest" derives the day offset between the latest live model revision and that period’s supplied publication date.
  • Missing latest horizon: A company without a usable live prediction or publication date receives latest_horizon_unavailable; other companies continue.
  • Availability gate: Target \(t\) requires \(\mathrm{publication}_t+h\ge \mathrm{publication}_{t-1}\); equality passes this gate.
  • Reading boundary: Model and consensus values must be known strictly before the smaller of the explicit as_of and the horizon cutoff. This package preserves its exclusive timestamp contract; Exabel’s external date-version loaders are not part of the numerical port.
  • Delayed history: Earlier actuals must also have been published by the reading cutoff; unavailable history refuses the row and its diagnostics.
  • Supplied schedule: Pass subject keys and UTC publication_date in publications. Schedule provenance remains the caller’s responsibility.

Executable example

Show the code
import pandas as pd
import pf
import postforecast as pfc

settings = pfc.BayesianPredictionSettings(
    version="independent-example",
    method="independent",
    series="predictions",
    values=("prediction", "posterior-growth", "prior-weight", "model-weight", "consensus-weight"),
)
result = pfc.bayesian_kpi_predictions(
    pf.quarterly_history(),
    pd.Timestamp("2026-05-10", tz="UTC"),
    forecast_source="model",
    settings=settings,
)
result[["entity", "period", *settings.values, "eligible"]]
entity period prediction posterior-growth prior-weight model-weight consensus-weight eligible
0 ZS 2026-06 800.648824 0.049481 0.830506 0.094336 0.075158 True

See the coverage audit for the source mapping, parity evidence, and integration boundaries.