What (One-liner)
Three-in-one market criticality heuristic: rising correlation × volatility suppression × heavy-tail regression → weighted fragility score [0, 1]. Self-declared 'not production risk model', used as a Canvas market state visual indicator.
How to use
Drag b0_criticality_v1 onto Canvas, connect upstream to price_factor_v1 node (Canvas automatically converts to returns), optionally manually fill correlations matrix. Typical usage:
price_factor → b0_criticality_v1 (returns auto) → reflexivity_detector_v1
↘
(multi-asset) correlations → cross-asset fragility overlayCore formulas
# Three independent gated components:
avg_corr = mean(upper_tri(correlations)) if len >= 2
vol = std(returns) * sqrt(252) if len > 10
suppr = 1 - min(1, vol / (max|r|*sqrt(252)+1e-9))
tail_α = -slope(log(rank) vs log(sort_desc(top-10%|r|))) if tail > 5
# Weighted composite (capped 1.0):
fragility = 0.40 * max(0, avg_corr)
+ 0.35 * suppr
+ 0.25 * min(1, tail_α / 5.0)
|> min(1.0, _) |> round(4)Rounding contract: All numeric fields round(4); fragility strictly [0, 1].
Gating contract: When inputs do not meet thresholds, corresponding fields are entirely missing (not None).
Assumptions & applicability
Assumptions: Daily frequency (sqrt(252) annualization) + symmetric correlation matrix + ad-hoc subset weights + tail log-rank approximation.
Applicable: Canvas market criticality visual indicator, educational demo, cross-asset fragility overlay input.
Not applicable: Production-grade VaR, intraday, Hill-level tail exponent estimation, ≤10 observations, monthly/weekly frequency.
Input / Output contract
{returns?, correlations?} → {_method, fragility_composite_0_1 (always), avg_pairwise_correlation?, realized_vol_annualized?, vol_suppression_index_0_1?, tail_decay_exponent_proxy?}. gated fields missing when input insufficient.
Known limitations
- Self-declared heuristic:
_methodfield explicitly states 'not production risk model' - Suppression uses whole-sample max (field name "rolling_max" is misleading — not truly rolling)
- Tail α uses naive log-rank regression (Hill MLE not implemented)
- Weights 0.40 / 0.35 / 0.25 ad-hoc (no empirical calibration)
- sqrt(252) hardcoded (systematic bias for non-daily frequency inputs)
- Correlation matrix PSD / symmetry not validated
- Gated fields missing (not None): clients must handle gracefully with
if 'field' in result: - n=1 corr → avg_pairwise_correlation field does not appear
- len(returns) ≤ 10 → vol / suppression / tail fields all missing
References
Scheffer et al. (2009) Early-warning signals for critical transitions (Nature) + Preis et al. (2012) Correlations under stress (Sci Reports) + Clauset-Shalizi-Newman (2009) Power-law distributions (SIAM Review). See frontmatter for details.
Golden Test
tests/golden/fixtures/tier3/b0_criticality/, numpy_manual cross-implementation (reference_compute.py independent numpy re-implementation + mutual assertion with b0_6_criticality at capture time). 1e-10 tolerance. 11 tests:
matches_snapshot— 6 cases (fragile / benign / returns-only / too-few / n=1 corr / no-input) byte-equaldeterminism— 5 reruns consistentavg_corr_upper_triangular_mean— 3x3 matrix known off-diagonal → 0.6 exactn_equals_one_no_avg_corr— [[1.0]] → avg_pairwise_correlation field missingreturns_too_short— len=10 → vol / suppression fields missingreturns_eleven_activates_branches— len=11 boundaryfragility_composite_bounded_0_1— extreme inputs all within [0, 1]no_inputs_returns_zero_fragility— all None → fragility = 0.0method_field_locked—_methodalways carries heuristic declarationrounding_contract— all numeric fields round(4)weight_contract— known avg_corr=0.85 → fragility = 0.34 exact (weight 0.40 locked)
Changelog
- 1.0.0 (2026-04-20) — First Active (Tier 3 batch 1.2, cross-impl numpy_manual)

