This page publishes the mechanical contract used by the public index and score surfaces: the windows, the fallbacks, the transforms, and the exact places where MarketSchema withholds or discounts degraded data.
Apply declared component transforms such as raw, pct_change, log_return, yield_change, macro_impulse, zscore, invert, clip, moving average, or percentile rank.
Combine transformed component series using the index definition: usually weighted_mean, with equal_weight, sum, median, geometric_mean, or ratio where declared.
Convert the aggregate into z-score, percentile, min-max, or raw space. The normalized value is what drives public signal labels.
Apply the index's threshold family to produce strong positive, positive, neutral, negative, or strong negative.
window = last 252 observations min_obs = ceil(window * 0.30) mean = average(non_null(window)) std = sample_std(non_null(window)) z = (value_t - mean) / std index_z = clip(z, -3, +3)
Component-level z-score transforms reject non-finite output and extreme values beyond +/-10 sigma. Final index-level z-score normalization clips to +/-3 sigma after the aggregate is built.
If the latest five normalized observations are empty, the engine retries shorter windows in this order: 126, 63, then 20 observations. That fallback is a data availability rule, not a new formula.
window = last 252 observations rank_pos = count(values_in_window <= value_t) percentile = 100 * rank_pos / non_null_count
Percentile indexes use the same primary 252-observation window and the same 126 / 63 / 20 recent-output fallback. Percentile ranks use an inclusive rank convention.
Percentile families have their own threshold registry so skewed credit, housing, and crypto distributions are not forced through normal z-score cutoffs.
weighted_mean_t = sum(weight_i * transformed_i_t for live components) / sum(weight_i for live components)
If a component is missing on a date, the aggregate uses the remaining available weight. If publish quality is degraded downstream, asset scoring discounts the affected index weight: DEGRADED = 60% effective weight, WITHHELD = 30%.
If less than 60% of an asset exposure basket is covered, the asset score is withheld rather than filled with a fake midpoint.
| Family | Strong + | Positive | Neutral low | Negative |
|---|---|---|---|---|
| canonical_stress | +2.00 | +0.75 | -0.50 | -1.50 |
| macro | +1.50 | +0.50 | -0.50 | -1.50 |
| macro_surprise | +1.00 | +0.30 | -0.30 | -1.00 |
| credit_stress | +2.00 | +0.75 | -0.50 | -1.50 |
| housing | +1.25 | +0.40 | -0.40 | -1.25 |
| fx | +1.25 | +0.40 | -0.40 | -1.25 |
| em | +1.75 | +0.60 | -0.60 | -1.75 |
| commodity | +2.00 | +0.75 | -0.75 | -2.00 |
| crypto | +2.50 | +1.00 | -1.00 | -2.50 |
| equity_rotation | +1.50 | +0.50 | -0.50 | -1.50 |
| equity_thematic | +1.75 | +0.60 | -0.60 | -1.75 |
| Family | Strong + | Positive | Neutral low | Negative |
|---|---|---|---|---|
| credit_stress | 85% | 65% | 35% | 15% |
| housing | 80% | 60% | 40% | 20% |
| crypto | 90% | 70% | 30% | 10% |
| equity_thematic | 80% | 60% | 40% | 20% |
macro_signal = 50 + power_stretch(weighted_index_signal) * 50 narrative_component = 50 + capped_overlay / cap * 50 schema_score = active_macro_weight * macro_signal + active_entry_weight * entry_value + active_narrative_weight * narrative_component
The shipped schema-v3 blend is 60% macro signal, 20% entry value, and 20% narrative alignment when all components are available. Narrative deviation from neutral is capped at +/-15 final score points.
If entry or narrative evidence is unavailable, that sleeve stays out of the computation and its weight flows back to macro_signal. Confidence travels beside the score; it does not pull the public number toward 50.
conditions_score = /api/conditions/snapshot.composite_score conditions_label = /api/conditions/snapshot.conditions_label risk_score = 100 - conditions_score market_read = MarketRiskObject.risk_state + risk_score
Public site chrome, footer, methodology needle, pricing demo, and index directory must read the conditions snapshot for the headline market state. Pulse text is not allowed to overwrite this contract.
Narrative rows can be mapped while not admitted. In that case the narrative sleeve is neutral, and the UI must say "mapped" or "dormant" instead of implying an active signal.
The display bands are fixed product-contract breakpoints, not claimed optimal investment thresholds. A separate scorecard/backtest page is responsible for proving realized behavior by band. Until a band has that evidence, MarketSchema should describe it as a deterministic classification, not as statistical alpha.