This page publishes the mechanical contract used by public index and asset objective surfaces: the windows, the fallbacks, the transforms, the Condition Percentile display, 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 rank-based reading.
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, rank-based, min-max, or raw space. The public primary read is the Condition Percentile derived from that normalized measurement.
Apply the index's threshold family to produce deterministic condition labels: strong tailwind, tailwind, neutral, headwind, or strong headwind.
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) rank_percentile = 100 * rank_pos / non_null_count
Rank-based indexes use the same primary 252-observation window and the same 126 / 63 / 20 recent-output fallback. The rank convention is inclusive.
Rank-based 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, condition reads discount the affected index weight: DEGRADED = 60% effective weight, WITHHELD = 30%.
If less than 60% of an asset exposure basket is covered, the objective asset condition 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% |
primary_value_field = "condition_percentile" primary_value_label = "Condition Percentile" primary_value = condition_percentile condition_band = supportive | normal | stressed secondary_value_fields = ["z_score", "level"] withheld_state = visible_when_inputs_missing methodology_version = published_contract_version
Public site chrome, methodology needle, index detail, asset detail, and API examples must lead with Condition Percentile when a measured value exists. Z-score and level remain secondary context.
When inputs are missing, the UI renders an explicit building or withheld state with coverage context. It never fills a missing read with a fake midpoint.
The display bands are fixed product-contract breakpoints, not claimed optimal investment thresholds. A separate proof/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.