Skip to content

Free TradingView indicator

Schaff Trend Cycle

Schaff Trend Cycle oscillator built from a MACD line and two smoothed stochastic passes, with 25/75 signals and alerts.

Momentumv1.0TradingView (Pine Script v6) Non-repainting signals Alerts

What it does

The Schaff Trend Cycle (STC), developed by Doug Schaff, is an oscillator that runs a MACD line through a stochastic calculation twice. The result moves between 0 and 100 like a stochastic, but follows the trend-sensitive MACD rather than raw price, and tends to turn earlier than MACD while being smoother than a plain stochastic.

This version colors the line by direction and marks signals when STC crosses up through 25 or down through 75.

How it works

  1. MACD line = EMA(source, fast) − EMA(source, slow). The defaults of 23 and 50 are commonly quoted for STC.
  2. First stochastic: where MACD sits within its range over the cycle length, scaled 0–100. If the range is zero, the previous value is kept.
  3. First smoothing: smoothed = previous + factor × (new − previous), with factor 0.5 by default.
  4. Second stochastic: the same calculation applied to the smoothed series over the cycle length.
  5. Second smoothing with the same factor gives the final STC.

Signals, confirmed on bar close:

  • Bullish: STC crosses above the lower level (25).
  • Bearish: STC crosses below the upper level (75).

The line is green while rising and red while falling. The band between the levels is lightly shaded.

How to use it

  • STC spends much of its time pinned near 0 or 100 and then moves quickly between them. The cross out of an extreme is the event of interest, not the extreme itself.
  • Many traders only take STC signals in the direction of a slower trend tool, for example a 200-period moving average or the higher-timeframe structure.
  • A failed signal, where STC crosses 25 and drops straight back, often appears in ranges and is a reason for caution.
  • Works on most liquid markets from M15 to D1. The MACD lesson explains the base calculation.

Settings

InputDefaultWhat it changes
SourceclosePrice used for the MACD.
MACD fast / slow length23 / 50Speed of the underlying MACD.
Cycle length10Window for both stochastic passes. Shorter = faster, noisier.
Smoothing factor0.5Lower = smoother and slower. 1 = no smoothing.
Lower / upper signal level25 / 75Signal thresholds.
Rising / falling colorsteal / redLine colors and signal markers.

Limitations

  • Because of the double stochastic, STC can jump from one extreme to the other in a few bars on small price moves, producing whipsaw in ranges.
  • In strong trends it can sit at 100 or 0 for long periods and give early counter-trend signals when it dips.
  • Small changes in cycle length or factor noticeably change signal timing; settings that look good on one chart rarely transfer unchanged.
  • Like every oscillator it is derived from past prices and confirms rather than predicts.

Pine Script source

In TradingView open Pine Editor, paste the code, click Save and then Add to chart.

FXP_SchaffTrendCycle.pine

66 lines

// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/schaff-trend-cycle/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
// Schaff Trend Cycle: a MACD line passed through two smoothed stochastic stages, producing a
// 0–100 oscillator. Signals fire when STC crosses up through 25 or down through 75 (bar close).
indicator("FXP Schaff Trend Cycle", shorttitle = "FXP STC", overlay = false)

// ── Inputs ─────────────────────────────────────────────────────────────
grpS     = "Schaff Trend Cycle"
src      = input.source(close, "Source", group = grpS)
fastLen  = input.int(23, "MACD fast length", minval = 1, group = grpS)
slowLen  = input.int(50, "MACD slow length", minval = 2, group = grpS)
cycleLen = input.int(10, "Cycle length", minval = 2, group = grpS)
factor   = input.float(0.5, "Smoothing factor", minval = 0.05, maxval = 1.0, step = 0.05, group = grpS, tooltip = "Weight of each new stochastic value in the two smoothing stages (1 = no smoothing).")

grpL     = "Levels"
lowLevel = input.float(25.0, "Lower signal level", minval = 0.0, maxval = 50.0, group = grpL)
upLevel  = input.float(75.0, "Upper signal level", minval = 50.0, maxval = 100.0, group = grpL)

grpV    = "Display"
colUp   = input.color(#26a69a, "Rising / bullish", group = grpV)
colDown = input.color(#ef5350, "Falling / bearish", group = grpV)

// ── Stage 1: MACD line ─────────────────────────────────────────────────
macdVal = ta.ema(src, fastLen) - ta.ema(src, slowLen)

// ── Stage 2: stochastic of MACD, smoothed ──────────────────────────────
lo1  = ta.lowest(macdVal, cycleLen)
hi1  = ta.highest(macdVal, cycleLen)
rng1 = hi1 - lo1

var float stoch1 = 0.0
stoch1 := rng1 > 0 ? (macdVal - lo1) / rng1 * 100.0 : stoch1

var float smooth1 = na
smooth1 := na(smooth1) ? stoch1 : smooth1 + factor * (stoch1 - smooth1)

// ── Stage 3: stochastic of the smoothed series, smoothed again ─────────
lo2  = ta.lowest(smooth1, cycleLen)
hi2  = ta.highest(smooth1, cycleLen)
rng2 = hi2 - lo2

var float stoch2 = 0.0
stoch2 := rng2 > 0 ? (smooth1 - lo2) / rng2 * 100.0 : stoch2

var float stc = na
stc := na(stc) ? stoch2 : stc + factor * (stoch2 - stc)

// ── Signals ────────────────────────────────────────────────────────────
stcRising  = stc > nz(stc[1])
bullSignal = ta.crossover(stc, lowLevel) and barstate.isconfirmed
bearSignal = ta.crossunder(stc, upLevel) and barstate.isconfirmed

// ── Plots ──────────────────────────────────────────────────────────────
plot(stc, "STC", color = stcRising ? colUp : colDown, linewidth = 2)
hUp  = hline(upLevel, "Upper level", color = color.new(colDown, 40), linestyle = hline.style_dashed)
hLow = hline(lowLevel, "Lower level", color = color.new(colUp, 40), linestyle = hline.style_dashed)
fill(hUp, hLow, color = color.new(color.gray, 94), title = "Neutral band")

plotshape(bullSignal, "STC crosses up through lower level", style = shape.triangleup, location = location.bottom, color = colUp, size = size.small)
plotshape(bearSignal, "STC crosses down through upper level", style = shape.triangledown, location = location.top, color = colDown, size = size.small)

// ── Alerts ─────────────────────────────────────────────────────────────
alertcondition(bullSignal, "STC bullish signal", "Schaff Trend Cycle crossed up through the lower level on {{ticker}} ({{interval}})")
alertcondition(bearSignal, "STC bearish signal", "Schaff Trend Cycle crossed down through the upper level on {{ticker}} ({{interval}})")

Key inputs

Key inputs of Schaff Trend Cycle
InputDefaultDescription
MACD fast length23Fast EMA of the underlying MACD line.
MACD slow length50Slow EMA of the underlying MACD line.
Cycle length10Lookback for both stochastic passes.
Smoothing factor0.5Weight of each new value in the two smoothing stages.
Lower / upper signal level25 / 75Levels STC must cross for a signal.

Educational tools, not advice. Indicators and Expert Advisors describe price; they do not predict it, and past behaviour does not guarantee future results. Test everything on a demo account first and never risk money you cannot afford to lose. See our disclaimer.

Keep exploring

Related tradingview indicators