Skip to content

🇬🇧 English · 🇪🇸 Español

Signal contract

Status: Slice 1 shipped in 0.65.0 (sparsity-only quality). Slice 2 (draws + propagation) and Slice 3 (calibration) are planned.

The signal contract is the per-RiskIndex data shape that lets a downstream LP / SVAR estimator know how reliable an index reading is and (later) propagate that reliability into IRF bands.

Schema (Slice 1)

puremacro.narrative.types.RiskIndex carries two optional fields:

@dataclass
class RiskIndex:
    name: str
    country: str
    series: pd.Series
    method: str
    corpus: str
    language: str
    normalization: str
    metadata: dict
    quality: SignalQualityReport | None = None   # 0.65.0+
    draws:   pd.DataFrame | None          = None  # 0.66.0+

Both default to None — every pre-0.65.0 caller behaves identically.

Opt-in (Slice 1)

from puremacro.narrative.indices import lui

ri = lui(records, country="USA", language="en", with_quality=True)
ri.quality.summary()      # one-row DataFrame: mean_n_docs, mean_doc_length, n_coverage_gaps, ...

The same with_quality=False kwarg sits on every canonical index in puremacro.narrative.indices.__all__: epu, mpu, gpr, tone, wui, lui, ltui, ltui_up, ltui_down, lwui, lwui_wage, bbui, cboui, ep_ui, erpui, eurlex_ui, sotuui, bluesky_ui.

SignalQualityReport (Slice 1 fields populated)

Field Populated in Description
n_docs_per_period 0.65.0 docs per quarter that fed the kernel
avg_doc_length 0.65.0 mean tokens per doc per quarter
coverage_gaps 0.65.0 quarters with zero docs inside the date range
kernel_agreement 0.66.0 mean pairwise corr across kernel draws (Slice 2)
multilingual_parity 0.66.0 corr between language subsets (Slice 2)
doc_bootstrap_sd 0.66.0 per-period sd across doc-bootstrap draws (Slice 2)
corpus_loo_max_swing 0.66.0 max |Δ| across leave-one-corpus draws (Slice 2)
benchmark_scores 0.67.0 per-key Pearson/Spearman/RMSE vs. canonical (S3)
event_panel 0.67.0 rank-corr + top-decile hit + AUC vs. event panel
survey_scores 0.67.0 per-key Pearson/RMSE vs. survey series

Validation

RiskIndex.__post_init__ validates draws (when set): - draws.index must equal series.index. - draws.columns must be a 2-level pd.MultiIndex named ['source', 'draw_id']. - Every value of the source level must be in {'kernel', 'lexicon', 'doc', 'corpus'}.