A five-bar swing pattern that marks local highs and lows — always confirmed two bars after the fact, which is where most implementations quietly cheat.
Williams Fractals, popularized by Bill Williams, are a simple pattern definition for local swing points. An up (bearish) fractal is a bar whose high is higher than the highs of the two bars on either side of it; a down (bullish) fractal is a bar whose low is lower than the lows of the two bars on either side. Fractals are used to mark swing structure, place reference levels for breakouts and stops, and feed other Bill Williams tools such as the Alligator. The critical mechanical fact — and the reason fractal signals appear 'late' — is that a fractal cannot exist until two more bars have closed after the candidate bar. The pattern is defined by its neighbors, so it is unknowable in real time. Most charting platforms then draw the arrow back on the fractal bar itself, two bars in the past, which looks clean but misrepresents when the information became available. Fractals are descriptive markers of past swings, not predictions; this is educational content only, not financial advice, and all trading carries risk of loss.
The standard fractal uses a five-bar window. For an up fractal at bar N, the condition is: high[N] > high[N−1], high[N] > high[N−2], high[N] > high[N+1], and high[N] > high[N+2] (variants allow equal highs on one side). The down fractal mirrors this with lows. Because the condition references the two bars after the candidate, the earliest moment the pattern can be evaluated is at the close of bar N+2 — a fixed two-bar confirmation delay. In Pine Script this is exactly what ta.pivothigh(high, 2, 2) computes: it returns the pivot value on the confirmation bar, two bars after the pivot printed. The trap is in the plotting: the conventional display offsets the marker two bars back so the arrow sits on the swing itself. Visually that is fine, but any backtest, alert, or strategy that reads the offset series as if it were available on the fractal bar is looking two bars into the future. The correct, non-lookahead approach evaluates and acts on the confirmation bar, accepting that price may already have moved meaningfully away from the swing by then.
The classic definition is fixed at two bars on each side (a five-bar pattern) and has no adjustable inputs on most platforms. Generalized pivot versions let you widen the window — for example 3–5 bars per side — which yields fewer, larger swings at the cost of a proportionally longer confirmation delay: n bars per side always means an n-bar wait. Applies to any market and timeframe.
//@version=6
indicator("Williams Fractals (Non-Lookahead)", overlay = true)
n = input.int(2, "Bars Each Side", minval = 1)
// ta.pivothigh/ta.pivotlow only return a value once the pattern is
// confirmed n bars after the candidate bar — the same 2-bar delay the
// classic 5-bar fractal has by definition.
upFractal = not na(ta.pivothigh(high, n, n))
downFractal = not na(ta.pivotlow(low, n, n))
// Marks are placed on the CONFIRMATION bar, not offset back onto the
// fractal bar. Less pretty, but it shows when the signal truly existed —
// a live trader could not have acted any earlier.
plotshape(upFractal and barstate.isconfirmed, "Up Fractal Confirmed", style = shape.triangledown, location = location.abovebar, color = color.red, size = size.tiny)
plotshape(downFractal and barstate.isconfirmed, "Down Fractal Confirmed", style = shape.triangleup, location = location.belowbar, color = color.green, size = size.tiny)
alertcondition((upFractal or downFractal) and barstate.isconfirmed, "Fractal Confirmed", "A Williams fractal was confirmed 2 bars after the swing.")Pro tip: When testing anything built on fractals, compare two versions of your logic: one that acts on the confirmation bar and one that (incorrectly) acts on the fractal bar itself. The performance gap between them is pure lookahead — information you never had. If a published fractal strategy only works with the offset version, it does not work. Educational information only, not financial advice; all trading involves risk of loss.
Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.