Free key · 10 calls/day Brooks paid · $9.90/mo
What just happened — and how often did it work out?
Price-action traders name recurring events: a breakout from a tight range, a climactic spike, price pressing the edge of a range. This endpoint detects those events in the window trading right now and attaches to each one the outcome rate we measured for it — pre-registered, on sixteen years of S&P 500 futures data — instead of the number the classroom quotes.
The name credits the tradition the definitions come from: the price-action vocabulary Al
Brooks teaches. The output is descriptive — an events array with measured
historical frequencies and sample sizes attached, not a verdict and not a signal. Where the
tradition’s number failed our measurement, the response says so.
Two further blocks come with every read. day_type is the calibrated five-class
day-type distribution for the session in progress — the read this endpoint was originally
built around — served in the day session, where a session exists to read.
shape is plain arithmetic over the bars already printed: where price closed
inside its own range, how much of the travel was one-way, the deepest pullback. One estimates
an unfinished day; the other measures a finished stretch. They are kept apart on purpose, and
shape carries no accuracy figure because nothing is being predicted.
Get free API key View a real response
Live around the clock — including the gap nobody covers
A day-type read needs a session; an event read only needs recent bars. That difference is why
this endpoint has three windows and always has something live to say on 24-hour instruments:
the US day session (rth), the Asian session (asia, 09:00–16:00
Beijing), and the stretch in between — gap, 16:00–21:30 Beijing, after the
Asian close and before the US open. Each window’s rates were measured separately: the
same breakout definition fails 62.6% within 10 bars in the US session and 62.8% in the gap
window, so the structure holds there too, and the response always pairs an event with the
rates for the window it fired in. Omit ?window and the read follows whichever
window has the freshest bars.
The same asymmetry decides which of the other two blocks you get. In the gap and Asian
windows day_type returns available: false with the reason attached
— the model reads a session from its open, and there is no open to read from — while
shape still measures what those hours printed. In the day session you get both.
The five event types
| Event | What it is, and what comes attached |
|---|---|
range_breakout | The day’s first close outside a tight trading range. Carries the measured failure rates and a calibrated per-event estimate of whether this one closes back inside. |
breakout_follow_through | The bar after a breakout closes beyond the breakout bar’s extreme. Carries the measured rate at which the projected measured-move target was touched. |
range_position | A close in the top or bottom third of an established range. Carries the measured rate of moving one third of the range height each way — including the half of the claim that did not confirm. |
long_range_breakout | A breakout from a range that has held for 20+ bars. The tradition says the direction is 50/50; the measured split is skewed upward — reported as measured. |
climactic_spike | Two or more consecutive strong bars closing near their extremes with little overlap. Carries the measured rate at which the spike’s projected target was touched. |
Each type reports at most its first occurrence per window per day — that is the definition the reference rates were measured under, so the live detection and the published numbers describe the same population.
The endpoint
Base URL https://api.quantdata.uk. It takes one header,
X-API-Key: qd_.... No SDK,
no OAuth, no session state. One subscription covers every endpoint on the site — the
Weis Wave API and the options-positioning pair,
/v1/maxpain and /v1/gamma, included. Full parameter and error tables
live in the API reference. There is also a
POST /v1/brooks/backtest that runs the identical detectors over bars you supply,
so you can check the calibration on your own instrument yourself.
GET /v1/brooks/{symbol} — events in the live window
Returns the events detected in the freshest window, the quote the read was computed from, and
the volatility base every definition is scaled by. This example is a gap-window read — the
hours when no day-type read can exist at all, which is exactly what its
day_type block says.
$ curl -H "X-API-Key: qd_9f3c..." \
https://api.quantdata.uk/v1/brooks/ES=F
{
"symbol": "ES=F",
"window": "gap",
"window_is_live": true,
"session": "2026-08-06",
"bars": 41,
"quote": { "open": 6362.25, "high": 6371.5, "low": 6355.0,
"last": 6368.75, "prev_close": 6360.5, "change_pct": 0.13 },
"source": "leandata",
"volatility_base": { "avg_daily_range_5d": 62.75,
"definition": "mean high-low range of the last 5 completed US regular sessions" },
"events": [
{
"type": "range_breakout",
"direction": "up",
"at": "2026-08-06T18:05:00+08:00",
"bars_since": 6,
"breakout_level": 6366.0,
"range": { "low": 6358.25, "high": 6366.0 },
"outcome_so_far": { "failed_within_10_bars": null, "resolved": false,
"bars_observed": 6 },
"conditional_estimate": {
"p_fail_within_10_bars": 0.58,
"meaning": "Of past breakouts whose own rolling context looked like this one,
this share closed back through the breakout level within 10 bars."
},
"reference": { "failure_rate_pct": {
"within_5_bars": { "rate_pct": 50.4, "n": 3918 },
"within_10_bars": { "rate_pct": 62.8, "n": 3916 },
"within_20_bars": { "rate_pct": 72.4, "n": 3882 } } }
}
],
"day_type": {
"available": false,
"why": "No day-type model has been trained or validated for the gap window.
The day session has its own model (mode=day_session) and the Asian
window has its own (mode=asia_session); the gap window is covered
by the shape block and the event reads instead."
},
"shape": {
"bars_measured": 41,
"net_move_pct_of_range": 61.2,
"close_position_in_range": 0.83,
"one_way_share": 0.58,
"deepest_pullback_pct_of_range": 24.5,
"high_made_at": 0.92,
"low_made_at": 0.04,
"direction_changes": 3,
"range_tightness": 0.74,
"not_a_forecast": "Measured description of bars that have already printed.
It carries no accuracy figure because nothing is being
predicted, and it is not the day-type classification."
},
"disclaimer": "Educational analytics, not investment advice."
}
Read that response as: an upward breakout printed six bars ago and has not yet resolved;
historically 62.8% of gap-window breakouts closed back through the level within 10 bars
(n=3,916), and this particular one — given its own range tightness, breakout strength and
context — carries a calibrated 58% estimate. The shape block adds that the
stretch finished near the top of its own range (0.83) with a little over half the travel
in one direction. Descriptive, dated, sample-sized.
The scoreboard
The conditional estimate was confirmed under a pre-registered protocol whose only judged cell was NQ futures 2023+ — an instrument and a period the model had never seen.
Calibration is the part people skip and the part that matters most for an agent. An uncalibrated 60% is a vibe. A calibrated 60% is a number you can put into an expected-value calculation. The pre-registration documents and the full result tables are on the methodology page.
The famous claims, fact-checked
Price-action classrooms quote “80%” and “90%” constantly. We tested the claims one at a time against 3,946 S&P 500 E-mini trading days of 5-minute data, 2010 to 2026. This table is free to read here and on the methodology page, which carries all the verdicts. No key, no account.
| Claim | Classroom says | Measured | Sample |
|---|---|---|---|
| 90 minutes after the open, one side’s daily extreme is already in place | 90% | 81.2% | 3,946 days |
| On a bull day, the low of the day forms in the first third of the session | 90% | 83.3% | 3,946 days |
| After an opening-range breakout, the opposite extreme holds | 90% | 83.5% | 3,578 days |
| Trading-range breakouts fail (the famous “80% rule”) | 80% | 52.1% / 62.6% / 70.6% within 5 / 10 / 20 bars, first breakout per day | ~3,900 events |
| A breakout from a long-lived range goes either way 50/50 | 50/50 | 57.8% upward skewed in every window — claim reversed | 2,745 events |
Meta-verdict: the directions are mostly correct, the numbers are systematically inflated by 7 to 10 percentage points — and two claims failed outright. The “80% rule” never reaches 80% under any definition of range tightness we tried. The 50/50 long-range breakout claim reversed: the split is skewed upward in every window we measured, consistent with the index’s long upward drift. And the sell-zone half of the range-position claim did not confirm in the US session or the gap window. The practical rule stands: trust the direction, discount the number — and check which claims did not survive at all.
Get free API key Read the API reference
Honest limits
Publishing where the numbers fail is not modesty, it is the only way the successes mean anything. Three limits matter before you buy.
Rates were measured on ES
Every reference rate comes from S&P 500 E-mini futures. The conditional model was
additionally validated zero-shot on NQ and QQQ. On any other symbol — single stocks,
Hong Kong, A-shares, crypto, FX — the response carries a coverage_note and
the numbers are context about ES, not claims about that market.
Half of one claim is dead
The range-position claim is taught symmetrically: sell the top third, buy the bottom third, 60% each way. Measured, only the bottom-third half carries support (55.6% in the Asian window, its best), while the top-third half is indistinguishable from or below 50% in the US session and the gap. The response reports the asymmetry rather than averaging it away.
It never says buy or sell
There is no signal endpoint, no entry, no stop, no target. The output is a list of events with historical frequencies and sample sizes. If your agent turns that into a trade, that is your agent’s decision and your risk — and we would rather you use it as a context layer than a trigger.
Who this is for
A good fit
- Students of price action who want an answer key: spot the event on your own chart, then call the API and compare — including how often it actually resolves the way the classroom says.
- People building trading agents who need structural context in one line of code, with estimates that are actually calibrated, at any hour the market trades.
- Researchers and sceptics who want measured base rates instead of course slides — including the claims that failed.
A bad fit
- Anyone looking for entries, exits or alerts. This is a context layer; there is no signal in the box.
- High-frequency work. The unit of analysis is a 5-minute bar, not a tick.
- Anyone who needs the number to be big. Our honest numbers are breakout failure rates in the 50–72% band and an AUC of 0.646 — real, measured, and not huge. If that is disappointing, the products promising 90% are one search away, and they are lying.
The day-type read
This endpoint began as a five-class day-type probability read, and that read is still here —
now one block of the response rather than the whole of it. It answers a different question
from the events around it: not what just happened, but which of five scripts the session in
progress is on course to finish as. Because that question needs a session, the block is
served in the day session and reports available: false with its reason
elsewhere.
$ curl -H "X-API-Key: qd_9f3c..." \
"https://api.quantdata.uk/v1/brooks/ES=F?window=rth"
{
"day_type": {
"available": true,
"bars_read": 54,
"probs": { "TrendUp": 0.34, "Reversal": 0.22, "TrendingRange": 0.21,
"Range": 0.2, "TrendDown": 0.03 },
"meaning": "Calibrated probability distribution over the five day types this
session could resolve into. Report the distribution, not just the
top class — the second script is often very much alive.",
"accuracy": "Measured on held-out S&P 500 E-mini years the model never trained
on: at 18 bars (90 minutes in) top-1 53.5% and top-2 68.6%; over a
complete session 66% and 80%. The majority class covers 37% of
days — quote that baseline alongside any accuracy figure."
}
} Quote the 37% baseline whenever you quote the 66%: the gap between them is the whole claim, and 66% on its own reads as far more than it is. Calibration error is under 10%, so a stated 70% corresponds to roughly 70% of such sessions resolving that way. The same read powers the published day-type × volume-event gating study (56.5% vs 50.8% on ES, replicated zero-shot on NQ and QQQ) behind the QQQ strategy case study. The full record is on the methodology page.
The shape block — measurement, not prediction
shape exists because the honest answer during the eleven hours without a session
is not silence, and it is not a day type either. It is arithmetic over the last stretch of
bars: close_position_in_range (1.0 finished at the top of its own range, 0.0 at
the bottom), one_way_share (near 1.0 the move was close to a straight line, near
0 it retraced most of what it covered), deepest_pullback_pct_of_range,
high_made_at and low_made_at (0 = start of the stretch, 1 = the
latest bar), direction_changes and range_tightness.
Every one of those is recomputable from the same bars, which is the only promise it makes. It has no accuracy figure, and it is not entitled to borrow the day-type model’s: our definitions, no pre-registered test behind them, nothing being predicted. Reported as a trend-day or reversal-day call it would be a claim we have not measured, so the response says plainly that it is not a forecast and not the day-type classification.
Frequently asked
What happened to the day-type probabilities?
They are part of this response, in the day_type block — each window served by the model trained for it. In the regular day session it is mode=day_session: the same five-class model, the same held-out numbers (66% top-1 and 80% top-2 over a complete session, 53.5% and 68.6% at the 90-minute mark, against a 37% majority-class baseline). In the Asian window of 24-hour instruments it is mode=asia_session: a separate model trained natively on Asian windows under a pre-registered protocol and confirmed zero-shot on NQ — top-1 35.7/38.5/41.0% at 18/42/63 bars on held-out ES windows (n=908, majority-class baseline 30.2%) and 35.2/40.1/45.4% on NQ (n=915, baseline 29.9%). Its five classes come from their own frozen labelling rule, so those figures are not comparable to the day-session 66%/80% and the two sets must never be mixed. The gap window has no validated model and returns available: false; the shape block describes every window with plain arithmetic either way.
What is the difference between day_type and shape?
They answer different questions. day_type estimates what an unfinished session will resolve into, so it is a prediction, it can be wrong, and it comes with a measured accuracy and its majority-class baseline attached. shape measures the bars that have already printed — where price closed inside its own range, how much of the travel was one-way, the deepest pullback, where the high and the low landed, how many times direction changed. It is arithmetic, so there is nothing to be right or wrong about, it carries no accuracy figure, and it exists in every window including the gap. shape is not a day type and borrows none of the day-type numbers; anyone reporting it as one is misreading the response.
Does the famous "80% of range breakouts fail" rule actually work?
Not at 80%. Measured on S&P 500 E-mini trading days from 2010 to 2026 under a pre-registered definition, breakouts from a tight trading range failed 52.1% of the time within 5 bars, 62.6% within 10 bars and 70.6% within 20 bars in the US session (about 3,900 events per horizon, one per day). The direction of the claim is right — most breakouts do fail — but the number never reaches 80% under any definition we tested. This endpoint attaches those measured rates to the breakout it just detected, so you quote the measurement, not the folklore.
What is the conditional estimate, and should I trust it on my symbol?
Every breakout looks different: how tight the range was, how strong the breakout bar was, how often the range had been tested. The conditional estimate feeds twelve such features of the event you are looking at into a small gradient-boosted model and returns a calibrated probability that this breakout closes back through its level within 10 bars. It was validated zero-shot on NQ futures 2023+ — an instrument and period the model never trained on — where it separated breakouts into a lowest tercile that failed 54.2% of the time and a highest that failed 79.1% (AUC 0.646, calibration error 5.1%, n=2,637), and on QQQ (AUC 0.660). On symbols other than ES, NQ and QQQ the response carries a coverage_note and you should treat the estimate as descriptive.
Is this investment advice?
No. Quant Data publishes descriptive analytics and developer tooling for people learning quantitative trading. The API never returns a buy or sell instruction, never sets a price target, and never sizes a position. It reports which classical events just occurred and how events like them resolved historically, with sample sizes. Trading involves risk of loss and past performance does not guarantee future results.
Which symbols can I call?
US tickers (NVDA, TSLA, SPY), US futures with a =F suffix (ES=F, NQ=F, GC=F), Hong Kong stocks as digits plus .HK (3690.HK), China A-shares as 6-digit codes (600519), crypto pairs such as BTC-USD, and spot FX written as EURUSD — never EUR/USD, because the slash splits the URL path. The gap and asia windows exist for 24-hour instruments only. One caveat: callable is not the same as validated. The reference rates were measured on ES and the conditional model was validated on ES, NQ and QQQ; on anything else the response says so and you should relay that.
Do I need to be a programmer to use it?
Not for the early-access workflow, but your AI workspace must have a terminal and outbound network access so it can attach the private API header. The personalized prompt works in ChatGPT Work Desktop and Claude Cowork or Claude Code; standard ChatGPT and Claude web or mobile chat modes are not supported yet. Paying still requires the cardholder to complete Stripe checkout once.
Use Brooks without the full API bundle. Brooks-only access is $9.90 per month, starts immediately, and can be cancelled any time.
Already holding one of the old single-product keys? It keeps working at the price you signed up at. If you want the endpoints it does not cover, email us and we will open them on the same key rather than have you pay twice.
Quant Data is an independent research project and is not affiliated with or endorsed by Al Brooks. If you want to learn the method itself, buy his books.