A community-famous momentum oscillator — essentially a smoothed, EMA-normalized cousin of the CCI — with two lines and overbought/oversold zones near ±60.
The WaveTrend Oscillator is one of the most-copied community scripts on TradingView, published by the user LazyBear, and it circulates almost entirely without formula documentation — which is why we reverse-engineer it here. Under the hood it is a smoothed variant of the Commodity Channel Index idea: it measures how far the typical price (hlc3) sits from its own exponential average, scales that distance by a smoothed measure of typical deviation (using the same 0.015 constant CCI uses), and then smooths the result again into two lines — a faster WT1 and a slower WT2 (a 4-period SMA of WT1). The output oscillates around zero, with ±60 commonly drawn as extreme zones, though the scale is not strictly bounded. Because every stage is an average of past prices, WaveTrend is a lagging, descriptive tool: it summarizes recent momentum and says nothing certain about future price. Popularity is not validation — a heavily-used script is not a more predictive one. This entry is educational only, not financial advice, and all trading involves risk of loss.
The calculation runs in five deterministic steps. First, take the typical price: ap = (high + low + close) / 3. Second, compute an EMA of it over the channel length (default 10): esa = ta.ema(ap, 10). Third, measure typical deviation the same way: d = ta.ema(math.abs(ap − esa), 10) — an EMA of the absolute distance between price and its average. Fourth, form the normalized channel index: ci = (ap − esa) / (0.015 × d). This is structurally the CCI formula with EMAs substituted for the SMA and mean absolute deviation, which is why WaveTrend behaves like a smoother CCI. Fifth, smooth ci with a longer EMA (default 21) to get WT1, and take a 4-period SMA of WT1 to get WT2 as a signal line. Crossings of WT1 and WT2, and visits to the ±60 region, are what most published scripts trade off. Two implementation notes matter for correctness: the division blows up when d approaches zero (flat, zero-range bars — thin sessions, illiquid symbols), so robust code guards that case; and clones differ — some swap hlc3 for close, alter the 0.015 constant, or add extra smoothing, so two 'WaveTrends' on the same chart can legitimately disagree.
The canonical LazyBear defaults are channel length 10 (for the esa and d EMAs), average length 21 (for WT1), and a fixed 4-period SMA for WT2, computed on hlc3, with guide lines at ±60 and sometimes ±53. Shorter channel lengths make the oscillator jumpier; longer average lengths smooth WT1 at the cost of more lag. Because clones vary the source, constants, and smoothing, state which variant you use when comparing results — identical settings labels do not guarantee identical formulas.
//@version=6
indicator("WaveTrend Example", overlay = false)
chLen = input.int(10, "Channel Length", minval = 1)
avgLen = input.int(21, "Average Length", minval = 1)
src = input.source(hlc3, "Source")
esa = ta.ema(src, chLen)
d = ta.ema(math.abs(src - esa), chLen)
ci = d != 0 ? (src - esa) / (0.015 * d) : 0.0 // guard flat bars
wt1 = ta.ema(ci, avgLen)
wt2 = ta.sma(wt1, 4)
plot(wt1, "WT1", color = color.blue)
plot(wt2, "WT2", color = color.orange)
hline(60, "Upper", color = color.gray)
hline(0, "Zero", color = color.new(color.gray, 50))
hline(-60, "Lower", color = color.gray)
crossUp = ta.crossover(wt1, wt2) and barstate.isconfirmed
plotshape(crossUp, "WT1 x WT2 up", style = shape.triangleup, location = location.bottom, color = color.teal, size = size.tiny)Pro tip: If you compare a WaveTrend port against the original, test on a symbol with occasional flat bars — that is where unguarded implementations diverge wildly because of the near-zero deviation term. And always gate any alert or marker on barstate.isconfirmed, since WT1/WT2 can cross and uncross repeatedly within a live bar. Educational context only, not financial advice: WaveTrend describes past momentum, predicts nothing, and trading always involves risk of loss.
Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.