Scan the whole market. Get back a ranked shortlist.
One POST /v1/scan call scans US stocks, ETFs and crypto for the tickers currently in a given regime or printing a chart/candlestick pattern — ranked by the measured base rate, and every rate comes with the pattern-free baseline for that market, timeframe and horizon, plus a cluster-robust 95% CI. Your agent stops analyzing one ticker at a time, and it reads each number against the right reference instead of a made-up one.
POST /v1/scan$0.02REST + MCPx402 + Stripe
TL;DR — The screener is patternfetch's flagship discovery endpoint. Pass optional filters — assetClass, regime, pattern, tf, minLift, minBaseRate, limit — and POST /v1/scan returns a ranked shortlist of tickers, ordered by the measured base rate and shipped with the pattern-free baseline for the same market, timeframe and horizon plus a cluster-robust 95% CI. Same discipline as the brief: a rate is only meaningful against its baseline, and we publish both. Also available as the patternfetch_scan MCP tool.
Lookup vs. discovery
Most market-data APIs — patternfetch's own /v1/brief included — are lookup: you already know the ticker, and you ask for its current state. That's the right tool once you have a candidate. But an agent screening the market has the opposite problem: it doesn't know which tickers to look at yet. Calling /v1/brief on hundreds of symbols to find the handful that matter is slow, token-heavy and expensive.
"What's the state of AAPL on the 1d?" → one brief. To find candidates you'd loop /v1/brief over the whole universe yourself, then sort — many calls, many tokens, your own ranking logic.
"Which US stocks and crypto are in an uptrend printing a double_bottom, best base rate first?" → one /v1/scan call returns the ranked shortlist. Then call /v1/brief only on the names that survived.
That's the whole pitch: the scanner turns lookup into discovery, so your model narrows the universe in one call instead of being handed one ticker at a time — and it ranks by measured numbers, each next to its baseline, not by a confident-sounding label.
How it works
- A curated universe. An evidence-backed set of liquid US large-caps, core & sector ETFs, and major crypto pairs is scanned so every result is a name with enough history to measure — and enough history to compute its pattern-free baseline.
- Precomputed, not live. Scanning the whole universe live (a fetch + full analysis per ticker) would be slow and hammer upstream sources. Instead the universe is scanned offline on a schedule and each ticker's current-signal row is stored, so a scan is served from memory — fast and cheap.
- Filter. Your optional filters narrow the universe by asset class, regime, pattern, timeframe and a minimum base rate.
- Rank by the measured base rate. Survivors are ordered by the top pattern's backtested directional base rate (with its cluster-robust 95% CI, sample size and the pattern-free baseline for the same market, timeframe and horizon) — the same evidence the brief attaches to a pattern — then by geometric confidence, then timeframe, then symbol.
- Act on the shortlist. Take the ranked rows and call /v1/brief on the top names for the full picture before your agent does anything.
The filters
Every field is optional; an absent field puts no constraint on that axis. A filter-less POST /v1/scan returns the top of the universe, ranked.
| Filter | Type | Meaning |
|---|---|---|
| assetClass | "stock" | "crypto" | "all" | Restrict to US stocks/ETFs, crypto pairs, or all. Default all. |
| regime | "up" | "down" | "range" | Only tickers whose current regime trend matches — uptrend, downtrend, or sideways/chop. |
| pattern | string | Require the ticker's top pattern to be this one: double_bottom, double_top, head_and_shoulders, bullish_engulfing, bearish_engulfing, hammer. |
| tf | string | One of 1m 5m 15m 30m 1h 4h 1d 1w. The universe is currently precomputed at 1d. |
| minLift | −1..1 | The drift-free filter — prefer this one. Drop tickers whose top pattern doesn't beat its own pattern-free baseline by at least this many rate points. 0.02 = 2pp of measured lift; 0 = at or above baseline. Rows with no baseline in the evidence table are always excluded — absence of a lift is not a lift of 0. |
| minBaseRate | 0..1 | Drop tickers whose top-pattern backtested base rate is below this floor. Careful: a raw base rate isn't comparable across bullish and bearish rows. Kept for existing consumers — see minLift. |
| limit | int 1..500 | Max rows returned. Default 50. |
Which floor should you screen on? minBaseRate asks how often a pattern resolved in its direction. minLift asks how much of that the pattern was responsible for. On the daily US stock table a bullish pattern starts about 16pp ahead of a bearish one before either carries any information, so a base-rate floor is mostly a drift filter in a signal's clothing. minLift is the floor that survives that objection — and it returns very little, which is the honest result rather than a broken filter.
Example — request & response
Ask for US stocks and crypto in an uptrend with at least a 55% base rate, top 20:
curl -X POST https://patternfetch.com/v1/scan \
-H "Authorization: Bearer pf_…" \
-H "Content-Type: application/json" \
-d '{ "assetClass": "all",
"regime": "up",
"minBaseRate": 0.55,
"limit": 20 }'
{
"asOf": "2026-07-05",
"tfs": ["1d"],
"universe": 137,
"count": 2,
"results": [
{ "sym":"AAPL","tf":"1d","assetClass":"stock",
"regime":"up","pattern":"double_bottom",
"baseRate":0.58,"ci95":0.03,"n":300,
"scope":"US stocks & ETFs","confidence":0.72,
"baseline":0.5784,"lift":0.0016,"liftCi95":0.026,
"liftReading":"indistinguishable-from-baseline" },
{ "sym":"BTC/USDT","tf":"1d","assetClass":"crypto",
"regime":"up","pattern":"bullish_engulfing",
"baseRate":0.56,"ci95":0.04,"n":180,
"scope":"major crypto pairs","confidence":0.69,
"baseline":0.5412,"lift":0.0188,"liftCi95":0.041,
"liftReading":"indistinguishable-from-baseline" }
],
"note":"Precomputed current-state scan ranked by
impersonal historical base rate. Discovery,
not a prediction or a buy/sell signal.",
"disclaimer":"… informational only, not advice …"
}
Each row carries sym, tf, assetClass, regime, pattern, baseRate (the ranking key), ci95, n (sample size), scope (the corpus the rate was measured over) and geometric confidence — plus the drift-free block baseline, lift, liftCi95 and liftReading. The envelope's universe and asOf tell you how many tickers were scanned and when. See it live →
The drift-free screen
Note what the two rows above actually say: both clear a 55% base rate, and neither is distinguishable from its own baseline. That is the failure mode a base-rate floor cannot see. Screen on minLift instead and the filter asks the harder question:
curl -X POST https://patternfetch.com/v1/scan \
-H "Authorization: Bearer pf_…" \
-H "Content-Type: application/json" \
-d '{ "assetClass": "all",
"regime": "up",
"minLift": 0.02,
"limit": 20 }'
{
"asOf": "2026-07-05",
"tfs": ["1d"],
"universe": 137,
"count": 0,
"results": [],
"note":"Precomputed current-state scan ranked by
impersonal historical base rate. Discovery,
not a prediction or a buy/sell signal.",
"disclaimer":"… informational only, not advice …"
}
An empty shortlist is a result, not a broken filter. Across the 105 pattern/market/timeframe buckets we backtested, three clear an uncorrected interval — fewer than the ~5.3 that chance alone would produce, and on US stocks it is 0 of 60. minLift is the parameter that lets your agent act on that instead of on drift. Read the full study →
How results are ranked
The whole feature is "ranked by the measured base rate", so ordering is deterministic and evidence-first:
| Key | Direction | Why |
|---|---|---|
| baseRate | desc | How often that exact pattern + timeframe + confidence band historically resolved in its own direction, with no lookahead. Read it against the scope's pattern-free baseline, returned with every row. |
| confidence | desc | Geometric fit score (0..1) — breaks ties between equal base rates. |
| tf then sym | asc | Stable, attributable ordering for same-strength rows. |
Tickers whose top pattern has no sufficiently-powered evidence bucket carry baseRate: null and rank last — the scanner never invents a number it can't back with history.
One caveat the ranking itself can't fix: base rates are not comparable across asset classes. US stocks and ETFs drift upward, so a bullish daily bucket starts from a 57.8% pattern-free baseline over 10 bars, while the same bucket in crypto starts from about 49.3%. A 56% crypto row and a 56% stock row are therefore not the same finding. Compare each row to the baseline for its own scope, which is why the baseline travels with the row.
A confident-looking chart pattern is not the same as a pattern that carries information. Every other screener ranks by how cleanly a shape matches, and published pattern statistics usually quote a hit rate with nothing to compare it against — the same bearish engulfing is quoted at 57%, 75.76% and 79% by three widely-cited sources, none of which publishes a baseline or an interval. patternfetch measures instead. Every base rate ships with the pattern-free baseline for the same market, timeframe and horizon: over 10 bars on the daily, US stocks and ETFs close up 57.8% of the time with no pattern involved, crypto about 49.3%. Measured that way, three of the 105 buckets we tested clear an uncorrected interval — fewer than the ~5.3 chance alone would produce, and none of the three survives correction; on US stocks and ETFs it is 0 of 60 — daily bullish engulfing is +0.4pp (±2.6pp, n=11,535), hammer −0.1pp (±2.7pp, n=5,600). That is the point: numbers your model can rank on without inventing significance that isn't there.
Over MCP
The screener is also the patternfetch_scan tool on the patternfetch MCP server — same optional filters, same ranked output. Point any MCP client (Claude, Cursor, Smithery, an OpenAI agent over a bridge) at https://patternfetch.com/mcp; tool discovery is free and a call is billed like the REST route.
# one line — OAuth mints a free-tier key, nothing to paste
claude mcp add --transport http patternfetch https://patternfetch.com/mcp
Then your agent can call patternfetch_scan with, e.g., {"assetClass":"crypto","pattern":"double_top","limit":10} and reason over the ranked shortlist. See the MCP docs.
① A scan is $0.02 per call — the same pay-per-call model as every endpoint. ② No-signup demo & free key: the wider API has a keyless demo and a free key with a $3.00 starter credit, no card. ③ Pay as you go: settle with Stripe or with x402 (USDC on Base, no account) so an agent can fund itself. ④ Credits never expire. Full pricing →