Skip to content
Level 1 · Chart ReaderLessonPart 06 · page 1 of 1124 min
24Minutes
4AFL functions
5Sources
StandardRequires
AFL functions taught here4

What an Indicator Actually Is

By the end of this lesson you will be able to open an indicator you have never seen before, work out in about a minute what it does to price, and say out loud what it cannot possibly know. That skill is worth more than any particular indicator, because it is the thing that stops you from believing a number.

Here is the definition the rest of this part rests on. An indicator takes the bars that have already closed, applies arithmetic to them, and returns one number for every bar. In AmiBroker that is literal: MA( Close, 20 ) is not “a moving average line”, it is an array with exactly as many elements as there are bars on the chart, and the element at bar 500 was computed from bars 481 to 500 and nothing else.

The predefined arrays an indicator can read are documented, and there are not many of them: Open, High, Low, Close, Volume, OpenInt and Avg, where Avg is the typical price, (High + Low + Close) / 3. Everything the platform’s built-in indicators compute, they compute from those. There is no hidden extra input.

MA(Close, 3) is one number per bar, computed from that bar and the two before it

The first two bars have no answer at all. AmiBroker's own worked example shows MA(Close,3) returning Null until three closes exist, and those Nulls propagating into anything that compares against them.
Bar123456
Close10.011.012.011.013.012.0
MA(Close, 3)NullNull11.0011.3312.0012.00
Close > MA(Close, 3)NullNull1010
The first two bars have no answer at all. AmiBroker's own worked example shows MA(Close,3) returning Null until three closes exist, and those Nulls propagating into anything that compares against them. Prices in this diagram are invented for the illustration. They are not market data and nothing should be inferred from them.

Two things in that table are worth staring at. First, the average on bar 5 is 12.00 and the average on bar 6 is also 12.00, even though the closes were different — an average destroys information on purpose. Second, the first two bars are Null, not zero, and AmiBroker’s own tutorial shows those Nulls flowing straight through a comparison into a Buy array. A warm-up period is not cosmetic; it is a stretch of the chart where the indicator has no opinion because it has no data.

An indicator cannot add information that was not in its inputs. It can only remove information, or rearrange what is there into a form your visual system handles better.

That is not a philosophical point. It has a practical consequence you can check: if two indicators are both computed from the last twenty closes, then whatever they disagree about is a disagreement about weighting, not a disagreement about the market. A twenty-bar simple average and a twenty-bar exponential average of the same closes contain the same raw material. When one turns up before the other, that is the weighting scheme talking.

Lag is structural, not a defect to be engineered away

Section titled “Lag is structural, not a defect to be engineered away”

Take a simple average of the last n closes. Every close in the window carries the same weight, 1/n. The average of the bar positions in that window sits (n - 1) / 2 bars in the past. For a 20-bar average, the centre of mass of the calculation is 9.5 bars ago. The line you are looking at is, in a very concrete sense, a summary of where price was about ten bars back.

You can shorten the window, and the summary becomes more current and more jumpy. You can weight recent bars more heavily — that is what an exponential average does — and the centre of mass moves closer to now, but it never reaches now, because if it did the “average” would just be the close and would smooth nothing.

Degrees of freedom: where the numbers came from

Section titled “Degrees of freedom: where the numbers came from”

RSI( 14 ). MA( Close, 200 ). Bollinger Bands at two standard deviations. The 70 and 30 lines. Every one of those constants is a choice someone made, and none of them was derived from a property of markets.

AmiBroker documents the defaults its own functions use, and they are worth knowing precisely because they differ from the conventions you will read elsewhere. RSI( periods = 14 ) and ADX( period = 14 ) match the usual convention. ROC( ARRAY, periods = 12, absmode = False ) does not — its default lookback is 12, not 14 and not 10. BBandTop( ARRAY, periods = 15, width = 2 ) defaults to a 15-bar average, where almost every textbook uses 20. ATR( period ) has no documented default at all.

Each of those numbers is a degree of freedom. Every degree of freedom is somewhere you can, without noticing, tune a rule until it fits history that has already happened. Part 30 and Part 31 deal with that problem at length. For now, form the habit of writing the number down: say “a 14-period RSI”, never “the RSI”, and treat a level of 70 as a line you chose rather than a threshold the market respects.

Given an unfamiliar indicator, five questions get you most of the way. Ask them in order.

Reading an unfamiliar indicator

  1. What are the inputs?Close only? The whole bar? Volume? The previous close, which is what makes gaps visible?
  2. How long is the window?Fixed lookback, or recursive so that every bar ever loaded still contributes something?
  3. What kind of smoothing?Simple mean, linear weights, exponential decay, or Wilder-style recursion. Each has a different centre of mass.
  4. Is it bounded?Bounded oscillators must saturate in a persistent move. Unbounded ones drift with the price level and cannot be compared across symbols.
  5. Is it normalised?Price units, percent, or standard deviations? Only the last two survive a comparison between two different instruments.

Try it on something AmiBroker publishes in full. The documented formula for rate of change is:

Fragment — not a complete formula

// This is the documented definition of ROC, not something to type.
// ROC( array, periods ) equals:
100 * ( array - Ref( array, -periods ) ) / Ref( array, -periods )

Walk the five questions. The input is whatever array you pass, so it need not be price. The window is fixed: exactly one bar periods ago, with everything in between ignored — this is a two-point measurement, not an average, which is why it is so jumpy. There is no smoothing at all. It is unbounded. And it is normalised, because the difference is divided by the earlier value and multiplied by 100, so it is already a percentage.

That last point is where people get hurt. Because the denominator is the earlier value and not its absolute value, applying ROC to something that can go negative — an oscillator, a spread, the MACD line — flips the sign of the answer whenever the denominator is negative. AmiBroker documents an absmode argument for exactly this case, defaulting to False. Reading the formula tells you that. Reading a description of “rate of change” does not.

Now try the same five questions on RSI, whose internal algorithm AmiBroker also publishes:

Pseudocode — not valid AFL

for each bar after the first:
diff = this close - previous close
W = diff if diff > 0, else 0 // the up-move
S = -diff if diff < 0, else 0 // the down-move
P = ( (period - 1) * P + W ) / period
N = ( (period - 1) * N + S ) / period
if enough bars have passed:
RSI = 100 * P / ( P + N )

Input: closes only, and only their bar-to-bar differences — the size of the bar’s range is invisible to RSI. Window: recursive. P and N are running values that are never reset, so every bar ever loaded still contributes a little; the nominal 14 controls the decay rate, not a hard cut-off. Smoothing: this recursion is Wilder’s, and it is neither a simple average nor the standard 2/(n+1) exponential average, which is why RSI values from two different platforms often disagree slightly. Bounded: yes, hard, between 0 and 100 by construction, because P and N are both non-negative and the result is P over their sum.

Every lesson from here on is a specific case of the same argument. The stochastic oscillator divides by the recent range, so it saturates when price sits at the edge of that range. ADX double-smooths a measure of directional movement, so it is slow and it says nothing about direction. OBV accumulates from the first bar loaded, so its level is an artefact of how much history you happen to have in the database.

None of that makes indicators useless. It makes them instruments with known characteristics, which is a much better thing to own than a signal generator you do not understand.

An indicator is a function of bars that have already closed, returning one number per bar. It creates no information; at best it discards the parts you were not going to use. Lag is a structural consequence of averaging, not a flaw to be optimised away. Every constant in an indicator’s definition is a choice, and AmiBroker’s documented defaults do not always match the conventions in books. Reading the arithmetic — inputs, window, smoothing, bounds, normalisation — tells you more in one minute than a chapter of interpretation.

Check your understanding

Question 1. A 30-bar simple moving average and a 30-bar exponential moving average of the same closes disagree about where the trend turned. What does that disagreement tell you about the market?
Show the answer and why

Answer: Nothing about the market — it is a difference in weighting of the same 30 closes

Both are functions of the same input. Whatever they disagree about is a property of the weighting scheme, not of the price history they share.

Question 2. AmiBroker documents ROC as 100 * ( array - Ref( array, -periods ) ) / Ref( array, -periods ). Applying it to the MACD line, which can be negative, produces surprising signs. Why?
RocOfMacd = ROC( MACD(), 12 );
Show the answer and why

Answer: The denominator is the earlier value itself, so a negative denominator flips the sign

The default absmode of False divides by the signed earlier value. AmiBroker documents absmode = True, which divides by its absolute value, for arrays that can go negative.

Question 3. Which of these statements are consequences of an indicator being a function of past data only? Select all that apply.
Show the answer and why

Answer: It has a warm-up period during which it returns Null or unreliable values, It cannot contain information that was absent from the bars it read, A bounded oscillator must saturate during a persistent one-way move

The first three follow directly from the construction. The fourth does not: an indicator in price units, such as ATR or LinRegSlope, is not comparable across instruments until you divide by something that scales with price.

Question 4. You read that an indicator "has no lag". Which explanation is NOT one of the three real possibilities?
Show the answer and why

Answer: It uses a proprietary smoothing that removes lag without cost

Lag is the price of averaging. A method can move the centre of mass closer to the present, at the cost of noise, but no weighting of past bars can place it at or beyond the present bar.

Sources for this lesson

5 verified · checked 2026-08-31

  1. 01AFL Function Reference — MAamibroker.com/guide/afl/ma.html2026-08-31
  2. 02AFL Function Reference — ROCamibroker.com/guide/afl/roc.html2026-08-31
  3. 03AFL Function Reference — RSI§ Internal implementation commentamibroker.com/guide/afl/rsi.html2026-08-31
  4. 04AmiBroker User's Guide — Understanding how AFL language worksamibroker.com/guide/h_understandafl.html2026-08-31
  5. 05AmiBroker User's Guide — AFL language reference§ Identifiersamibroker.com/guide/a_language.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.