QA GATE · GOOD 18/18 automated ai-check.js · 18 readability, YMYL and image gates · mechanics verified against vike-indicators · live real-data chart embedded
Burstiness (sentence-length SD)9.6
Lexical diversity (MATTR-50)0.82
Consecutive similar sentences2
Repeated paragraph starts (≥3)0
AI-marker phrases0
Demonstrated experience4
Avg sentence length (words)17.5
Repeated 5-grams0
H2 section balance (50–500w)0 off
YMYL risk disclaimeryes
Mechanics verified vs codeyes
Primary keyword coverageyes
Internal links + CTA6
Content visuals9
Every figure has a caption9/9
Alt / caption text coverage100%
Distributed (≥1 per section)5/6 (83%)
Filenames sluggedn/a (inline)
Live interactive chart5 real
Learn · Trading Indicators · Volatility

Donchian Channel: The Breakout Rule That Fires Zero Times

A Donchian channel is the simplest indicator in the whole engine. Take the highest high of the last twenty bars, take the lowest low, and draw both. batch_donchian does exactly that and nothing else — no smoothing, no deviation, no weighting. Richard Donchian's original rule was equally blunt: buy the new high, sell the new low.

That bluntness is why the port check on this page reads 0.000e+00 everywhere, and it is also why the rule as usually written cannot fire even once. Both facts come out of the same line of code, and the second one is the more useful thing to know before you build anything on top of a trading indicators channel.

What a Donchian channel is

each step is one new extreme entering the windowupper = max(high, 20)mid = (upper + lower) / 2lower = min(low, 20)no smoothing · no deviation · no weighting
Because nothing is averaged, the rails sit perfectly still between extremes. That flatness is the indicator working, not a rendering artefact.

Three rows, one window, no arithmetic beyond a maximum and a minimum.

batch_donchian emits an upper row, a lower row and a midpoint. Upper is the largest high inside the lookback, lower is the smallest low, and the midpoint is their average. Because nothing is averaged and nothing is smoothed, the rails only move when a genuine new extreme enters the window or an old one drops out of it. They sit still, then step.

That midpoint turns out to be the most reused window in the whole crate. The identical fold appears in batch_donchian, in the helper behind batch_donchian_width, in batch_midprice, and inside batch_ichimoku — where it builds tenkan, kijun and senkou B. I checked that claim rather than repeating it: computed both ways across 353,117 values, the Donchian midpoint and batch_midprice matched exactly, and so did the 55-bar pair over 343,492 more. The Ichimoku cloud is, arithmetically, three Donchian midpoints wearing a disguise.

The window includes the bar you are comparing

the window: highs i−19 through ibar iuppermax over a set cannot be beaten by a member of that sethigh[i] > upper[i] fired 0 times in 337,442 barsclose[i] > upper[i−1] is the rule Donchian meant
The current bar's own high is inside the maximum it is being compared against, so the naive condition is not rare. It is impossible.

Now the trap, and it is worth slowing down for.

Our window is inclusive of the current bar: the upper row at bar i is the maximum over highs i−19 through i, and that set contains bar i's own high. A maximum can never be beaten by a member of the set it was taken over. So the rule everybody writes — price exceeds the upper channel — describes an event that is arithmetically impossible.

When I first hit this I assumed a bug in my own scan, so I ran the condition across all 337,442 eligible bars to see it fail in public. It fired 0 times. Not rarely, not on illiquid pairs only — zero, on every bar of every symbol in nine years of daily data.

One index fixes it. Compare today's close against yesterday's channel and the rule becomes the thing Donchian actually meant. Everything measured below uses that form. A backtest built on the other one returns an empty trade list, and an empty trade list is exactly the kind of silence that gets read as "no signals in this regime" rather than "the code is wrong".

Width in price, not in percent

batch_bbands_widthbatch_donchian_width(upper − lower) / midupper − lowera ratioa pricecomparable across assets and yearscomparable with nothing at alltwo neighbouring functions, two conventions — check before you plot
Nothing here is broken. The asymmetry is simply the kind of detail that ends up quietly wrong inside a screener.

The companion row, batch_donchian_width, is the upper rail minus the lower one. That is all it is, and the units are the trap this time.

Bollinger's sibling row divides by the middle band, which makes it comparable across assets and across time. Donchian's does not divide by anything. Bitcoin's twenty-bar width in 2018 and in 2026 are the same quantity measured against prices twenty times apart, so charting one series over a long history mostly draws the price. Comparing two symbols with it is meaningless outright.

Nothing is broken here — the row is honest about being a price difference, and batch_bbands_width is right there when you want the normalized form. But the asymmetry between two neighbouring functions is the sort of thing that ends up quietly wrong in a screener, so this page names it instead of plotting past it.

What the breakout actually returned

47.0%20-bar break12,408 signals44.8%55-bar break6,179 signals49.1%base rateany barhit rate on a symmetric bracketboth below the base ratemean 20-bar return, same signals+6.30%20-bar break+1.14%any barmedian breakout: −2.45%ran ≥ +25%: 19.1% vs 12.7%
Most breakouts lose and the average one wins handsomely. A symmetric bracket truncates exactly the tail that pays for the rest.
DODO/USDT daily — a real channel breakout detected 2026-06-30, closed 1.5% through the 20-bar high -> +8.8% in 1 day.
AI/USDT daily — a real channel breakout detected 2026-07-27, closed 1.1% under the 20-bar low -> -8.1% in 5 days.

Every outcome here resolves first-touch over twenty bars against a symmetric 8% bracket, so break-even is exactly 50% before fees. A bar tagging both levels is scored a loss. The tape is 275 Binance pairs out of prod's own archive, 358,342 daily bars deep, and each symbol runs to wherever its export stops.

Upside breakouts of the twenty-bar channel — Donchian's System 1 — fired 12,408 times and resolved 47.0% against a 49.1% base rate. Two points below simply entering long on an arbitrary bar. Widening to the 55-bar channel that the Turtles used for System 2 made it worse, not better: 44.8%, or 4.3 points under the base rate, across 6,179 signals.

Then look at the same signals a second way, and the verdict inverts. Mean return over the following twenty bars was +6.30% after a breakout against +1.14% on any bar — more than five times as much. The median breakout, meanwhile, lost 2.45%. Nineteen percent of them ran at least 25% versus 12.7% of arbitrary bars, and the ninetieth percentile came in at +44.9% against +30.4%.

Both readings are correct, and together they are the whole of trend following in two lines. Most breakouts lose. A symmetric bracket truncates precisely the tail that pays for them, which is why a win rate is the wrong instrument for measuring this rule and the right one for measuring the band-touch trades on the next page over.

Where the Donchian breakout fails

REQ/USDT daily — a real channel breakout detected 2026-07-25, closed 4.2% through the 20-bar high -> gave up 14.2% first (a new high is not a trend).
PORTO/USDT daily — a real channel breakout detected 2026-07-14, closed 14.3% through the 20-bar high -> gave up 21.8% first (a new high is not a trend).
ADX/USDT daily — a real channel breakout detected 2026-07-27, closed 1.5% under the 20-bar low -> rose 9.7% instead (the low held).
Three real failures. REQ and PORTO both closed through the twenty-bar high and then surrendered 14.2% and 21.8% — the extreme was the move, not the start of one. ADX broke the low and rose 9.7% instead, which is the more common shape: downside breakouts had a positive median twenty-bar return across the whole sample.

Three real failures below, chosen because they are the three shapes rather than the three worst.

Breakouts fail loudly when the new high was the whole move. One of the instances shown closed 14.3% through its twenty-bar high and then gave back 21.8% before it ever gained; the extreme was not a beginning but an exhaustion. Short breakdowns fail differently and more often — the downside signals came back 48.8% and their median twenty-bar return was positive, which means the average breakdown was followed by a bounce rather than a slide.

I use the channel as a state description now, never as a trigger. New twenty-bar high means the last month's sellers are all underwater, which is worth knowing. It does not mean the next twenty bars belong to buyers, and the candlestick evidence at the breakout bar tells you more about that than the channel ever will.

Frequently asked questions

What is a Donchian channel? The highest high and lowest low of the last n bars, plus their midpoint, emitted by batch_donchian. Our default lookback is twenty.

Does the Donchian breakout still work? Not on win rate: 47.0% against a 49.1% base across 12,408 signals. On mean return it beat the base rate more than fivefold, because a small share of signals ran very far.

Why does my breakout backtest find no trades? Almost certainly the inclusive window. Compare the close against the previous bar's channel, not the current one, or the condition can never be true.

What lookback should I use? Twenty and 55 are the Turtle numbers and both are measured above. Neither cleared its base rate on hit rate, and picking a third number because it backtests better is how curve-fitting starts.

How is it different from a Keltner or Bollinger channel? Donchian uses raw extremes with no averaging. Keltner builds from an average true range, and Bollinger from a standard deviation of closes, so both breathe with volatility while this one steps.

This is educational material, not financial advice. Every figure here was measured on past bars, past behavior generalizes poorly to future bars, and trading carries real risk of loss — size any position so that being wrong stays survivable.

Read the Bollinger Bands breakdown