KB / framework
Leading, coincident, and lagging indicators
Last verified
The alignment surface classifies its twelve signal categories into three indicator classes — leading, coincident, and lagging. The class drives how much weight a category gets in the weighted alignment percentage, where its dot lives on the Signal Alignment card, and how loudly the operator should react when it moves.
What the classes mean
- Leading — moves before price. A leading signal deteriorating while price still looks fine usually means price is about to follow.
- Coincident — moves with price. Confirms what is happening right now; doesn’t predict but disambiguates the read.
- Lagging — confirms after the fact. A lagging signal is the slowest to flip; useful for closing the loop on a regime change, less useful for catching one early.
The three classes are not equally informative. Leading signals carry more forward-looking content per move, lagging signals carry less. The weighted alignment math encodes that directly (see below).
The twelve categories by class
Order comes from IMPLICATION_FUNCS in app/signals/implications.py — leading first, then coincident, then lagging:
Indicator class — canonical assignment per category
Eleven categories ship active by default; news_sentiment is flag-gated behind ENABLE_AI_SENTIMENT_ALIGNMENT=0 per DOCTRINE P8 — additive until the per-horizon calibration substrate at /ai-brief/calibration-by-sentiment shows ≥55% hit rate over 30d. When the flag is unset the category is absent from the alignment response and the active count is 11.
Why classification matters
Weighted alignment
compute_alignment() returns two percentages on every /api/v1/signals/alignment response: alignment_pct (count-based — every category counts once) and weighted_alignment_pct (information-content-adjusted). The weighted variant multiplies four independent factors per category:
Indicator-class multiplier (from app/signals/regime.py:_INDICATOR_CLASS_WEIGHTS)
The full weight composition is indicator_class × leg_count × regime_relevance × freshness. A two-leg leading category with a fresh intraday read and energy-shock regime relevance gets the loudest voice; a single-leg lagging category running on a stale weekly print gets the quietest. A 50% unweighted reading with 3 leading aligned and 3 lagging divergent reads around 66% weighted because the leading agreement carries more weight than the lagging dissent.
Transmission order on the Alignment card
The eleven (or twelve) dots on the Signal Alignment card are split into a leading cluster (left) and a lagging cluster (right). The exact ordering within each cluster is regime-conditional — every active regime carries a profile in ui/src/data/signal-transmission-order.json. Examples:
- RISK-OFF is credit-led — credit → breadth → gamma → dark_pool → energy → growth_expectations (with news_sentiment ahead when active).
- energy_shock override is oil-led — energy → credit → growth_expectations → breadth → dark_pool → gamma. Fires whenever
energy_regime ∈ {SHOCK, CRISIS, SHOCK_UP, RISING}. - PANIC is vol-led — volatility moves up into the leading cluster.
The midpoint divider on the card hovers a tooltip with the rationale for the active profile. Per-regime profiles are the operator’s way of saying “in this regime, this indicator typically moves first” without re-classifying the underlying signal — correlations stays a coincident category structurally; the transmission-order JSON just decides where its dot lives in the visual ordering.
When a leading dot flips
The standing operator rule: when leading indicators deteriorate while lagging indicators still look fine, the leading indicators are usually right. The whole point of separating the classes is to weight the loudest forward-looking voices over the slowest confirming ones. A bearish DIX + bearish credit + bearish gamma with bullish liquidity reading is a signal to reduce risk, not a signal to wait for liquidity to confirm.
The STRONG_DIVERGENCE severity badge (5+ divergent categories) is the loudest version of this — it fires loudest when leading + coincident categories disagree with SPY’s recent direction. Lagging-only divergence is quieter by construction.
See also
- Five-level signal scale — the dot levels every category’s implication ultimately resolves to.
- Regime overrides — how regime conditions can additionally rebalance per-category weights at the score layer.
- Hybrid analogue matcher — also reads the leading-cluster signals through its coarse-tag filter.
- Implementation:
app/signals/implications.py(IMPLICATION_FUNCSregistry),app/signals/regime.py(_INDICATOR_CLASS_WEIGHTS,_LEG_COUNT_WEIGHTS,_FRESHNESS_STATUS_FACTOR),ui/src/data/signal-transmission-order.json(per-regime ordering).