◆ New — Strategy Validator, Code Fixer & Prop Compliance Checker are live. Try one free →
Home / Indicators / Schaff Trend Cycle
Momentum indicator

Schaff Trend Cycle

MACD run through two rounds of stochastic normalization — faster-turning than MACD, at the cost of more whipsaw.

Illustrative diagram — not live market data.

What it is

The Schaff Trend Cycle (STC) is a momentum oscillator attributed to Doug Schaff that combines two familiar tools: it starts with a MACD line and then normalizes it twice using stochastic-style calculations. The result is a bounded 0-100 line that turns noticeably sooner than the MACD it is built from, usually read against reference levels around 25 and 75. The often-repeated claim is that STC is 'faster than MACD' — and in the narrow sense of reduced lag at turns, the double stochastic normalization does achieve that. What the marketing usually omits is the cost: normalizing an oscillator to its own recent range makes it react to every wiggle in that range, so STC trades lag for whipsaw rather than eliminating either. It also frequently pins at 0 or 100 for extended stretches, for the same reason StochRSI does. STC is a deterministic transformation of past prices — descriptive, not predictive. This is educational material, not financial advice, and all trading involves risk of loss.

How it works

STC is a four-stage pipeline. Stage one: compute a MACD line as the difference between a fast EMA and a slow EMA of price — the STC convention uses 23 and 50 rather than MACD's usual 12 and 26. Stage two: apply a stochastic calculation to that MACD line, locating it within its own highest-to-lowest range over a cycle length (commonly 10 bars) and scaling to 0-100. Stage three: smooth that value with a recursive averaging step (each bar moves the smoothed value a fixed fraction, typically 0.5, toward the new reading). Stage four: repeat stages two and three on the smoothed result — a second stochastic over the same cycle length followed by the same recursive smoothing. The final output is the Schaff Trend Cycle. Each stochastic pass re-expresses its input relative to its recent extremes, which is what makes STC snap quickly from one end of the scale to the other: once the MACD line reaches a new short-term extreme, the normalization saturates at 0 or 100 regardless of how large the underlying move actually is. The smoothing fractions keep the line from being pure noise, but the range-relative logic dominates its behaviour.

How traders read it

Common settings

The standard parameters are fast EMA 23, slow EMA 50, cycle length 10, and a smoothing factor of 0.5 applied after each stochastic pass. These come from the original publication's convention, not from any optimality result. Shortening the cycle length makes saturation and whipsaw more frequent; lengthening it makes STC behave more like a smoothed MACD. Because there are four interacting parameters, small changes can alter signals substantially — a sensitivity worth testing explicitly rather than assuming.

Strengths

Pitfalls to watch

Pine v6 example

//@version=6
indicator("Schaff Trend Cycle Example", overlay = false)

fastLen  = input.int(23, "Fast EMA Length", minval = 1)
slowLen  = input.int(50, "Slow EMA Length", minval = 1)
cycleLen = input.int(10, "Cycle Length", minval = 1)
factor   = input.float(0.5, "Smoothing Factor", minval = 0.1, maxval = 1.0)

macdLine = ta.ema(close, fastLen) - ta.ema(close, slowLen)

// First stochastic pass on the MACD line, then recursive smoothing
loM = ta.lowest(macdLine, cycleLen)
hiM = ta.highest(macdLine, cycleLen)
stoch1 = 0.0
stoch1 := hiM - loM > 0 ? (macdLine - loM) / (hiM - loM) * 100 : nz(stoch1[1])
pf = 0.0
pf := nz(pf[1]) + factor * (stoch1 - nz(pf[1]))

// Second stochastic pass on the smoothed result, then smoothing again
loP = ta.lowest(pf, cycleLen)
hiP = ta.highest(pf, cycleLen)
stoch2 = 0.0
stoch2 := hiP - loP > 0 ? (pf - loP) / (hiP - loP) * 100 : nz(stoch2[1])
stc = 0.0
stc := nz(stc[1]) + factor * (stoch2 - nz(stc[1]))

plot(stc, "STC", color = color.blue)
hline(75, "Upper", color = color.gray)
hline(25, "Lower", color = color.gray)

Pro tip: Put STC in one pane and its source MACD(23,50) in another and step through a ranging period bar by bar. Count how many full 0-to-100 STC swings correspond to trivial MACD movement — that count is the honest measure of what the extra speed costs on that instrument and timeframe. Speed and reliability are a trade-off, not a free upgrade. Educational context only, not advice; all trading carries risk of loss.

Built an indicator from this? Run it through the Validator to catch look-ahead bias and repainting, or convert a strategy to Pine Script.

Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.

Catch the bug that compiles.Run auditGet Pro