# Do order blocks predict anything?

> Controlled for recent momentum, the order-block measure added nothing out of sample. It was redundant, not underpowered — and the distinction is the method.

- Canonical: https://hadalinstruments.com/research/do-order-blocks-predict-anything/
- Published: 2026-08-23
- Author: Hadal Research
- Answers the question: "do order blocks actually predict anything"
- Coins the term: **Costume Variable** — A constructed feature that appears to measure a new mechanism but is a re-encoding of a simpler variable already in the model — revealed when adding it to a model that already contains the simpler one makes out-of-sample performance worse rather than better.

---
Not in the form that can be measured from price. I built the most natural
price-derived version of the idea — a recency-weighted measure of how much
rejection and dwell had accumulated at a level — and under momentum control it
carried nothing. On held-out data it made the model marginally worse.

My own note at the time is the shortest accurate summary: **the fill-state
proxy was momentum in a costume.** I call that shape a **Costume Variable** — a
feature that appears to measure a new mechanism and turns out to be a
re-encoding of one already in the model.

That is the finding. Most of what follows is the part that took longer to
learn: **why a null is nearly useless unless you publish what would have had to
be true for it to have gone the other way.**

## What was actually tested

The retail vocabulary here is order blocks, unmitigated levels, stacked
liquidity. The measurable core of all of them is the same claim: a level
accumulates a state, and that state predicts what happens on the next visit.

Resting orders are not visible on retail data, so any version of the claim
stated in terms of actual orders is untestable rather than false — and a claim
that cannot be contradicted by observation is not a finding, it is a framing.
The version that *can* be tested is the price-derived one: build the best proxy
for accumulated pressure that price history allows, and ask whether it predicts.

That is what I built, and I built it to spec rather than to fail: a logistic
model of outcome on momentum plus pressure, fitted on the first 70% of the
history by time, evaluated on the held-out remainder.

## The result

The partial effect of pressure, read after momentum, was a likelihood-ratio
χ²(1) of **0.32** at **p = 0.57**.

Split into tertiles, the outcome rate ran **47% / 44% / 47%** — flat, and not
even monotonic.

On the held-out portion, adding pressure to a momentum-only model moved log-loss
from **0.6664 to 0.6667**. Slightly *worse*. That is the signature of a variable
contributing noise rather than information.

The proxy was not too weak to detect. It was carrying the same information
momentum already carried, at lower fidelity.

## What this test could have caught, stated before you ask

A null is only interpretable beside the smallest effect the test could have
found. Without that bound, <q>we found nothing</q> and <q>we could not have found
anything</q> are the same sentence, and the second one is worthless. So here is
the bound.

The model was fitted on **1,027 level arrivals** and checked on a held-out
**441**, with a base outcome rate of **46.6%**. At that size, an effect of
**odds ratio 1.20 per standard deviation** of the pressure measure would have
been detected with 80% power at the conventional five-per-cent threshold. The
effect actually observed was **odds ratio 1.04 per standard deviation**.

In the units the tertile table above uses, the same bound reads: this test
could have caught a spread of about **ten percentage points** between the
lowest- and highest-pressure thirds — roughly 42% against 52%. What it saw was
three points, running the wrong way in the middle.

**Why that is enough to publish as a finding rather than a shrug.** Order
blocks are not taught as marginally predictive. The claim in the wild is that a
level with orders resting at it is *materially* more likely to hold — a
difference you could trade, not one you could only detect with a corpus. An
effect of that size would have been caught here several times over. It was not
there.

**And what it does not license.** Effects smaller than that bound are *not*
excluded by this test, and I am not going to pretend otherwise. If resting
pressure moves the odds by two or three per cent per standard deviation, this
sample could not have seen it, and neither could you trade it. The honest claim
is bounded: the large effect the folklore asserts is refuted; a small one
remains unmeasured.

*The bound is derived from the observed standard error of the pressure
coefficient — the conventional route when a test has already been run — at
alpha 0.05 two-sided and 80% power, on the Wald approximation to the
likelihood-ratio statistic reported above.*

## Why testing it alone would have shown the opposite

The correction generalises well beyond levels, and it is the cheapest correction in this
article.

Tested on its own, a pressure measure looks informative. It genuinely separates
outcomes. That is not an illusion — levels that were recently active really do
behave differently from levels that were not.

But the measure is built from price history, so it correlates with recent price
history **by construction**, whether or not the mechanism it names exists at
all. Any feature assembled from past prices inherits the predictive content of
past prices and then presents it under a new name.

The test that distinguishes the two is conditional and cheap: put the simple
variable in first, then ask what the elaborate one adds. Most feature testing
asks whether the new thing predicts. The question that matters is whether it
predicts *anything the old thing did not*.

---

## The five ways this test could have lied to me

Everything above is the easy half. The harder half is that a conditional test
run carelessly produces a confident null that is worth nothing. Below are five
failure modes, each one measured on my own research rather than argued from
first principles, and each one changing what a null is allowed to mean.

### 1 · Your sample size is not your sample size

The single most common defect in retail and semi-professional testing is
counting overlapping observations as independent ones.

If an outcome is evaluated over a forward window, and a new observation starts
on every bar, then consecutive observations share most of their future. They
are not independent draws. They are heavily overlapping views of the same
price path, and a test that treats them as independent will report a standard
error that is far too small and a p-value that is far too confident.

I measured this on my own EURUSD study — 98,864 bars, a 24-bar horizon and a
20-pip barrier:

| quantity | measured |
|---|---|
| raw walks | **96,991** |
| mean average uniqueness | **0.2608** |
| uniqueness-weighted walks | **25,297** |
| mean walks live at any one time | **6.36** |
| mean walk duration | **6.41 bars** |

**The honest sample is 25,297, not 96,991 — an overstatement of 3.83×.** Every
standard error computed on the raw count is too small by roughly the square root
of that, and every p-value derived from it is correspondingly too eager.

The implication for a null is the opposite of the obvious one, and worth sitting
with: **inflated n makes it easier to reject, so a null computed on an inflated
n is a stronger null than it looks.** My order-block result was already a
failure to reject; correcting the effective sample size makes that failure more
robust, not less. But run the same arithmetic on a *positive* result and it will
frequently dissolve.

**And there is a second source of overlap that is easier to miss, because it is in the
feature rather than the outcome.** The arithmetic above is about the forward window: two
observations overlap because their futures overlap. But two observations also fail to be
independent when they carry **the same label** — and a feature computed at a coarser grain
than the bars it is attached to guarantees that. A daily label spread across hourly bars
makes every occasion twenty-four bars long before the market is consulted at all. In my
own set, three of six features are exactly that (see failure mode five). If you are
conditioning hourly data on a daily statistic, your occasion count is your *day* count, and
the gap between those two numbers is a factor of twenty-four.

One warning, because it is the trap inside the fix. There is a widely-copied
form of the design-effect calculation that divides the long-run variance by
`p(1−p)/n`. **That form returns approximately n for any series you give it** —
it cannot fail, it validates everything, and it is worse than not correcting at
all because it produces a number that looks like diligence. The ratio has to be
between two variances of the *same* estimator.

### 2 · A beautiful cell that does not clear

The second failure mode is the one that catches careful people, because it
requires no error at all — only a search.

I ran an interaction search across my own instrument stack on EURUSD: 15
modules, **1,323 candidate cells**, each one a pair of conditions crossed
against a common outcome ledger. The best cell that came back was this:

> `entropy_perm = Q2` **and** `regime = COMPRESSION` — expectancy **−4.93 pips**
> over **426 episodes**, n = 2,032, HAC t-statistic **−4.55**.

A t of −4.55 on 426 episodes with a coherent mechanical story. In most published
research that is a finding, and it would have been written up as one.

It is not one. Against a rotation null drawn over the same search — **819
rotations, which is every whole-week rotation the 829-week span permits, so the
p-value carries no sampling error and the test is exact rather than
Monte-Carlo** — the family p-value is **0.0646**.

The detail that makes this decisive rather than marginal: the **smallest p this
test could possibly have returned is 0.0012**. The bar was reachable. It was not
met. This was not a test that lacked the resolution to find something — it had
resolution to spare, looked at 1,323 cells, found the best one, and that best
one is not distinguishable from what the same search finds in rotated labels.

The verdict recorded on the artifact is `INSIDE_NULL`, and the sentence that
matters is: *crossing the modules adds nothing the singles did not have.*

**The lesson for anyone testing order blocks, or anything else, with more than
one variant:** the number of things you tried is part of your result. A t of
−4.55 means one thing when it is the only test you ran and something entirely
different when it is the best of 1,323. If you have tried several definitions of
a level, several lookbacks and several outcome windows, you have run a search,
and your best result needs to be priced against the search that produced it.

### 3 · Your baseline may have eaten the signal

The baseline problem is subtler, and I have not seen it discussed in retail material at all.

If your reference model estimates its own baseline from data that already
contains the effect you are looking for, the baseline absorbs the effect and the
test becomes blind to exactly the thing it was built to find.

I hit this on a change-point monitor watching twelve market channels over 201
weekly observations. It flagged one candidate break with a complete attribution
story. Then I tested it against a control: rotate each channel independently,
which preserves every channel's own distribution and autocorrelation while
destroying the co-movement *between* channels, and recount.

- observed joint change-points: **1**
- mean across 200 rotated surrogates: **1.365**
- every one of the 200 surrogates produced **at least as many** as the real data

The real series is not merely indistinguishable from independent channels. It is
**quieter** than them. I do not yet know why — the obvious candidate is that a
covariance estimated from data containing the co-movement absorbs it — and I
publish that as a hypothesis rather than a mechanism, because the artifact
contains no test of it.

The transferable point stands regardless: **a control that can only make your
result look better is not a control.** If your null model is fitted on the same
data as your signal model, find out what it absorbed before you trust either.

### 4 · The instrument, not the market

The instrument explanation is the cheapest to check and the most humbling.

Before concluding that the market has nothing to say, confirm your measurement
device can say anything. I found one of my own features declaring **four
possible states** and, across the entire corpus, having ever emitted **one**. It
passed every structural check — the code was correct, the labels were valid, the
tests were green — and it could not possibly have conditioned anything, because
it never varied.

A declared range is not a realised range. Before reading a null as a fact about
the market, measure the realised spread of your own feature: if the thing you
are conditioning on is pinned at one value, or nearly so, the null is a fact
about your instrument.

Applied here: my tertile split (47% / 44% / 47%) is doing double duty. It shows
the outcome does not vary with pressure — and it also shows the pressure measure
*did* have enough spread to form three genuinely different groups. Had those
tertiles been near-identical in pressure, the flat outcome rate would have proved
nothing at all.

---

### 5 · Your label may be the wrong size for the question

The last one I only measured this week, and it is the one I would now check first, because
it is the cheapest and it invalidates everything downstream of it.

A feature can vary plenty and still be structurally incapable of answering the question you
are asking it — if its **resolution** does not match the question's.

I was testing six of my own conditioning features for how much of each label is explained
by the time of day, on 98,864 hourly bars. Four came back at exactly **0.0000**. Exact
zeros across four independent features are not what noise looks like, so before writing
that down I tested the obvious mechanism, and it was the answer:

| feature | label changes per day | can it express an hour? |
|---|---|---|
| liquidity | 10.407 | yes |
| session *(control)* | 3.298 | yes — by construction |
| atr | 1.936 | yes |
| regime | 0.476 | barely |
| entropy | 0.018 | no — that is once every ~55 days |
| return-memory | 0.002 | no |
| har-vol | 0.000 | no — constant on 100% of days |
| jumps | 0.000 | no — constant on 100% of days |

**Three of the six emit a label that never changes within a day.** Their mutual information
with hour-of-day is zero *by construction*, whatever the market is doing. And this is not a
"weak feature" story — `har-vol` has three states, a modal share of 0.552 and more label
entropy than any other feature in the set. It varies enormously. It just never varies
*within a day*, so it cannot answer an hourly question and its zero says nothing at all
about whether the clock is in the underlying quantity.

Two things make this checkable rather than a caution:

**Run a positive control.** I included a feature whose label *is* the hour bucket. It
returned exactly 1.0000. Without that, a screen of zeros is indistinguishable from a broken
measurement — an empty diagnostic has to be provably empty.

**Know your noise floor.** Mutual information estimated from a finite sample is biased
*upward*, by roughly `(k−1)(m−1) / (2N ln2)`. At this sample size that is about 0.0005
bits. Four features read below their own noise floor, which is what makes those zeros
structural rather than merely small.

### The falsifier that could not fire

There is a sharper version of this worth stating on its own, because it changed how I read
my own pre-registered predictions.

Before running that measurement I had written down a prediction with an explicit falsifier:
*if this particular feature moves little, the mechanism I proposed is wrong.* The feature
moved by exactly zero. On its face the falsifier had fired and the mechanism was dead.

It had not, and it was not. The feature's label is daily — it **could not** have moved on
that metric under any market condition. My falsifier had assumed the feature was capable of
the movement it was testing for, and it was not. So the mechanism came out **untested**,
not refuted, and recording that distinction was the only honest option.

**A pre-registered falsifier is only as good as the assumption that its condition, when
met, is met for the reason you think.** Writing the prediction down first is what made this
visible — had I reasoned about the result afterwards, "the mechanism is wrong" is exactly
the conclusion I would have reached, and it would have been the wrong one.

## What does survive

Something real is in there, and it would be dishonest to let a null on one
construction imply a null on the whole category.

What a level did **most recently** predicts what it does next. The probability of
absorption given that the level last absorbed is **61%**, against **33%** when it
last swept — an odds ratio of **3.49**, and it holds out of sample with log-loss
genuinely better than base rate.

That is a real effect. It is also a general property of price series: recent
behaviour persists for a while. It is not evidence about resting liquidity,
institutional participation, or levels as objects with state, and presenting it
as such would be exactly the move this article is about.

**And I have made that exact move myself, in public, on this same effect.** An earlier
finding of mine read a level's history as durable identity — the two halves of a split
history correlated at r = +0.31, which is what memory would produce and is equally what
short-range trend produces, because the halves share a boundary. Over sixteen years and
183,689 revisits, controlling for the most recent outcome and asking whether a genuinely
distant one still adds anything returns an odds ratio of **1.01** at **p = 0.53**. The
retraction is published as [the level that remembered
nothing](/research/the-level-that-remembered-nothing/), and the shape it names — the
Recency Mirage — is the same shape as the Costume Variable seen from the other side. One
is a feature re-encoding a simpler variable; the other is a *finding* that turned out to be
the same. I did not spot either from the inside.

**Neither shape is new, and the names are the only part I am claiming.** A variable that
carries no information once a correlated simpler one is in the model is collinearity, and
statisticians have had that for a century. A relationship that exists only because both
series carry their own recent history is *spurious regression* in the Granger–Newbold
sense, and the econometrics literature has had that since 1974. There is also an
established **recency illusion** in linguistics, which is a different phenomenon with a
neighbouring name. What I think the names add is nothing about the mechanism and
everything about the moment of recognition: both describe what the error looks like *from
inside the analysis that is making it*, which is the vantage point from which the textbook
terms are hardest to apply to yourself. If you find these useful, the underlying statistics
are older and better documented than anything here.

## The version of this I did build, and what it says

The null above is about a *predictive* proxy. It is not a claim that zones cannot be
tracked — I track them, as objects with a lifecycle, and the base rates that falls out
of are worth more than the feature test that started this article.

Every order block and fair-value gap is instantiated as a zone with a birth bar, a
direction, a size class, and a state that advances as price arrives. The definitions are
mechanical, and they are the ones that matter for the retail claim:

- **TOUCHED** — price entered the zone at all (fill fraction above zero)
- **MITIGATED** — price filled at least half of it (fill fraction ≥ 0.5)
- **INVALIDATED** — a bar **closed** beyond the far edge. For a support zone, price closed
  below its floor. This is the level failing, definitionally.

On EURUSD, over a trailing 520-bar H1 window — about a month — with the input file pinned
by content hash:

| | count |
|---|---|
| zones born in the window | **112** |
| **invalidated — price closed straight through** | **87** |
| still live at the end of the window | **25** |

Of the 25 still live: **16 have never been touched**, 4 have been touched, and 5 are
mitigated at half or more. Seven are order blocks, eighteen are fair-value gaps, and in
this window every live zone is a support zone.

**The retail claim is that a level with accumulated orders is more likely to hold. In this
window, 87 of the 112 that were born did not hold** — and "did not hold" here is not a
judgement call, it is a bar closing beyond the far edge.

One number in that census is **not** a finding and I am not going to present it as one.
The artifact also reports zero zones *expired*, and expiry fires at an age cap of 500
bars inside a 520-bar window — so only a zone born in the first twenty bars could ever
reach it. Zero expiries is an artifact of the window length, not evidence that zones never
age out. It is in the file; it means nothing yet.

**And the honest boundary, which the artifact draws on itself.** Its `signal_v1` block —
the fields that would carry prediction, profit, loss and capital protection — reads
`NOT YET COMPUTED` in all four. This is measured **state**, published as state. The
paired validation that would turn a zone census into a predictive claim has not been run,
and until it has, none of the above is a signal. That is the same discipline the rest of
this article is about, applied to my own instrument rather than to somebody else's idea.

## Five reasons a null happens, and only one of them means stop

The reason all of the above matters is that **<q>we found nothing</q> is not one
result — it is five, and they imply opposite next actions.** Reporting them all
with the same word is the single biggest waste in quantitative research, my own
included.

| the null is limited by | what it means | what to do next |
|---|---|---|
| **effect** | the effect is genuinely near zero and your test had room to see it | stop — this is finished, and the bound is a product |
| **power** | the effect could be real but sits under your detection floor | more data, or a cleaner outcome — it is reachable |
| **occasions** | the condition fires too rarely, or too clustered, to resolve anything | unreachable on this sample; stop *on this corpus* |
| **statistic** | your measure is pinned near its own ceiling or floor | change the instrument, not the hypothesis |
| **geometry** | the effect exists but not in the shape you tested for | re-specify — and price the re-specification as a search |

My order-block result is **effect-limited**, and that is why it is publishable
as a finding rather than parked as inconclusive: the measure did not merely fail
to reach significance, it made held-out prediction *worse*, which is a
direction a merely-underpowered variable does not have.

The interaction result above is also effect-limited, and its bound is unusually
sharp because the achievable floor was measured: p could have gone to 0.0012 and
stopped at 0.0646.

## A number is only true as of the moment it was computed

One more, added the same day I learned it, because it is the failure mode that outlives
every other one on this page.

Everything above is about whether a number was *right when it was measured*. This is about
what happens afterwards. A published figure has a shelf life, and nothing about being
correct on the day protects it.

Two of my own, found this week:

- A document in my estate stated that an append-only register held **159** entries. It
  holds **194**. The sentence was true when written and had quietly stopped being true,
  and nothing in the writing of it could have prevented that.
- Worse, because it reads as precision rather than staleness: a document quoted **"114
  codes defined"**. The registry defines **119**. 114 is the count of codes in a
  particular *state* — a different quantity that happens to be adjacent, and adjacent
  numbers are the ones that survive review.

The cure is not diligence, because diligence is what already failed. It is to attach to
each published number **the command that regenerates it** and **the commit it was last
checked at**, then have something re-run the command and compare. I run exactly that.

**And it had been failing, unread.** Four claims were refusing when I looked — one of them
stale because of a commit I had made myself that morning. I had made a discovery, not
propagated it, and the instrument built to catch precisely that was already saying so to
nobody.

**A rail that is red and unread is a rail that does not exist.** That is the transferable
part, and it is cheaper to accept from someone else's estate than to learn in your own.

The honest application to this article: **the figures in the section above are enrolled
that way; the χ², the tertiles and the log-loss in my own headline result are not.** They
were computed, they are reported faithfully, and they currently have no mechanism
regenerating them on demand.

**And that enrolment order is backwards, which is worth saying plainly rather than
leaving as an observation.** The headline figures are the ones that get quoted, cited and
attacked; the supporting ones are not. Putting the load-bearing numbers last into the rail
means the most-scrutinised values on the page are the least-verified, and publishing that
fact does not fix it. They now ship with their artifact, which closes the recomputation
gap for a reader today; enrolling them in the regenerate-and-compare rail — so a drift is
caught here rather than by someone else — is the outstanding work, and it goes first, not
last.

## Limits

**One instrument — AUDJPY — price-derived measures only, bar data.** A
single-instrument null establishes nothing about any other, and naming which
instrument is part of the claim rather than a detail: the downloadable artifact
states the pair in its first field, and a reader should be able to see that
without opening it. The supporting measurements in this article are drawn from
my EURUSD research rather than from the order-block study itself — they are there to show the method, not to bound that specific
result.

The scope matters more than usual here, so it is worth stating twice: this result
kills **one price-derived proxy as a predictor under momentum control**. It does not
kill the fill-state concept, and it does not kill zone tracking — the zone lifecycle
this article publishes, with its TOUCHED, MITIGATED and INVALIDATED base rates, tracks
zones and reports those rates, and that machinery stands.

What each of the remaining routes actually needs, stated as status rather than as a
wish:

- **Book-based measures** are no longer blocked on data. I hold exchange top-of-book
  quotes and have censused them — 21,158,845 rows across seventeen roots in a single
  trading day. The constraint is that this is exchange data for exchange-traded
  instruments, so it speaks to futures directly and to a retail spot feed only by
  analogy. What is missing is the study, not the tape.
- **Order-flow measures** need signed flow, which top-of-book quotes do not carry.
  That one is still a data question.
- **Zone-state measures** are built and publishing. What they are missing is the
  paired validation, and their own artifact says so in four fields.

The permanent lesson is narrower and more useful than "order blocks don't work":
**accumulated rejection measured from price is dominated by memory.** If you want to
measure state at a level, either use a source that is not the price series itself, or
track the level as an object and report its base rates — but do not build a scalar out
of past prices, put it beside momentum, and expect it to survive.

And whatever you measure it with, publish the floor beside the verdict. A null without
its bound is not a result, it is a shrug with a p-value attached.
## The artifact

- SHA256: f4d2d7450f13405fea85d8afac2e2ee8d1aa9f1c4cbc010b954052b30e73d1d0
- Download: https://hadalinstruments.com/data/order-block-fill-state.json
- Measurement technique: Logistic model of absorb ~ momentum + pressure on AUDJPY level arrivals, fitted on the first 70% by time and evaluated on the held-out remainder. The file is the model's own output verbatim: arrival counts, base rate, coefficients, the partial likelihood-ratio statistic, and held-out log-loss for the base, momentum-only and momentum-plus-pressure models.

---

## Claims examined

### Claim 01 — canonical: https://hadalinstruments.com/refutations/#claim-f48d20b2

> "That level has orders stacked at it, so it's more likely to hold." — our reading: Unproven

I built the honest version: a recency-weighted measure of accumulated rejection and dwell at a level, fitted as a logistic model of outcome on momentum plus pressure, trained on the first 70% of the history by time and checked on the held-out remainder. The partial effect of pressure, read after momentum, came in at a likelihood-ratio chi-squared of 0.32 on one degree of freedom, p = 0.57. Split into tertiles the outcome rate was flat: 47%, 44%, 47%. And on held-out data, adding pressure made the model very slightly worse. The measure was not weak. It was redundant — and the distinction between those two words is the whole of the method.

**What is true:** The price-derived measures of accumulated pressure at a level carry no predictive content once recent behaviour at that level is accounted for, because what they actually encode is recent behaviour at that level.

Evidence: https://hadalinstruments.com/research/do-order-blocks-predict-anything/#claim-f48d20b2

### Claim 02 — canonical: https://hadalinstruments.com/refutations/#claim-9215dcc1

> "It worked in my testing, so the concept is sound." — our reading: Misleading

Tested alone, a pressure measure looks informative, because levels that were recently active do behave differently from levels that were not. The test that matters is conditional: put the simple variable in the model first, then ask what the new one adds. This is not a high bar and it is not expensive. It is simply a different question from the one most feature testing asks, and it is the question that separates a discovery from a renaming.

**What is true:** A feature can only be credited with predictive content once it is tested alongside the simpler variables it might be re-encoding, because a measure built from price history will correlate with recent price history whether or not the mechanism it names exists.

Evidence: https://hadalinstruments.com/research/do-order-blocks-predict-anything/#claim-9215dcc1

### Claim 03 — canonical: https://hadalinstruments.com/refutations/#claim-8821787f

> "So price-based analysis of levels is worthless." — our reading: False

I am not claiming nothing survives, and it would be dishonest to let a null on one construction imply a null on the category. The sequential effect is real and holds out of sample: an odds ratio of 3.49, with held-out log-loss genuinely better than base rate. The honest framing is that the predictive spine is what the level did last, not how loaded it is — and that this is a general property of price series rather than evidence for any story about resting liquidity.

**What is true:** What a level did most recently does carry real, out-of-sample predictive content — the probability of absorption following a prior absorption is 61% against 33% following a sweep — so the useful signal is short-range and sequential rather than a measure of accumulated state.

Evidence: https://hadalinstruments.com/research/do-order-blocks-predict-anything/#claim-8821787f

### Claim 04 — canonical: https://hadalinstruments.com/refutations/#claim-81bdcfb9

> "A null result just means you didn't have enough data." — our reading: Misleading

The claim is sometimes true and is not knowable without measuring it. A null with no bound beside it cannot be distinguished from a test that never had the resolution to reject. So the bound has to be computed and published in the same place as the verdict: what is the smallest effect this test would have caught? If the observed effect is far below that floor, the honest reading is that the question is unresolved on this sample. If the observed effect is a large fraction of the floor and still fails, the line of enquiry is finished and the null is a product. Those two nulls look identical on the page and imply opposite next actions.

**What is true:** A null is only interpretable once it is paired with the smallest effect the test could have detected — without that bound, 'nothing was found' and 'nothing could have been found' are the same sentence.

Evidence: https://hadalinstruments.com/research/do-order-blocks-predict-anything/#claim-81bdcfb9

## Cite This Article

APA BibTeX HTML

Hadal Research. (2026). Do order blocks predict anything?. Hadal Research. https://hadalinstruments.com/research/do-order-blocks-predict-anything/ (SHA-256: f4d2d7450f13405fea85d8afac2e2ee8d1aa9f1c4cbc010b954052b30e73d1d0) Version fa5df51, 2026-08-29.

@misc{hadal_2026_do-order-blocks-predict-anything,
author = {Hadal Research},
title = {Do order blocks predict anything?},
year = {2026},
url = {https://hadalinstruments.com/research/do-order-blocks-predict-anything/},
howpublished = {Hadal Research},
version = {fa5df51},
note = {Published: 2026-08-23; version dated 2026-08-29, Data Hash (SHA-256): f4d2d7450f13405fea85d8afac2e2ee8d1aa9f1c4cbc010b954052b30e73d1d0}
}

Source: Hadal Research, Do order blocks predict anything? (Hash: f4d2d7450f13405fea85d8afac2e2ee8d1aa9f1c4cbc010b954052b30e73d1d0). <a href='https://hadalinstruments.com/research/do-order-blocks-predict-anything/' rel='canonical'>Original Research</a>

Copy Citation

**Version fa5df51** identifies the commit that last changed this page in Hadal's content repository. That repository is not public, so the identifier does not resolve externally — it is published so a citation pins one specific state rather than a moving page. To obtain the exact version cited, use the [press and research route](https://hadalinstruments.com/press/).

## Explore further

### Instruments

- [Epistemic Harness](https://hadalinstruments.com/instruments/epistemic-harness/)
- [Microstructure Dashboard](https://hadalinstruments.com/instruments/microstructure-dashboard/)
- [Overfit Auditor](https://hadalinstruments.com/instruments/overfit-auditor/)
- [Reproducible Verdict Kernel](https://hadalinstruments.com/instruments/reproducible-verdict-kernel/)

### Concepts

- [Absorb/Sweep](https://hadalinstruments.com/glossary/absorb-sweep/)
- [Combinatorial Purged Cross-Validation (CPCV)](https://hadalinstruments.com/glossary/combinatorial-purged-cross-validation/)
- [Data Snooping](https://hadalinstruments.com/glossary/data-snooping/)
- [Deflated Sharpe Ratio (DSR)](https://hadalinstruments.com/glossary/deflated-sharpe-ratio/)
- [Effective Sample Size](https://hadalinstruments.com/glossary/effective-sample-size/)
- [Look-Ahead Bias](https://hadalinstruments.com/glossary/look-ahead-bias/)
- [Walk-Forward Validation](https://hadalinstruments.com/glossary/walk-forward-validation/)

### Indicators whose taught claim it examines

- [Liquidity Pools Indicator](https://hadalinstruments.com/ict/liquidity-pools-indicator/)
- [Order Block Indicator](https://hadalinstruments.com/ict/order-block-indicator/)

### Research

- [The level that remembered nothing](https://hadalinstruments.com/research/the-level-that-remembered-nothing/) Asked as: do price levels remember what happened there before
- [The edge that was real and worth half a pip](https://hadalinstruments.com/research/the-edge-that-was-real-and-worth-half-a-pip/) Asked as: can a trading edge be statistically significant but not profitable
- [Do round numbers matter in forex?](https://hadalinstruments.com/research/do-round-numbers-matter-in-forex/) Asked as: do round numbers matter in forex trading

[All Hadal research](https://hadalinstruments.com/research/)[This article as plain markdown](https://hadalinstruments.com/research/do-order-blocks-predict-anything.md)

---

## Raw artifact — PUBLISHED

The figures on this page recompute from the file below. It is the measurement's own output, content-hashed, so you can verify that what you downloaded is what was measured — and that it has not changed since.

sha256 f4d2d7450f13405fea85d8afac2e2ee8d1aa9f1c4cbc010b954052b30e73d1d0

[Download the artifact](https://hadalinstruments.com/data/order-block-fill-state.json)
