Winning vectors —
cluster-first chart pattern intelligence.
Winning vectors are recurring regions of chart-pattern embedding space where forward returns were consistently positive across both a training period (2016–2022) and a held-out test period (2023–2025). We mine them offline from 4M+ daily patterns, attach a feature signature to each, and expose them so an agent can match a live anchor to a known winning (or losing) pattern with calibrated odds.
Cohort intelligence is anchor-first: take a chart, find its analogs. Winning vectors is cluster-first: mine the embedding space ahead of time for the regions where retrieval-based forecasts have historically been most reliable, then ask of a new anchor: does it land in one of those regions, and do its current features align with the regime that made the region win?
The problem with cohort_score alone
The simplest way to use a chart-similarity engine is to compute a composite score over the cohort’s forward-return distribution and rank candidates. Higher score = take the trade.
On a 5-year, 256-week backtest over a 44-symbol mega-cap + sector-ETF universe, a score-only strategy returned roughly 34% over five years versus SPY’s 103%. The cohort statistics were correct; the problem was that a high cohort score on its own doesn’t tell you whether this particular anchor looks like the cohort members that won, or like the ones that lost. It only tells you the average outcome of the cohort.
The cluster-first reframe
A different question: across all 4M+ chart patterns we have, are there regions of embedding space where the typical forward return is consistently and meaningfully different from the universe baseline — and stable across years?
Cluster the V5 embedding space into K=300 mini-batch k-means clusters fit on the train period. For each cluster, compute the 5-day forward-return distribution separately for the train period and for the held-out test period, plus the per-year median over the train period (consistency check). Score each cluster by:
quality = sign(median) × |median| × |win_rate − 0.5| × consistency × log10(n)
with sign-agreement penalty when median direction
disagrees with win-rate direction (fat-tail-only clusters
get attenuated).Filter clusters where one symbol dominates (max_symbol_share > 30%) or sample is too small (n < 200 train members). The top 20 by signed quality are the winning vectors. The bottom 20 are the losing vectors: regimes where going long has historically been a -1% to -2% expected 5-day trade.
What a signature looks like
Each top cluster is characterized against the population baseline. For every Layer 2 feature, compute the cluster mean and the z-score of that mean against the global distribution. Features with |z| > 0.5 are the cluster’s signature.
Loser cluster #164 (one of the top ranked DON’T-trade patterns, −1.30% median train, −1.69% median test):
days_since_earnings: cluster 280 vs pop 48 (z = +3.23)
days_since_ath: cluster 1554 vs pop 351 (z = +2.62)
pct_off_ath: cluster -76% vs pop -21% (z = -2.49)
broke_50d_low: cluster 24% vs pop 6% (z = +0.78)
cross_sectional_momentum_rank: cluster 0.28 vs pop 0.50 (z = -0.77)
vix: cluster 24.9 vs pop 19.4 (z = +0.66)
rs_in_sector_rank: cluster 0.33 vs pop 0.49 (z = -0.58)
broke_20d_range_low: cluster 28% vs pop 10% (z = +0.58)The pattern is concrete and trader-readable: stocks far below their all-time high, with stale earnings catalysts, in elevated VIX regimes, sitting in the bottom quartile of sector relative strength and overall momentum, that just broke a 50-day or 20-day range low. That description doesn’t come from a list we wrote — it falls out of the data.
The matching winner clusters look the opposite. Cluster #185 (TQQQ-led, +1.16% / 60.8% train, OOS replicates) carries elevated VIX with elevated credit spreads and tight macro — a stress-reversal regime where high-beta tech historically rallied. Cluster #1 (industrial-led, +0.86% / 58.5% train, +0.62% / 61.0% test — improves OOS) carries a steepening yield curve with rising broad-market 60-day return.
The Layer 2.5 chart-event features
The macro features alone (VIX, yield curve, credit spreads) didn’t produce strong-enough signatures to beat passive on a risk-adjusted basis. Adding 13 daily-bar-derived features made the signatures concrete enough to actually trade. They’re cheap: pure window functions over the existing daily price+volume table.
- Volume trajectory: today’s volume z-score, 5-day volume acceleration, dollar-volume z — captures “volume is ramping” not just volume snapshot.
- Breakout flags: broke 50d high, broke 50d low, broke 20d range high, broke 20d range low, broke all-time high. Trailing windows exclude today so “broke 50d high” means today beat the prior 50 bars.
- Volatility events: gap z-score, range expansion z, range compression z — the coiled-spring signal.
- Cross-sectional ranks: relative strength rank within sector ETF, cross-sectional momentum rank across the entire universe on the same date.
These features show up across nearly every top winning and losing cluster signature. The ranks in particular surfaced the clearest loser pattern: anchors in the bottom quartile of both their sector and the universe, that just broke a 20-day range low, are the clearest mechanical short-side candidate in the catalog.
Risk-adjusted result on a 5-year backtest
On a 5-year, 256-week, 44-symbol universe backtest with all ablations:
Strategy Total return Sharpe Hit rate Max drawdown
SPY (passive) +103.0% +0.97 63.3% -22.4%
S5 (cohort score + sticky lessons + 5d hold)
+75.9% +0.74 55.5% -22.5%
S6 (rich brief + dynamic stops)
+24.7% +0.43 48.8% -27.8%
S8 (winning-vector match + cohort-derived stops)
+45.2% +0.90 28.1% -6.6%Total return of the winning-vector strategy lags SPY in absolute terms because it stays in cash on roughly half of trading dates when no anchor matches a known winning cluster. But it cuts max drawdown by 70% and matches passive long-only on Sharpe. Calmar ratio (annualized return divided by max drawdown) is 1.16 versus SPY’s 0.68: at 2× leverage, the strategy would beat SPY in absolute return while keeping similar drawdown risk.
The strategy isn’t supposed to beat SPY in absolute terms on a +103% bull-market universe of mega-cap names. The point is that cluster-matched, signature-aligned trades are a risk-adjusted edge: high-conviction selectivity over forced participation.
How to use it from an agent
Three tools, available both as REST API endpoints and as MCP server tools. The MCP server is published as chartlibrary-mcp on PyPI.
match_winning_vector
POST /api/v1/match_winning_vector
{"symbol": "AAPL", "date": "2024-06-21", "timeframe": "1d"}Returns the nearest cluster, classifies it as winner / loser / unranked, scores how well the anchor’s current Layer 2 features align with the cluster’s signature, and suggests cohort-percentile-derived stop / target / hold for a directional trade.
list_winning_vectors
GET /api/v1/list_winning_vectors?top_n=20&kind=bothCatalog of mined patterns: top 20 winners, top 20 losers, each with train+test medians, win rates, p25/p75, top symbol, sample size.
get_cluster_signature
GET /api/v1/get_cluster_signature/164Full rule card for a single cluster: numeric features with |z| > 0.5 vs population, train/test outcome distribution, categorical mode (sector / regime / etc.), top symbols.
Honest caveats
- Bull-market window. The 2021–2025 backtest period was a +103% SPY bull. A defensive long-only strategy in that regime is geometrically constrained from beating passive long-only on absolute return. Risk-adjusted metrics (Sharpe, Calmar) are a fairer comparison.
- Survivorship in the universe. The 44-symbol test universe is mega-cap names + sector ETFs that existed throughout the period. Strategy-vs-strategy comparison on the same universe is still valid, but the absolute-return numbers wouldn’t survive a wider universe with more failed companies.
- Single-seed determinism. All LLM-driven strategy variants were run with temperature=0 to remove Haiku non-determinism. Bootstrapping over multiple random universes / seeds would tighten the confidence intervals.
- Daily granularity. Walk-forward simulation uses daily OHLC. Same-bar collisions resolve as “stop fires first” (conservative). True intraday data would refine stop-vs-target attribution but is unlikely to flip the sign of the result.
Frequently asked questions
- Is the winning-vector catalog static or refreshed?
- Refreshed. The catalog is regenerated when the underlying mining run is rerun. The API loads the most recent winning_vectors_<run_id>.json + matching centroids artifact lazily on first call after restart, so updating the artifact + restarting the API picks up new mining results without code changes.
- Why K=300 clusters?
- Empirical balance. K=30 was too coarse to find tight signatures; K=500+ pushes per-cluster sample sizes below the threshold where forward-return statistics are stable across years. K=300 leaves ~14K members per cluster on average, which keeps yearly-median variance low without smearing distinct regimes together.
- What's the next planned extension?
- Allow short positions on loser-cluster matches. Cluster #164 has a -1.30% median 5-day return that's stable in OOS; the symmetric short trade adds expected positive return without changing drawdown control. Beyond that: better features (volume profile from minute bars, options flow, earnings-call sentiment), broader universes, and a per-trade thesis-invalidation check that exits when the live signature drifts during the hold.
Run a cohort_analyze call.
Free Sandbox tier — 200 calls/day, no authentication. MCP install for Claude or Cursor takes 30 seconds.