TradingView indicators

WaveTrend Oscillator: Crosses and Signal Timing

The WaveTrend oscillator compares a normalized, smoothed price deviation (WT1) with its four-bar average (WT2). Their cross marks a change in the oscillator spread. On a live candle, that cross can appear and disappear before the close.

This guide follows LazyBear's public 2014 TradingView version, which the author describes as a TS/MT port. It separates the calculation, reference levels and signal timing so you can compare a script's output on the same completed bar.

HLC3 → EMA channel → normalized deviation → WT1
WT1 → SMA(4) → WT2
WT1 − WT2 → spread and cross events
View the Pine Script example

Channel normalization comes before signal smoothing

The channel length controls two separate EMAs. The first estimates the price center; the second measures the absolute distance from that moving center. The 0.015 factor rescales this distance. Average length then smooths CI into WT1, and a four-bar SMA creates WT2.

WaveTrend calculation in the referenced public version
StageFormulaMeaning
Price inputAP = (high + low + close) / 3HLC3, not close alone.
Channel centerESA = EMA(AP, n)n = 10 by default.
Channel deviationD = EMA(abs(AP − ESA), n)Smoothed absolute distance; not ATR or standard deviation.
NormalizationCI = (AP − ESA) / (0.015 × D)Undefined when D = 0; values can exceed ±100.
Main lineWT1 = EMA(CI, m)m = 21 by default.
Signal and spreadWT2 = SMA(WT1, 4); spread = WT1 − WT2A positive spread means WT1 is above WT2.

The source defaults are n = 10, m = 21, upper levels +53/+60 and lower levels −53/−60. These levels do not cap WT1. A reading above +60 can persist, and does not establish that price must reverse. Changing a threshold only moves a reference line in the example below; it does not change the calculation or filter its alerts.

Worked snapshot: a positive cross at WT1 = 50

Assume the current HLC3 is 103, the updated ESA is 100 and updated D is 2. Then CI = 3 / (0.015 × 2) = 100. With m = 21, the EMA coefficient is 2 / 22 = 1 / 11. If previous WT1 was 45, current WT1 = 45 + (100 − 45) / 11 = 50.

Let the preceding WT1 values, oldest to newest, be 55, 52, 48 and 45. Previous WT2 = (55 + 52 + 48 + 45) / 4 = 50. Current WT2 = (52 + 48 + 45 + 50) / 4 = 48.75. The spread moves from −5 to +1.25: an upward cross. WT1 is positive, so this is not an oversold cross.

This is an arithmetic illustration with specified EMA state, not a market observation or a backtest. The full result depends on earlier data used to initialize and update the EMAs.

A cross, an extreme and a reversal are separate conditions

Cross definitions and optional extreme filters
RuleExact conditionInterpretation
Upward crossWT1 > WT2 now; WT1 ≤ WT2 on the previous bar.The spread changes from nonpositive to positive.
Downward crossWT1 < WT2 now; WT1 ≥ WT2 on the previous bar.The spread changes from nonnegative to negative.
Extreme-filtered upward crossUpward cross AND WT1 < −53 at this bar's close.An optional rule; not every upward cross meets it.
Extreme-filtered downward crossDownward cross AND WT1 > +53 at this bar's close.An optional rule; changing the level changes the sample.

Decide whether an extreme filter uses the signal bar, previous bar or both lines. These are different rules. WT1 moving from −62 to −52 while crossing above WT2 fails a same-bar WT1 < −53 filter, but can pass a previous-bar filter. Neither rule is inherently profitable.

WT1 above WT2 is a state that can last many bars; a crossover is only the transition into that state. The spread crossing zero is the same mathematical event as WT1 crossing WT2, so it is not independent confirmation. A spread above zero also does not require WT1 itself to be above zero.

How the same candle can lose its cross

Illustrative intrabar cross that disappears by close
ObservationWT1WT2Upward cross?
Previous closed bar−56−55Baseline: WT1 below WT2
Current bar, early update−53−54.5Yes, provisionally
Same bar, closing update−57−55.5No confirmed upward cross

These illustrative WT2 values use preceding WT1 values −54, −55 and −56. Pine recalculates the open bar as prices update, using rollback rather than treating every tick as a new bar. A provisional marker can therefore vanish. Waiting for barstate.isconfirmed trades earlier notification for a completed-bar decision. See TradingView's execution model and bar-state documentation.

Pine Script v6 with confirmed cross alerts

This adaptation keeps LazyBear's calculation and attribution. It keeps the default inputs, guards a zero deviation, and gates markers and alerts at the chart bar's close. WT1, WT2 and the spread still update intrabar. The alerts cover crosses at any level; no extreme filter, divergence detector, orders or backtest is included.

Pine Script v6
//@version=6
// WaveTrend calculation: @author LazyBear
// Original: https://www.tradingview.com/script/2KE8wTuF-Indicator-WaveTrend-Oscillator-WT/
// Original author's notice:
// If you use this code in its original/modified form, do drop me a note.
// Pineify adaptation: v6 inputs, zero-deviation guard, confirmed cross alerts.
indicator("WaveTrend: confirmed crosses", shorttitle="WT confirmed", overlay=false)

channelLength = input.int(10, "Channel Length", minval=2)
averageLength = input.int(21, "Average Length", minval=1)
obOuter = input.float(60, "Upper outer level")
obInner = input.float(53, "Upper inner level")
osInner = input.float(-53, "Lower inner level")
osOuter = input.float(-60, "Lower outer level")

ap = hlc3
esa = ta.ema(ap, channelLength)
deviation = ta.ema(math.abs(ap - esa), channelLength)
ci = deviation > 0 ? (ap - esa) / (0.015 * deviation) : na
wt1 = ta.ema(ci, averageLength)
wt2 = ta.sma(wt1, 4)
spread = wt1 - wt2

// Compute crosses every bar. Only markers and alerts wait for bar close.
rawUp = ta.crossover(wt1, wt2)
rawDown = ta.crossunder(wt1, wt2)
valid = deviation > 0 and deviation[1] > 0 and not na(wt2) and not na(wt2[1])
confirmedUp = barstate.isconfirmed and valid and rawUp
confirmedDown = barstate.isconfirmed and valid and rawDown

hline(0, "Zero", color=color.gray)
hline(obOuter, "Upper outer", color=color.red)
hline(obInner, "Upper inner", color=color.red, linestyle=hline.style_dashed)
hline(osInner, "Lower inner", color=color.green, linestyle=hline.style_dashed)
hline(osOuter, "Lower outer", color=color.green)
plot(wt1, "WT1", color=color.teal, linewidth=2)
plot(wt2, "WT2", color=color.orange)
plot(spread, "WT1 minus WT2", color=color.new(color.blue, 80), style=plot.style_area)
plot(confirmedUp ? wt2 : na, "Confirmed upward cross", color=color.lime, linewidth=3, style=plot.style_circles)
plot(confirmedDown ? wt2 : na, "Confirmed downward cross", color=color.red, linewidth=3, style=plot.style_circles)
alertcondition(confirmedUp, "WT confirmed upward cross", "WT1 crossed above WT2 on a closed chart bar")
alertcondition(confirmedDown, "WT confirmed downward cross", "WT1 crossed below WT2 on a closed chart bar")
  1. Paste the complete code into TradingView's Pine Editor, save it and add it to your chart.
  2. Compare closed-bar WT1 and WT2 with the referenced source using the same symbol, timeframe, session and 10/21 inputs. Early values can differ because the example skips normalization when deviation is zero.
  3. Create an alert using one of the two confirmed cross conditions and select Once Per Bar Close. Recreate it after input or code changes; TradingView alerts retain a saved snapshot.
  4. Observe an open bar and its close. The lines may move; confirmed cross markers should appear only if the final cross condition holds.

The example uses only the chart timeframe. A bar-close gate alone does not solve higher-timeframe confirmation if you later add request.security(). Constant-price data has no valid normalized deviation until prices move. Syntax validation does not prove trading performance.

Check the version before changing the rules

The WaveTrend with Crosses publication by lonestar108 adds cross visualization and bar highlights to LazyBear's oscillator. The title contains LazyBear's name, but the publication author is lonestar108. Other similarly named scripts may add filters or change smoothing. Record the publication URL and compare source, lengths, signal average, threshold rule and confirmation timing.

Shorter smoothing can expose more fluctuations, while longer smoothing delays changes. No universal best timeframe or parameter set follows from the formula. Thresholds can remain exceeded in sustained trends; closely spaced crosses can alternate in choppy data. Divergence rules also need explicit pivot and confirmation definitions.

Modify a rule with Pineify

The Pine Script AI Coding Agent can help edit a code document from a written rule. Supply source you are entitled to use, retain its author and license notices, and specify the version you want to match. Review the changes, run syntax validation and compare chart output before using alerts.

"Keep the HLC3 and 10/21 WaveTrend calculation and four-bar signal SMA. Add an upward alert only when WT1 crosses WT2 and WT1 is below −53 on the same closed bar. Keep author notices. Explain how the new rule differs from all-level crosses."
Explore the Pine Script AI Coding Agent

Educational material, not investment advice. Any trading strategy needs separate order, exit, sizing and cost assumptions. Neither a cross nor a successful compile guarantees a profitable trade. Review the source's reuse terms before republishing modified code.

WaveTrend questions

Sources and related indicators

Sources checked October 17, 2026. Numerical examples are explanatory calculations, not historical returns.