The Stochastic Oscillator
The stochastic oscillator answers one question: where did the market close, relative to the range it has been trading in? That is a genuinely different question from the one RSI asks, and it comes with a different failure mode — one that has nothing to do with trends and everything to do with division.
What it measures
Section titled “What it measures”The published construction of the raw oscillator is a position within a range. Take the
highest high and the lowest low of the last n bars. Ask where today’s close sits between
them, as a percentage. A close at the top of the range gives 100, a close at the bottom gives
0, a close halfway gives 50.
In AFL primitives that is:
Fragment — not a complete formula
// The textbook raw %K, built from documented parts.Period = 14;RangeHigh = HHV( High, Period );RangeLow = LLV( Low, Period );RawK = 100 * ( Close - RangeLow ) / ( RangeHigh - RangeLow );That expression contains the whole indicator and, if you look at it for a moment, both of its weaknesses. The numerator is bounded above by the denominator, so the result is confined to 0 to 100 — another bounded oscillator, with the same obligation to saturate. And the denominator is a range, which can become very small.
Raw %K jumps around violently, so the published indicator smooths it, and then smooths the smoothing:
| Stage | What it is | The AmiBroker function |
|---|---|---|
| Raw %K | Position of the close within the n-bar range |
none — build it from HHV and LLV, or pass ksmooth = 1 |
| Slow %K | Raw %K averaged over KSmooth bars |
StochK( periods = 14, ksmooth = 3 ) |
| Slow %D | Slow %K averaged over DSmooth bars |
StochD( periods = 14, Ksmooth = 3, Dsmooth = 3 ) |
The stage that many other platforms call fast %D is the stage AmiBroker calls StochK.
How it is commonly read
Section titled “How it is commonly read”The standard readings, again as convention rather than finding:
- Above 80 is called overbought, below 20 oversold.
%Kcrossing above%Dis read as a turn upward, and the reverse downward.- Those crossings are said to “count for more” when they happen in the outer bands.
- Divergence between the oscillator and price is read the same way it is for MACD, with the same methodological problems described in that lesson.
The two limitations that come from the construction
Section titled “The two limitations that come from the construction”It saturates in a trend, for the same reason RSI does
Section titled “It saturates in a trend, for the same reason RSI does”A market advancing steadily closes near the top of its recent range most days, so %K sits
near 100 most days. This is not the indicator warning you about anything; the close being near
the high of the last fourteen bars is what an advance is. Expect long stretches pinned in
the upper band during a trend, and expect the crossings inside that band to be numerous and
mostly meaningless.
It becomes hypersensitive when the range is small
Section titled “It becomes hypersensitive when the range is small”This one is specific to the stochastic and worth more attention than it usually gets. The
denominator is HHV( High, n ) - LLV( Low, n ). In a very quiet market that number becomes
tiny, and a tiny denominator turns a trivial price change into a full-scale swing of the
oscillator.
Consider an instrument whose fourteen-day range is 0.4 per cent of its price. A move of
0.1 per cent — noise, a rounding of the closing auction, a slightly wider spread — travels a
quarter of the whole oscillator scale. %K swings from 20 to 90 and back while the chart
looks like a flat line.
A third, milder point: because the range is built from HHV and LLV, a single extreme bar
fixes the denominator for n bars and then drops out abruptly. The oscillator can jump on a
quiet day because an old spike left the window. This is the same drop-out artefact as a simple
moving average, but sharper, because an extreme moves the whole range rather than one
fourteenth of an average.
Fast, slow, and why the naming is such a mess
Section titled “Fast, slow, and why the naming is such a mess”The historical vocabulary is genuinely confusing, and it is worth untangling once rather than being caught by it repeatedly.
“Fast stochastic” originally meant the pair raw %K and a short average of raw %K. That was found to be too jittery to look at, so the convention shifted: take the smoothed line as the new %K, and average it again for the new %D. That second pair is the “slow stochastic”. The line in the middle — the average of raw %K — therefore has two names depending on which pair you are talking about: it is the fast %D and it is the slow %K. They are the same numbers.
AmiBroker resolved the ambiguity by shipping only the slow pair and naming them plainly. So
StochK gives you that middle line, and StochD gives you the average of it. If a
description elsewhere refers to “%K” and you cannot tell which stage is meant, count the
smoothings — that is the only thing that distinguishes them.
Choosing the lookback is the same trade-off as choosing any window. A shorter periods
narrows the range being measured, so the close reaches the edges of it more often and the
oscillator spends more time saturated. A longer one measures position within a wider range,
which changes the meaning of “near the top” considerably: the top of a 5-day range and the top
of a 60-day range are different statements about the market. Write the period down whenever
you quote a reading.
Displaying it in AmiBroker
Section titled “Displaying it in AmiBroker”It is a 0-to-100 oscillator, so it needs its own pane. Insert it by double-clicking the entry
in Window -> Charts, or apply a formula. The Parameters window’s Axes & Grid tab offers
20/80 among its fixed grid levels, which is the usual pair for this indicator and saves
you writing them.
From a formula:
Fragment — not a complete formula
Period = Param( "Stochastic period", 14, 2, 100, 1 );KSmooth = Param( "K smoothing", 3, 1, 20, 1 );DSmooth = Param( "D smoothing", 3, 1, 20, 1 );
SlowK = StochK( Period, KSmooth );SlowD = StochD( Period, KSmooth, DSmooth );
Plot( SlowK, "%K", colorBlue, styleLine | styleThick );Plot( SlowD, "%D", colorRed, styleLine );PlotGrid( 80, colorGrey40, 9, 1, True );PlotGrid( 20, colorGrey40, 9, 1, True );PlotGrid( 50, colorGrey40, 8, 1, False );Checking what the function actually returns
Section titled “Checking what the function actually returns”AmiBroker does not document the type of averaging used for the internal smoothing, nor the warm-up length. So verify rather than assume:
Fragment — not a complete formula
Period = 14;RawK = 100 * ( Close - LLV( Low, Period ) ) / ( HHV( High, Period ) - LLV( Low, Period ) );
Plot( RawK, "Hand-built raw %K", colorGrey40, styleLine );Plot( StochK( Period, 1 ), "StochK(14, 1)", colorBlue, styleLine | styleThick );Plot( StochK( Period ), "StochK(14) default", colorRed, styleLine );PlotGrid( 80, colorGrey40, 9, 1, True );PlotGrid( 20, colorGrey40, 9, 1, True );Turning this into a testable question
Section titled “Turning this into a testable question”The conventional claim attaches meaning to a threshold, which imports an arbitrary number into the hypothesis. Avoid that by bucketing instead:
On my universe, over my chosen period, do 10-day forward returns differ between bars where slow %K closed in the bottom fifth of its range, the middle three fifths, and the top fifth?
Three buckets instead of one threshold does two useful things. It removes the argument about whether the line should be at 80 or at 75. And it shows you the shape of the relationship — whether returns change smoothly across the range, jump at the edges, or do nothing at all — rather than collapsing everything into a single yes-or-no comparison.
You should also record how many bars land in each bucket. In a trending instrument the top bucket may hold ten times as many bars as the bottom one, and an average computed from a handful of observations is not comparable to one computed from hundreds. The last lesson of this part builds a test of exactly this shape and spends as much time on reading the result as on producing it.
The stochastic oscillator measures where the close sits inside the highest-high to lowest-low
range of the last n bars. AmiBroker’s StochK( periods = 14, ksmooth = 3 ) is the slow
%K — already internally smoothed — and StochD( periods = 14, Ksmooth = 3, Dsmooth = 3 ) is
the slow %D, double smoothed; neither takes an input array, and the internal averaging method
and warm-up are undocumented. It saturates in trends, like every bounded oscillator, and it
becomes hypersensitive when the recent range is small, because the range is the denominator.
Build the raw version from HHV and LLV once, compare it against the built-in, and you will
never again be confused about which of the three stages you are looking at.
Check your understanding
Sources for this lesson
5 verified · checked 2026-08-31
- 01AFL Function Reference — StochKamibroker.com/guide/afl/stochk.html2026-08-31
- 02AFL Function Reference — StochDamibroker.com/guide/afl/stochd.html2026-08-31
- 03AFL Function Reference — HHVamibroker.com/guide/afl/hhv.html2026-08-31
- 04AFL Function Reference — LLVamibroker.com/guide/afl/llv.html2026-08-31
- 05AmiBroker User's Guide — Parameters window§ Grid levelsamibroker.com/guide/w_param.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.