Trendlines and Channels
A horizontal level has one free parameter: the price. A trendline has at least six, and most people who draw one could not list them. This lesson is about counting them honestly, and then about the three known ways to get a sloping line you could actually test.
What a trendline is
Section titled “What a trendline is”Geometrically, nothing complicated: two points define a line, the line has a slope and an intercept, and extending it to the right produces a price for every future bar. Break the line, and price has moved to the other side of that sequence of prices.
The construction rules people use are simple to state.
- An uptrend line is drawn beneath the lows, connecting two or more troughs, and is understood as rising support.
- A downtrend line is drawn above the highs, connecting two or more peaks, and is understood as falling resistance.
- Two points define the line; a third touch is treated as confirmation. The third touch is doing a lot of work in that sentence, and it is worth asking what exactly it confirms.
- The line is usually extended to the right so that it keeps producing prices as new bars arrive. In AmiBroker this is a checkbox in the line’s properties dialogue, and it is the difference between a decoration and a usable object.
Wicks or bodies
Section titled “Wicks or bodies”Do you anchor to the extreme of the bar or to the close? Both conventions are in wide use. Anchoring to wicks respects the fact that trading genuinely happened there. Anchoring to closes treats the extremes as noise and the settled price as signal.
They produce different lines, break on different days, and there is no principled way to choose between them from first principles. You simply have to pick one, write it down, and use the same one every time. An unstated convention is a parameter you have hidden from yourself.
Log or linear
Section titled “Log or linear”Part 4 established that a linear axis shows equal currency moves as equal distances, and a logarithmic axis shows equal percentage moves as equal distances. A straight line on a linear chart is therefore a constant-currency path; the same two anchor points on a log chart give a line that is a constant-percentage path — and the two lines diverge, sometimes dramatically, over a long history.
On a five-year chart of an instrument that has tripled, the choice of axis will change whether the line has been broken. That is not a small detail; it is the whole conclusion.
Channels
Section titled “Channels”A channel is a trendline plus a parallel line offset by some distance, forming a band that price is said to travel inside.
The offset has to come from somewhere, and there are two families of answer.
Drawn channels put the parallel line through the most extreme opposite point in the period, so the band contains everything. This adds a third anchor point to be chosen, and therefore a third opportunity for hindsight.
Computed channels derive both the centre and the width from the data with no anchors at all. AmiBroker’s drawing toolbar offers three of these — Raff, standard deviation and standard error regression channels — alongside the trend line, ray, extended line, vertical line, horizontal line and parallel-lines tools. A regression channel fits a least-squares line through a selected span and sets the band width from the dispersion of price around that fit.
The difference between the two families is not cosmetic. A drawn channel encodes your opinion about which points matter. A computed channel encodes only the window length and the band multiplier, both of which are numbers you can state, vary and report.
Slope and time
Section titled “Slope and time”Two warnings that are easy to miss.
Slope has no meaning without the axes. The famous “45-degree line” is an artefact of whatever zoom level and pane height you happen to be using. Stretch the pane vertically and every line steepens. Any rule phrased in terms of the angle on screen is a rule about your monitor.
The x-axis is bars, not calendar time. AmiBroker plots bar by bar, so weekends, holidays and suspended trading do not occupy horizontal space. A trendline over a period containing a long market closure has a different slope per calendar day than per bar. If you ever want to compare the steepness of two trends, express the slope as a percentage of price per bar and say which interval you used.
The hindsight problem
Section titled “The hindsight problem”Now the count. Here is what actually goes into a hand-drawn trendline:
Every decision inside one trendline
- Which instrument, which interval, which date rangeThe line that exists on a daily chart may not exist on a weekly one
- Which two pivots to anchor toTypically a dozen plausible candidates on a three-year chart
- Wick or bodyTwo different lines from the same two pivots
- Linear or logarithmic scaleTwo different paths into the future
- How many touches count as confirmationAnd how close a bar must come to count as a touch
- When to redraw after a breakThe choice that makes the line unfalsifiable
The last one is the serious one. When a trendline breaks and price then resumes rising, the normal response is to draw a shallower line through the new lows. Do that consistently and the “trendline” can never be wrong: every break is followed by a redraw that re-establishes the trend, and every genuine reversal is credited to the final line.
There is a second, quieter problem. Because the anchors are chosen after seeing the subsequent bars, a line will almost always look as though price respected it — you would not have drawn it otherwise. The touches that appear to validate the line are the same touches that determined its position. Nothing has been tested.
Making a trendline objective enough to test
Section titled “Making a trendline objective enough to test”Three routes out, in increasing order of strictness.
Route 1: anchor it algorithmically
Section titled “Route 1: anchor it algorithmically”Let a rule pick the pivots. AmiBroker provides Peak, Trough, PeakBars and
TroughBars, which return the price and the bar distance of the n-th most recent swing
point, and LineArray, which builds a line array between two bar-and-price coordinates
with optional left or right extension. The official example for LineArray uses exactly
this pairing: two recent troughs from Trough/TroughBars, joined and extended right.
There is a catch, and the official documentation is refreshingly blunt about it. Peak,
Trough, PeakBars, TroughBars and the Zig function they are built on all carry the
same warning: they are based on the Zig Zag indicator and may look into the future. The
Zig page adds that this “means that you can get unrealistic results when back testing
trading system using this indicator”, and that the function is provided for pattern and
trend recognition rather than for systems.
Route 2: replace the line with a computed one
Section titled “Route 2: replace the line with a computed one”Drop the anchors entirely. Fit a least-squares line over a fixed window and let the data
place it. LinearReg(array, periods) returns the end-point value of that fit at every bar;
LinRegSlope returns its slope; StDev(array, periods) gives the dispersion you need for
the band.
Two people who agree on the window length and the band multiplier get the same channel, always. All the discretion has been compressed into two numbers that can be written in a report and varied in a sensitivity check.
Complete runnable AFL
// regression-channel.afl// Part 5 - Trendlines and Channels//// A trend channel with no anchor points to choose. The centre line is the// end-point of a least-squares fit over a fixed window; the band is a multiple// of the standard deviation of price around its own mean over that window.//// Two people running this on the same symbol, the same interval and the same// window get the same channel. That is the entire argument for it: it moves the// free parameters out of your hands (which pivots to anchor to, wick or body)// and into two numbers you have to write down (window length, band width).//// This is not a claim that a regression channel describes the market better// than a hand-drawn trendline. It is a claim that it is reproducible, and that// a hand-drawn line is not.//// Assumptions:// - daily bars, at least Window + 1 bars of history;// - prices greater than zero when fitting in log space;// - the first Window - 1 bars are warm-up and carry no channel.
_SECTION_BEGIN("Regression channel");
Window = Param( "Regression window (bars)", 60, 10, 400, 5 );BandMult = Param( "Band width (x StDev)", 2, 0.5, 4, 0.25 );UseLog = ParamToggle( "Fit in", "Price|Log price", 0 );
// Fitting the logarithm makes the channel a constant-percentage path instead of// a constant-currency one - the same choice as linear versus semi-log scaling// on the chart itself, and it produces a visibly different channel on any long// history.if ( UseLog ){ Source = log( Max( Close, 0.01 ) );}else{ Source = Close;}
Centre = LinearReg( Source, Window );Spread = StDev( Source, Window );
Upper = Centre + BandMult * Spread;Lower = Centre - BandMult * Spread;
if ( UseLog ){ Centre = exp( Centre ); Upper = exp( Upper ); Lower = exp( Lower );}
Plot( Close, "Close", colorDefault, styleCandle );Plot( Centre, "Regression centre", colorOrange, styleLine | styleThick );Plot( Upper, "Upper band", colorBlueGrey, styleLine );Plot( Lower, "Lower band", colorBlueGrey, styleLine );
// Where is price inside the channel? Zero at the centre, +1 at the upper band,// -1 at the lower. SafeDivide keeps a zero-width band from producing Null.Position = SafeDivide( Close - Centre, Upper - Centre, 0 );
// The slope of the fit, expressed as a percentage of price per bar, so that the// number means the same thing on any instrument.SlopePct = 100 * SafeDivide( LinRegSlope( Source, Window ), IIf( UseLog, 1, Close ), 0 );
Title = Name() + " regression channel, " + Window + " bars, +/-" + WriteVal( BandMult, 1.2 ) + " StDev" + WriteIf( UseLog, ", fitted in log price", ", fitted in price" ) + " | position in channel " + WriteVal( Position, 1.2 ) + " | slope " + WriteVal( SlopePct, 1.3 ) + "% per bar";
_SECTION_END();The formula fits either price or its logarithm — the same linear-versus-log decision as before, now made explicitly by a parameter rather than implicitly by the chart axis. It reports where price sits inside the channel on a scale where zero is the centre line and plus or minus one is a band, and it reports the slope as a percentage of price per bar so that the number is comparable across instruments.
To convince yourself that this is genuinely reproducible, note the channel’s boundary values today, close AmiBroker, reopen it and apply the formula again. The numbers are identical. Repeat that experiment with a hand-drawn line and you will not manage it.
Route 3: keep the hand-drawn line, but freeze it
Section titled “Route 3: keep the hand-drawn line, but freeze it”Sometimes the judgement is the point — you looked at the chart, you saw something, and you want to know whether that line meant anything. The honest way to find out is to draw it, timestamp it, and only ever evaluate bars that came afterwards.
AmiBroker supports this directly. Since version 3.52 any drawn study can be given a
two-letter Study ID in its properties dialogue, and Study(studyid, chartid) returns the
study as an array that AFL can use. The predefined identifiers are "UP" for uptrend,
"DN" for downtrend, "SU" for support, "RE" for resistance and "ST" for stop loss,
though the User’s Guide notes that any two-letter code is accepted. The chart identifier
normally comes from GetChartID(), which refers to the current pane.
The User’s Guide worked example is a single line: a support-line break is
Cross(Study("SU", GetChartID()), Close) — the study crossing above the close, which is
another way of saying the close fell below the study.
Complete runnable AFL
// trendline-break.afl// Part 5 - Trendlines and Channels//// Reads a trendline you drew by hand and turns it into an array, so that the// break of that line becomes an event with a date attached rather than an// impression. Study() is AmiBroker's bridge from a drawing to a formula.//// Before applying this formula:// 1. draw a trend line on the price pane (Insert -> Trend line, or the// "Draw" toolbar);// 2. open its properties (double-click the line, or Alt+Enter);// 3. tick the right-extension option so the line keeps going as new bars// arrive;// 4. set "Study ID" to "SU" for a rising support line, or "RE" for a falling// resistance line. Both are AmiBroker's own predefined two-letter codes.//// Assumptions:// - the study is on THIS chart pane. Study() is looked up by chart ID, so a// line drawn on another pane is invisible here;// - the User's Guide does not document what Study() returns when no study// with the requested ID exists, so this formula reports how many bars the// study actually covers. Read that number before you trust an empty result;// - the line was drawn once and left alone. Redrawing it after a break makes// every reported date meaningless.
_SECTION_BEGIN("Hand-drawn trendline break");
LineId = ParamList( "Study ID", "SU|RE", 0 );ConfirmBars = Param( "Closes required beyond the line", 2, 1, 5, 1 );
Plot( Close, "Close", colorDefault, styleCandle );
TrendLine = Study( LineId, GetChartID() );Plot( TrendLine, "Study " + LineId, colorOrange, styleLine | styleThick | styleNoRescale );
// How many bars does the drawing actually cover? A study that was never drawn,// or that sits on a different pane, will not produce a usable array.LineBars = LastValue( Cum( IIf( IsNull( TrendLine ), 0, 1 ) ) );
// A support line is broken downwards, a resistance line upwards.// Cross() is an edge detector: true only on the bar the relationship changed.if ( LineId == "SU" ){ Beyond = IIf( IsNull( TrendLine ), 0, Close < TrendLine ); BreakEvent = Cross( TrendLine, Close ); BreakShape = shapeDownArrow; BreakColor = colorRed;}else{ Beyond = IIf( IsNull( TrendLine ), 0, Close > TrendLine ); BreakEvent = Cross( Close, TrendLine ); BreakShape = shapeUpArrow; BreakColor = colorGreen;}
// Confirmation: exactly the last ConfirmBars closes are on the far side of the// line, and the bar before them was not. That makes confirmation an event too,// instead of a state that stays true for the rest of the chart.Confirmed = Sum( Beyond, ConfirmBars ) == ConfirmBars AND Sum( Beyond, ConfirmBars + 1 ) == ConfirmBars;
PlotShapes( IIf( BreakEvent, BreakShape, shapeNone ), BreakColor, 0, Close, -20 );PlotShapes( IIf( Confirmed, shapeSmallCircle, shapeNone ), BreakColor, 0, Close, -40 );
Title = Name() + " study \"" + LineId + "\" covers " + NumToStr( LineBars, 1.0 ) + " bars" + " | arrow = first close beyond the line" + " | circle = " + ConfirmBars + " consecutive closes beyond it";
_SECTION_END();How it works
Section titled “How it works”The formula asks for a study by identifier, plots whatever came back, and then does three
things with it. It counts how many bars the study actually covers, so that a missing or
mis-tagged drawing announces itself instead of silently producing no signals. It detects the
first close beyond the line with Cross, which is an edge detector and therefore fires
once rather than on every subsequent bar. And it detects a confirmed break: exactly the
last N closes beyond the line, with the bar before them not beyond it, which turns
confirmation into an event of its own.
Key functions
Section titled “Key functions”Study(studyid, chartid, scale)— returns a hand-drawn study as an array.scaledefaults to automatic, following the pane’s own linear or logarithmic setting.GetChartID()— the identifier of the current chart pane. The same value appears in the Parameters dialogue under Axes and Grid, Miscellaneous.Cross(a, b)— true only on the bar whereacrosses aboveb. Reverse the arguments for the other direction.Sum(array, periods)— a rolling sum, used here to count consecutive closes beyond the line.
Test it
Section titled “Test it”Draw a line that price has clearly already broken and set its Study ID. Apply the formula. An arrow should appear on the bar you would have picked by eye. Now drag one end of the line by a few bars: the arrow moves, immediately and visibly. That sensitivity is the honest measure of how much your line was worth.
Common errors
Section titled “Common errors”Extension
Section titled “Extension”Add a second study — "RE" for a falling resistance line — and plot both, so that a
converging pair of lines becomes visible as a triangle. Then ask yourself what would count
as the triangle “resolving”, and notice how quickly you need a time limit as well as a
price condition.
A trendline is a hypothesis with at least six free choices baked into it, most of them invisible to the person drawing it. The redraw convention is the worst of them, because it turns a claim that could fail into a description that cannot.
Channels inherit all of that and add an offset, unless you compute them, in which case the whole construction collapses into two stated numbers. Slope is meaningless without naming the axes and the interval.
If you want a sloping line you can actually investigate, you have three options: let an algorithm place the anchors while remembering that the Zig-based functions may look into the future, replace the line with a regression fit, or draw it by hand and evaluate only what happened afterwards. All three are better than the fourth option, which is to draw a line, admire it, and call the admiration evidence.
Check your understanding
Sources for this lesson
9 verified · checked 2026-08-31
- 01AmiBroker User's Guide — Using studies in AFL formulasamibroker.com/guide/h_studies.html2026-08-31
- 02AmiBroker User's Guide — Charting guide§ Using drawing toolsamibroker.com/guide/h_charting.html2026-08-31
- 03AFL Function Reference — Studyamibroker.com/guide/afl/study.html2026-08-31
- 04AFL Function Reference — LineArrayamibroker.com/guide/afl/linearray.html2026-08-31
- 05AFL Function Reference — Peakamibroker.com/guide/afl/peak.html2026-08-31
- 06AFL Function Reference — Troughamibroker.com/guide/afl/trough.html2026-08-31
- 07AFL Function Reference — Zigamibroker.com/guide/afl/zig.html2026-08-31
- 08AFL Function Reference — LinearRegamibroker.com/guide/afl/linearreg.html2026-08-31
- 09AFL Function Reference — StDevamibroker.com/guide/afl/stdev.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.