Breakouts, Failed Breakouts and Role Reversal
Two analysts look at the same daily chart. One says the breakout happened on Tuesday, the other says it has not happened yet. Neither is being difficult: they are using different definitions of a word that sounds as though it has only one meaning. This lesson makes the definitions explicit, because a definition you have not written down is a definition you cannot test.
Six things called a breakout
Section titled “Six things called a breakout”All six of these are in common use. Every one of them is defensible. They identify different days.
| # | Definition | Fires when |
|---|---|---|
| 1 | Intraday penetration | The bar’s high exceeds the prior N-bar high |
| 2 | Closing breakout | The close exceeds the prior N-bar high |
| 3 | Margin breakout | The close exceeds the level by at least k × ATR, or by x per cent |
| 4 | Multi-bar confirmation | Two or more consecutive closes above the level |
| 5 | Volume-confirmed breakout | A closing breakout on volume above m times its own average |
| 6 | Range breakout | The close leaves a defined consolidation band, either side |
Definition 1 fires earliest and most often; definition 4 fires latest and least often. On a typical liquid stock over five years the counts can differ by a factor of three or more. If someone tells you that breakouts do or do not work, the first useful question is: which of these six did you measure?
The trap in the obvious formula
Section titled “The trap in the obvious formula”Before any of this can be measured, one piece of arithmetic has to be right.
The natural way to write “the close is above the highest high of the last twenty bars” is this, and it produces an array that is essentially never true:
Fragment — not a complete formula
// WRONG. HHV's window includes the current bar, so today's high is one of the// twenty candidates and the close cannot exceed a maximum that contains it.BreakoutBar = Close > HHV( High, 20 );The official HHV page states that the period includes the current day. The window has to
be pushed back one bar to mean “before today”, and Ref with a negative argument does
exactly that:
Fragment — not a complete formula
// RIGHT. The level is the highest high of the twenty bars before this one.Level = Ref( HHV( High, 20 ), -1 );BreakoutBar = Cross( Close, Level );Note the second change as well. Close > Level is a state: it stays true for as long as
price remains above the level, which on a strong trend can be months. Cross(Close, Level)
is an event: it is true only on the bar where the relationship changed. A breakout is an
event. Part 9 devotes a whole lesson to this distinction because it breaks more formulas
than any other single mistake.
State versus event on the same level
| Bar | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
Close | 20.0 | 20.4 | 21.6 | 22.1 | 21.9 | 22.8 | 22.4 |
Level | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 |
Close > Level (state) | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
Cross(Close, Level) (event) | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Confirmation and what it costs
Section titled “Confirmation and what it costs”Confirmation filters exist to reduce the number of breakouts that immediately reverse. They work, in the narrow sense that they do reduce that number. They are not free.
Every filter buys you the same three things, in the same proportions:
- Fewer immediate reversals, because the weakest breakouts are excluded.
- A worse entry price, because you are acting later and further from the level.
- Fewer observations, which makes whatever you conclude less reliable and, in the limit, makes the test uninformative.
And every filter adds a parameter. A closing breakout has one number in it: the lookback. Add an ATR margin and you have two. Add a volume multiple and its averaging length and you have four. Four parameters, each tried at five plausible values, is 625 versions of “the breakout system” — and one of them will look excellent on any dataset you own. Part 30 puts numbers on how badly that misleads.
Failed breakouts
Section titled “Failed breakouts”A failed breakout is a breakout that reverses. To count them, two more numbers are needed: how far back price has to come, and within how long.
Without the time limit, the concept is empty. A breakout followed by a return below the level after eighteen months is not a failed breakout in any useful sense; it is a breakout and then a subsequent decline. Without the distance rule, a single tick back below the level counts as failure. So:
A breakout at level L on bar t has failed if the close is below L on any bar between t+1 and t+N.
That is testable. It is also, notice, impossible to know at the time. On bar t+3, a breakout with N = 10 is neither a success nor a failure; it is undetermined. Any commentary that labels breakouts as failed in real time is either using a much shorter N than it admits, or is describing the past.
Role reversal
Section titled “Role reversal”The claim, in its usual form:
Once resistance is broken, it becomes support. Once support is broken, it becomes resistance.
This is a compound claim, and taking it apart is more useful than arguing about it. It asserts, first, that the level continues to matter after it has been crossed — that participants remember it. And second, that the direction of its effect flips.
The first half is at least mechanically plausible: buyers who missed the move may place limit orders at the old high, and the sellers who were absorbed at that price are gone. The second half does not follow from the first. A level could keep mattering without reversing role, and the memory could simply fade.
Making it measurable requires you to be specific about the sequence:
- A level L exists by some stated definition.
- Price closes above L by some stated margin (an upward break).
- Some bars later, price returns to the zone around L from above — the first touch after the break.
- Question: over the next N bars, does price hold above L − w more often than a comparable price with no history would?
Step 4 is the one people skip, and it is the only one that turns the story into evidence. Without a comparison, “it held 6 times out of 10” is a number without a scale. The reality check at the end of this part builds that comparison properly.
Gaps as a special case
Section titled “Gaps as a special case”AmiBroker gives you the strict definitions directly. GapUp() returns true on a bar where
yesterday’s high is less than today’s low; GapDown() is true where yesterday’s low is
greater than today’s high.
Notice that this is stricter than the definition many people carry in their heads, which is “today’s open is above yesterday’s close”. Under AmiBroker’s definition the entire bar must sit clear of the previous bar’s range, so a day that opens higher and then trades back into yesterday’s range is not a gap up. Both definitions are legitimate; they are not the same thing, and the counts differ substantially. When you report gap statistics, say which one you used.
Gaps matter to this part for a specific reason. A gap through a level means no trading took place at the level at all. Whatever mechanism you believed in — resting limit orders, absorbed supply, remembered prices — did not have the opportunity to operate. So a gap through resistance is a different event from a grind through resistance, even though a horizontal line on a chart makes them look identical.
There is a practical consequence too, which Part 30 develops: if your rule places a stop at a level, a gap does not fill you at the level. It fills you wherever the market reopened, which may be a long way below.
Two related built-ins are worth knowing while we are here. Inside() is true when today’s
high is below yesterday’s high and today’s low is above yesterday’s low; Outside() is
true on an outside bar. Both are used in the next lesson as consolidation and expansion
markers.
Turning a visual idea into a rule
Section titled “Turning a visual idea into a rule”This is the general procedure, and it applies to everything in this part.
From something you noticed to something a computer can find
- Name the object"The prior 20-bar high", not "the resistance up there"
- Give it a numberEvery fuzzy word becomes a parameter with a stated value
- Give it a time windowWithin how many bars must the thing happen?
- Make it an event, not a stateCross, not >, unless you genuinely mean the whole span
- Decide the outcome measure in advanceAnd what result would count as nothing happening
The formula below applies the first four steps to three of the six definitions, so that you can see them disagreeing on your own data.
Complete runnable AFL
// breakout-definitions.afl// Part 5 - Breakouts, Failed Breakouts and Role Reversal//// One chart, three definitions of "breakout", three different sets of dates.// Nothing here says which definition is the right one. The point is that the// word on its own does not identify an event, so a rule has to name one and// live with the consequences.//// A (circle) - the close rises through the highest HIGH of the previous// Lookback bars.// B (square) - as A, but the level must be exceeded by AtrMult x ATR(20),// so a one-tick poke does not qualify.// C (star) - as A, but the day's volume must also exceed VolMult times its// own moving average.//// A "failed breakout" is marked with a cross: a breakout by definition A whose// close falls back below the level within FailBars bars.//// Assumptions:// - daily bars; Volume is present and non-zero for definition C;// - counts in the title cover the bars currently loaded on the chart, so they// change when you zoom. That is deliberate: it forces the range to be// explicit rather than assumed;// - the failure marker looks FORWARD by FailBars bars. It is legitimate here// only because this array is drawn and never traded.
_SECTION_BEGIN("Three breakout definitions");
Lookback = Param( "Breakout lookback (bars)", 20, 5, 250, 1 );AtrMult = Param( "Definition B: excess (x ATR)", 0.25, 0.05, 2, 0.05 );VolMult = Param( "Definition C: volume multiple", 1.5, 1, 5, 0.1 );VolAvgLen = Param( "Definition C: volume average length", 50, 5, 200, 5 );FailBars = Param( "Failure window (bars)", 5, 1, 40, 1 );
// The level. HHV includes the current bar, so without Ref( ..., -1 ) the test// would be comparing today's close with a window that already contains today's// high - and Close > HHV( High, n ) can then never be true.Level = Ref( HHV( High, Lookback ), -1 );
Excess = AtrMult * ATR( 20 );VolumeAvg = MA( Volume, VolAvgLen );
BreakA = Cross( Close, Level );BreakB = Cross( Close, Level + Excess );BreakC = BreakA AND Volume > VolMult * VolumeAvg;
// Failure: at any point in the next FailBars bars the close is back below the// level that was broken. LLV of the forward window does the "at any point".FellBack = Ref( LLV( Close, FailBars ), FailBars ) < Level;FailedA = BreakA AND FellBack;
Plot( Close, "Close", colorDefault, styleCandle );Plot( Level, "Prior " + Lookback + "-bar high", colorRed, styleStaircase );Plot( Level + Excess, "... plus " + WriteVal( AtrMult, 1.2 ) + " x ATR", colorLightOrange, styleStaircase | styleDashed );
PlotShapes( IIf( BreakA, shapeSmallCircle, shapeNone ), colorBlue, 0, High, 12 );PlotShapes( IIf( BreakB, shapeSmallSquare, shapeNone ), colorOrange, 0, High, 26 );PlotShapes( IIf( BreakC, shapeStar, shapeNone ), colorGreen, 0, High, 40 );PlotShapes( IIf( FailedA, shapeDownArrow, shapeNone ), colorRed, 0, High, 54 );
CountA = LastValue( Cum( BreakA ) );CountB = LastValue( Cum( BreakB ) );CountC = LastValue( Cum( BreakC ) );CountF = LastValue( Cum( FailedA ) );
Title = Name() + " " + Interval( 2 ) + " breakouts on the loaded bars: " + "A circle " + NumToStr( CountA, 1.0 ) + " " + "B square " + NumToStr( CountB, 1.0 ) + " " + "C star " + NumToStr( CountC, 1.0 ) + " " + "of which A failed within " + FailBars + " bars: " + NumToStr( CountF, 1.0 );
_SECTION_END();How it works
Section titled “How it works”One level, three tests, one failure marker. The level is Ref(HHV(High, Lookback), -1),
drawn as a staircase because it only changes when a new high enters or an old one leaves the
window.
Definition A is Cross(Close, Level). Definition B is the same cross against
Level + AtrMult * ATR(20), so a one-tick poke above the old high does not qualify.
Definition C takes A and additionally requires volume above VolMult times its own
moving average.
The failure marker looks forward: it asks whether the lowest close of the next
FailBars bars is below the level. That is a deliberate forward reference, legitimate only
because the array is drawn and never traded — the formula’s header comment says so, and you
should form the habit of writing that comment yourself.
Key functions
Section titled “Key functions”Cross(a, b)— true on the baracrosses aboveb, and only that bar.HHV/LLVwithRef(..., -1)— the prior-window extreme, excluding today.ATR(period)— volatility scale, used to express the margin in the instrument’s own units.MA(Volume, n)— the volume baseline for definition C.PlotShapes(shape, colour, layer, yposition, offset)— marks bars. A positive offset moves the shape up the pane, which is how three markers stack without overlapping.
Expected result
Section titled “Expected result”Test it
Section titled “Test it”Set the lookback to 20 and record the three counts. Now set it to 50 without changing anything else. Every count falls, and they do not fall proportionally — the volume-confirmed count usually falls fastest, because longer-lookback breakouts are rarer events and the volume condition prunes what is left. Then set the ATR margin to its maximum and watch the B count collapse. Nothing about the market changed during this experiment. Only your definitions did.
Common errors
Section titled “Common errors”Extension
Section titled “Extension”Add definition 4 from the table: two consecutive closes above the level. The pattern is the
same one used in the trendline formula, Sum(condition, 2) == 2 AND Sum(condition, 3) == 2,
which is true on the second qualifying bar and not afterwards. Then count how many of the
A signals survive to become 4 signals, and how many bars later they arrive.
“Breakout” names at least six different events, and the choice between them changes both how many you find and which days they land on. State the definition or the conversation is not about anything.
The mechanics matter: HHV includes the current bar, so the level needs a Ref(..., -1)
shift, and a breakout is an event, so it needs Cross rather than a comparison. Confirmation
filters trade false starts for worse prices, fewer observations and more parameters.
A failed breakout needs both a distance and a time limit before it means anything, and it cannot be identified at the time. Role reversal is two claims stacked, only the first of which has an obvious mechanism, and it becomes measurable only when you specify the sequence and supply a comparison. Gaps deserve separate treatment because a gap through a level means the level was never actually traded.
Check your understanding
Sources for this lesson
8 verified · checked 2026-08-31
- 01AFL Function Reference — HHVamibroker.com/guide/afl/hhv.html2026-08-31
- 02AFL Function Reference — Crossamibroker.com/guide/afl/cross.html2026-08-31
- 03AFL Function Reference — Refamibroker.com/guide/afl/ref.html2026-08-31
- 04AFL Function Reference — GapUpamibroker.com/guide/afl/gapup.html2026-08-31
- 05AFL Function Reference — GapDownamibroker.com/guide/afl/gapdown.html2026-08-31
- 06AFL Function Reference — Insideamibroker.com/guide/afl/inside.html2026-08-31
- 07AFL Function Reference — Outsideamibroker.com/guide/afl/outside.html2026-08-31
- 08AFL Function Reference — PlotShapesamibroker.com/guide/afl/plotshapes.html2026-08-31
Every technical claim on this page was checked against the official AmiBroker documentation on the date shown. Where the course disagrees with folklore, the source is how you can tell which one to trust.