What separates winners from losers within shape-similar setups.
Shape similarity gets you a cohort of historical analogs. It doesn’t tell you which features inside that cohort predicted who won and who lost. Cohort intelligence is the analytical layer on top of retrieval that surfaces conditional outcome distributions, per-feature attribution, regime stratification, and a narrative-change score for news-driven setups. For the canonical definition see what is cohort intelligence.
Senior fundamental and quant analysts evaluate setups by asking conditional questions: given this shape, what does this regime do? given this news, is the price reaction consistent with absorption or with a real narrative shift? They typically answer those questions one idea at a time with custom code, internal databases, and analyst memory.
This API turns those conditionals into structured output: outcome distribution + per-feature attribution + regime stratification + risk profile + narrative-change score, in a single call. The same workflow a discretionary PM runs by hand — programmable, callable from an agent, comparable across ideas.
curl -X POST \
https://chartlibrary.io/api/v1/cohort_analyze \
-H 'Content-Type: application/json' \
-d '{
"anchor": {
"symbol": "NVDA",
"date": "2024-08-05",
"timeframe":"1h"
},
"cohort_size": 300,
"filters": { "vol_regime": ["mid","high"] }
}'{
"anchor": {"symbol":"NVDA","date":"2024-08-05","timeframe":"1h"},
"cohort_size_actual": 300,
"outcome_distribution": {
"5d": { "n": 287, "median": -1.24, "win_rate": 0.42, "p10": -18.2, "p90": 14.6 }
},
"feature_importance": {
"5d": [
{ "feature": "vol_regime=low", "direction": "negative", "importance": 0.93 },
{ "feature": "macro_state=bullish", "direction": "positive", "importance": 0.96 },
{ "feature": "sign_alignment", "direction": "negative", "importance": 0.17 }
]
},
"regime_stratification": {
"5d": {
"high": { "n": 77, "win_rate": 0.70, "mean_return": 2.73 },
"mid": { "n": 112, "win_rate": 0.48, "mean_return": -0.59 },
"low": { "n": 104, "win_rate": 0.26, "mean_return": -4.45 }
}
},
"narrative_change_score": 0.29,
"cohort_tightness_score": 0.61
}Try it interactively at /intelligence. MCP tool available via chartlibrary-mcp on PyPI.
How this differs from the v1 cohort primitive
Both endpoints return a cohort of shape-similar historical anchors. The difference is what they return on top of that.
| Output | /v1/cohort | /v1/cohort_analyze |
|---|---|---|
| Outcome distribution + calibrated bands | ✓ | ✓ |
| Survivorship envelope | ✓ | ✓ |
| Per-feature importance (logistic) | — | ✓ |
| Regime stratification | — | ✓ |
| Risk profile (drawdown / runup) | — | ✓ |
| Narrative-change score | — | ✓ |
| Filter on multi-signal metadata | regime / sector / event | 13 features incl. news |
| Median latency (lightweight) | ~200 ms | ~300 ms |
| Median latency (full analysis) | n/a | 1–6 s (cohort + features) |
Use /v1/cohort when you want a fast distribution. Use /v1/cohort_analyze when the conditional question — “which features matter inside this cohort?” — is the question.
1. Why shape similarity isn’t the whole answer
A retrieval-only cohort is a shape-conditioned distribution. The same shape can play out very differently depending on the volatility regime, macro state, sector relative strength, calendar context, and news at the anchor date. Stratification on a single anchor surfaces this:
| Vol regime at anchor | n | Win rate | Mean return |
|---|---|---|---|
| High | 77 | 70% | +2.73% |
| Mid | 112 | 48% | −0.59% |
| Low | 104 | 26% | −4.45% |
Same shape. 44 percentage points of win-rate spread between the high-vol and low-vol slices. Without stratification this information sits inside the cohort, mixed into a single average. With stratification it’s an actionable conditional.
2. The four outputs
One call to POST /api/v1/cohort_analyze returns the cohort distribution plus four analytical layers on top.
Per-horizon descriptive statistics on the cohort’s forward returns: n, mean, median, percentile band (p10/p25/p75/p90), win rate, skew. Also includes trimmed_mean (winsorized at p5/p95) and a mean_skew_warning bool that fires when |mean − median| > 1×std — the honest headline number when leveraged-ETF members are pulling the mean off the typical outcome. Same calibration story as the base cohort primitive — raw and conformal bands both available.
A logistic regression of metadata features → win/loss fit on the cohort itself. Returns sorted coefficients with direction (positive / negative), Wald CIs, and normalized magnitude. Shows which features separated winners from losers inside this specific shape, not in general.
Outcome distribution sliced by a categorical feature (default: volatility regime). Per-regime n, win rate, mean and median return. Tells you whether the same pattern is regime-dependent or regime-agnostic.
Drawdown and runup percentiles per horizon, plus a favorable-excursion ratio. Path-stat-aware version uses bar-level MAE/MFE; the default fast path approximates from terminal returns.
Every cohort_analyze call returns a single composite cohort_score ∈ [0, 1] — the headline number on /app and the metric that /track-record/intelligence validates. It multiplies four signals together, each clamped to [0, 1]:
cohort_score =
delta_from_base (cohort median 5d return vs base rate)
× tightness (1 − cohort std / 10pp clamped)
× cohort_size (saturating curve at n=300)
× feature_concentration (top-5 feature importance share)When a symbol also has live news flow, combined_conviction = min(1.0, cohort_score + 0.4 × narrative_pulse). Pulse is the intra-day narrative anomaly score from News v2. Combined conviction is shipped on /app and /discover but not yet independently validated to beat cohort_score alone — the honesty layer at /track-record/intelligence will resolve this once the news-day sample passes 300+ observations with realized returns.
3. The narrative-change vs priced-in distinction
On news days, the question that matters isn’t did news happen? It’s did the news materially change the narrative, or is it already priced in? Cohort intelligence answers this via a composite of six observed signals computed from deduped article counts, transformer-based sentiment scoring, and aligned price reaction:
- — Frequency anomaly. Today’s deduped news count vs trailing 30-day average. Sudden cluster after quiet = potential narrative break.
- — Tone shift. Sentiment today vs trailing 30-day average. Sharp reversals are narrative changes; drift is absorption.
- — Sentiment-price alignment. The cleanest signal: positive news met by flat or down price → already priced in (sell-the-news). Negative news met by up price → oversold bounce. Misaligned days are where the edge lives.
- — Reaction magnitude vs vol. A 1% move on news for a 30-vol stock is noise. A 5% move on news for a 15-vol stock is signal.
- — Persistence. Five-day return divided by one-day return on the news day. Narrative changes hold; priced-in moves fade.
- — Sentiment-price correlation history. Rolling 30-day correlation between daily returns and daily sentiment. Low historical correlation → today’s news might suddenly matter.
The composite lives in [0, 1]. Initial observed ranges, subject to refit once the meta-learning layer ships:
- —
> 0.5· right tail · likely meaningful narrative event - —
0.3 – 0.5· ambiguous - —
< 0.3· likely priced-in or non-event
On a representative news-day cohort (NVDA · 2024-08-05 · K=300), the sentiment-price misalignment feature carried a negative coefficient in the within-cohort regression — i.e. analogs where sign disagreed outperformed 5d. One anchor; consistent with the priced-in vs narrative-change distinction the score is built around. Population-scale validation requires the meta-learning layer.
4. Honest-negatives & coverage gaps
- News features are NULL pre-2024. News article ingestion starts 2024-01-01. Cohorts dominated by older analogs will see news features dropped from the regression by a
> 50%missing-data filter. The corollary: every passing month materially expands the news-aware cohort surface, and the system’s value compounds with time as more anchors carry full Layer 2 coverage. - Composite weights are starting points. The narrative-change-score weights are educated guesses pending a meta-learning refit from realized outcomes. Treat threshold calibrations as observation-only until the refit ships.
- Earnings consensus is not yet wired. The seventh signal in the published spec is earnings surprise vs consensus — not currently populated. Earnings-window queries fall back to the other six signals.
- Weekend news is dropped. Articles tagged on non-trading days are not currently rolled forward to Monday’s row. A Sunday catalyst is invisible until ingestion catches up on Monday.
- Latency. Lightweight calls (no feature importance, default cohort_size=300) typically 0.5–1.0s. Full analysis with feature importance + regime stratification + risk profile typically 1.5–5.5s depending on cohort_size and database warmth. Acceptable for analyst-paced workflows; not yet at high-frequency thresholds.
5. What this page deliberately will not tell you
- — The specific sentiment model architecture (family, parameter count, training recipe).
- — The dimensionality of news article embeddings and the dedup similarity threshold.
- — The exact composite weights of the narrative-change score (subject to refit).
- — The full list of metadata features exposed to feature_importance.
- — The retrieval architecture this layer sits on top of (covered in methodology).