Indicator · Pine Script v6 · Own pane

WaveTrend v2 [WavesUnchained]

by casoon

WaveTrend v2 [WavesUnchained] is a momentum oscillator displayed in a separate pane.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code212
Settings15inputs
LicenceMIT
Last updateyesterday27 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

212 lines of Pine Script v6 from indicators/momentum/wavetrend/wavetrend_v2.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

wavetrend_v2.pine
//@version=6
// ============================================================================
// WaveTrend v2 [WavesUnchained]
// Version: 2.0.4-experimental
// Author: WavesUnchained
// Build: 2026-10-02 00:00:00
// ============================================================================
// Formel-fokussierter Refactor des klassischen WaveTrend:
//
//   ✓ Schwäche 1: 0.015-Konstante als Input exposed
//   ✓ Schwäche 2: Normalisierung wahlweise Mean-Abs-Dev (klassisch) oder ATR
//   ✓ Schwäche 4: Glättungs-Typ wählbar (EMA / HMA / WMA / JMA-Approx)
//   ✗ Schwäche 6: Adaptive Glättung — nicht in Pine v6 möglich (ta.* require simple int)
//
// Signal-Logik bewusst minimal gehalten (nur Cross), damit man die
// Formel-Verbesserung sauber gegen die klassische Variante A/B-testen kann.
// ============================================================================

indicator('WaveTrend v2 [WavesUnchained]', 'WT2', format=format.price, precision=2,
     max_labels_count=500, max_lines_count=500, max_bars_back=500)

// ─── Engine Inputs ───────────────────────────────────────────────────────────

g_eng = 'Engine'

chLength  = input.int(10, 'Channel Length',  minval=2, group=g_eng,
     tooltip='Smoothing period of price input. Higher = smoother oscillator, more lag.')
avgLength = input.int(21, 'Average Length',  minval=2, group=g_eng,
     tooltip='Second smoothing period applied to the channel index.')
sigLength = input.int(4,  'Signal Length',   minval=1, group=g_eng,
     tooltip='SMA period for the signal line. wtSig = SMA(wt, sigLength).')

priceSrc  = input.source(hlc3, 'Price Source', group=g_eng,
     tooltip='Input price series. Default hlc3. Try ohlc4 for more weight on open, or vwap for volume-weighted.')

// ─── Schwäche 1: Normalisierungs-Konstante ────────────────────────────────────

g_norm = 'Normalization'

ciConst = input.float(0.015, 'Channel Index Constant', minval=0.001, maxval=0.5, step=0.001, group=g_norm,
     tooltip='Normalization constant in the channel index calculation.\n\nClassic WaveTrend uses 0.015 (from Lambert\'s CCI, originally tuned for US stocks). Higher = wt values stay smaller (rarely reach OB/OS bands). Lower = wt values get larger.\n\nFor instruments with higher inherent volatility (NatGas, Crypto), values around 0.020-0.025 may produce more useful range. Test per instrument.')

normMode = input.string('Mean Abs Dev (classic)', 'Volatility Norm', options=['Mean Abs Dev (classic)', 'ATR'], group=g_norm,
     tooltip='How the channel index normalizes deviations:\n\n• Mean Abs Dev: classic — averages absolute close-to-EMA distances. Gap-blind.\n• ATR: uses Average True Range (Wilder) — gap-aware, includes high/low ranges. Recommended for futures with overnight/roll gaps and crypto with liquidity gaps.')

// ─── Schwäche 4: Glättungs-Typ ────────────────────────────────────────────────

g_smooth = 'Smoothing'

smoothType = input.string('EMA (classic)', 'Smoothing Type', options=['EMA (classic)', 'HMA (Hull)', 'WMA (linear weighted)', 'JMA-approx'], group=g_smooth,
     tooltip='Type of smoothing applied to channel index → wt:\n\n• EMA: classic, well-known lag (~length/2 bars)\n• HMA: Hull MA, ~50% less lag than EMA, can ring on noisy data\n• WMA: linear-weighted, simple middle ground\n• JMA-approx: Jurik-like adaptive smoothing (open-source approximation, proprietary original is patented). Tunable phase parameter, less ringing than HMA.')

jmaPhase = input.int(50, '  JMA Phase', minval=-100, maxval=100, group=g_smooth,
     tooltip='Only used when JMA-approx is selected. Phase parameter controls reactivity vs smoothness:\n\n• -100: maximum smoothing, more lag\n• 0: balanced\n• +100: maximum reactivity, less lag, more overshoot\n\nDefault 50 = mild bias toward reactivity.')

// NOTE: Adaptive smoothing (Schwäche 6, Variante C — KAMA / Efficiency Ratio)
// not implemented here because Pine v6's ta.ema/hma/wma require `simple int`
// length, but adaptive length is `series int`. Would require manual EMA/HMA
// implementation. Kept as a future enhancement.

// ─── Bands ───────────────────────────────────────────────────────────────────

g_bands = 'Bands'

upperBand1 = input.int( 60, 'Upper Band 1', group=g_bands)
upperBand2 = input.int( 53, 'Upper Band 2', group=g_bands)
lowerBand2 = input.int(-53, 'Lower Band 2', group=g_bands)
lowerBand1 = input.int(-60, 'Lower Band 1', group=g_bands)

// ─── Signal Logic (minimal, nur Cross) ───────────────────────────────────────

g_sig = 'Signal'

showCross = input.bool(true, 'Show Cross Markers', group=g_sig)
strongOnly = input.bool(true, 'Strong crosses only (in OB/OS zones)', group=g_sig,
     tooltip='When ON, only flag crosses where the oscillator is currently inside the OB or OS band. When OFF, flag every wt-vs-wtSig cross.')

// ─── Functions ───────────────────────────────────────────────────────────────

// JMA-like adaptive smoothing (open-source approximation; not Mark Jurik's
// proprietary algorithm). Output is similar in character to commercial JMA.
f_jma(src, length, phase) =>
    var float jma = na
    var float e0  = na
    var float e1  = na
    var float e2  = na

    _phaseRatio = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100.0 + 1.5
    _beta       = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
    _alpha      = math.pow(_beta, 2)

    e0 := (1 - _alpha) * src + _alpha * nz(e0[1], src)
    e1 := (src - e0) * (1 - _beta) + _beta * nz(e1[1])
    e2 := (e0 + _phaseRatio * e1 - nz(jma[1], src)) * math.pow(1 - _alpha, 2) + math.pow(_alpha, 2) * nz(e2[1])
    jma := nz(jma[1], src) + e2
    jma

// Dispatched smoothing — selects EMA/HMA/WMA/JMA based on user input
f_smooth(src, length, mode) =>
    switch mode
        'HMA (Hull)'           => ta.hma(src, length)
        'WMA (linear weighted)'=> ta.wma(src, length)
        'JMA-approx'           => f_jma(src, length, jmaPhase)
        =>                        ta.ema(src, length)

// Improved WaveTrend formula:
//   • CI normalization constant exposed (Schwäche 1)
//   • Volatility norm switchable Mean-Abs-Dev / ATR (Schwäche 2)
//   • Smoothing type selectable (Schwäche 4)
f_getWT_v2(src, n1, n2, normMode, smoothMode) =>
    _esa = ta.ema(src, n1)
    _d   = normMode == 'ATR' ? ta.atr(n1) : ta.ema(math.abs(src - _esa), n1)
    _ci  = (src - _esa) / (ciConst * _d)
    f_smooth(_ci, n2, smoothMode)

// ─── Core Calculation ────────────────────────────────────────────────────────

wtOsc = f_getWT_v2(priceSrc, chLength, avgLength, normMode, smoothType)
wtSig = ta.sma(wtOsc, sigLength)

lowerThreshold = math.avg(lowerBand1, lowerBand2)
upperThreshold = math.avg(upperBand1, upperBand2)

// ─── Cross Detection ─────────────────────────────────────────────────────────

crossUp   = ta.crossover(wtOsc, wtSig)
crossDown = ta.crossunder(wtOsc, wtSig)

strongUp   = crossUp   and (not strongOnly or wtOsc < lowerThreshold)
strongDown = crossDown and (not strongOnly or wtOsc > upperThreshold)

// ─── Plotting (Pane) ─────────────────────────────────────────────────────────

colorBull    = #16a34a
colorBear    = #dc2626
colorOsc     = #0ea5e9
colorSig     = #f97316

hline(upperBand1, 'OB1', color.new(colorBear, 50))
hline(upperBand2, 'OB2', color.new(colorBear, 75), linestyle=hline.style_dotted)
hline(0,          'Mid', color.new(color.gray, 40))
hline(lowerBand2, 'OS2', color.new(colorBull, 75), linestyle=hline.style_dotted)
hline(lowerBand1, 'OS1', color.new(colorBull, 50))

p_osc = plot(wtOsc, 'Oscillator',
     color.from_gradient(wtOsc, lowerBand1, upperBand1, colorBull, colorBear), linewidth=2)
p_sig = plot(wtSig, 'Signal', color.new(colorSig, 20), linewidth=1)
p_mid = plot(0, display=display.none)
plot(wtOsc - wtSig, 'Histogram', color.new(colorOsc, 50), style=plot.style_histogram, linewidth=1)
fill(p_osc, p_mid, upperBand1, 0,          color.new(colorBear, 88), color.new(colorBear, 100))
fill(p_osc, p_mid, 0,          lowerBand1, color.new(colorBull, 100), color.new(colorBull, 88))

// ─── Markers ─────────────────────────────────────────────────────────────────

if showCross and strongUp
    label.new(bar_index, low, '▲',
         xloc=xloc.bar_index, yloc=yloc.price,
         style=label.style_label_up, color=colorBull, textcolor=color.white,
         size=size.small, force_overlay=true,
         tooltip='WT2 Strong Bullish Cross\nOsc: ' + str.tostring(wtOsc, '#.##')
              + '\nSig: ' + str.tostring(wtSig, '#.##')
              + '\nNorm: ' + normMode + '\nSmoothing: ' + smoothType
              )

if showCross and strongDown
    label.new(bar_index, high, '▼',
         xloc=xloc.bar_index, yloc=yloc.price,
         style=label.style_label_down, color=colorBear, textcolor=color.white,
         size=size.small, force_overlay=true,
         tooltip='WT2 Strong Bearish Cross\nOsc: ' + str.tostring(wtOsc, '#.##')
              + '\nSig: ' + str.tostring(wtSig, '#.##')
              + '\nNorm: ' + normMode + '\nSmoothing: ' + smoothType
              )

// ─── Mini Dashboard ──────────────────────────────────────────────────────────

var table dash = table.new(position.top_right, 2, 6,
     bgcolor=color.new(color.white, 5),
     border_color=color.new(color.gray, 60),
     border_width=1,
     frame_color=color.new(color.gray, 40),
     frame_width=1)

color tc = color.new(color.gray, 20)
color hd = color.new(color.gray, 90)

if barstate.islast
    table.cell(dash, 0, 0, 'WT v2', text_color=tc, bgcolor=hd, text_size=size.small, text_halign=text.align_left)
    table.cell(dash, 1, 0, '',                                  bgcolor=hd, text_size=size.small)

    table.cell(dash, 0, 1, 'Osc',     text_color=tc, text_size=size.small, text_halign=text.align_left)
    table.cell(dash, 1, 1, str.tostring(wtOsc, '#.##'), text_color=colorOsc, text_size=size.small, text_halign=text.align_right)

    table.cell(dash, 0, 2, 'Sig',     text_color=tc, text_size=size.small, text_halign=text.align_left)
    table.cell(dash, 1, 2, str.tostring(wtSig, '#.##'), text_color=colorSig, text_size=size.small, text_halign=text.align_right)

    table.cell(dash, 0, 3, 'Norm',    text_color=tc, text_size=size.small, text_halign=text.align_left)
    table.cell(dash, 1, 3, normMode == 'ATR' ? 'ATR' : 'MAD', text_color=tc, text_size=size.small, text_halign=text.align_right)

    table.cell(dash, 0, 4, 'Smooth',  text_color=tc, text_size=size.small, text_halign=text.align_left)
    _smoothShort = smoothType == 'HMA (Hull)' ? 'HMA' : smoothType == 'WMA (linear weighted)' ? 'WMA' : smoothType == 'JMA-approx' ? 'JMA' : 'EMA'
    table.cell(dash, 1, 4, _smoothShort, text_color=tc, text_size=size.small, text_halign=text.align_right)

    table.cell(dash, 0, 5, 'Const', text_color=tc, text_size=size.small, text_halign=text.align_left)
    table.cell(dash, 1, 5, str.tostring(ciConst, '#.###'), text_color=tc, text_size=size.small, text_halign=text.align_right)

// ─── Alerts ──────────────────────────────────────────────────────────────────

bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed
alertcondition(alertOk and (strongUp),   'WT2 Strong Bull Cross', 'WT2 · LONG · {{ticker}} {{interval}} · Px={{close}}')
alertcondition(alertOk and (strongDown), 'WT2 Strong Bear Cross', 'WT2 · SHORT · {{ticker}} {{interval}} · Px={{close}}')

Overview

WaveTrend v2 [WavesUnchained] derives channel index values using configurable price sources and smooths them with selectable algorithms including EMA, HMA, WMA, or JMA approximation. Traders can toggle normalization between traditional Mean Absolute Deviation and ATR to better account for price gaps. The script plots the oscillator and signal line against adjustable overbought and oversold thresholds, plotting visual markers on crossovers and offering optional filtering for crosses inside extreme bands.

Details

Published by

casoon on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Oscillators & momentum, Volatility & bands

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Topics

pine-scriptpinescripttechnical-analysistrading-indicatorstrading-strategiestradingview

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Channel Lengthint10chLength
Average Lengthint21avgLength
Signal Lengthint4sigLength
Price Sourcesourcehlc3priceSrc
Channel Index Constantfloat0.015ciConst
Volatility NormstringMean Abs Dev (classic)normMode
Smoothing TypestringEMA (classic)smoothType
JMA Phaseint50jmaPhase
Upper Band 1int60upperBand1
Upper Band 2int53upperBand2
Lower Band 2int-53lowerBand2
Lower Band 1int-60lowerBand1
Show all 15 settings
SettingTypeDefaultVariable
Show Cross MarkersbooltrueshowCross
Strong crosses only (in OB/OS zones)booltruestrongOnly
Alerts only on bar close (confirmed)booltruealertsOnBarClose
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

TTM Squeeze

by Alorse
330 stars

This indicator plots a TTM Squeeze momentum oscillator in a separate pane. It compares a Bollinger Band offset to a Keltner Channel offset and marks the zero line white when the difference is non-negative and black when the bands are inside the channel. A line

Indicator v5 Oscillators & momentumVolatility & bands
Updated 2 months ago · None stated GitHub repository of TTM Squeeze

Function - Logistic Equation

by ricardosantos79
261 stars

Calculates dynamic modeling values by applying a mathematical logistic differential equation to price change over a specified lookback length. It measures price momentum relative to the recent high-low price range. The script plots positive and negative logist

Indicator v5 Oscillators & momentumVolatility & bands
Updated 4 years ago · None stated GitHub repository of Function - Logistic Equation

MACD-V

by harryguiacorn
219 stars

MACD-V is a volatility-normalized momentum indicator based on research by Alex Spiroglou. It calculates the standard MACD histogram and normalizes it by dividing by the Average True Range (ATR). Plotted in a separate pane as a colored histogram, it includes us

Indicator v5 Oscillators & momentumVolatility & bands
Updated 1 year ago · None stated GitHub repository of MACD-V
218 stars

This indicator detects a Bollinger Band squeeze when the bands sit inside Keltner Channels, marking low volatility. It plots red dots during a squeeze and green dots when the bands are outside, in a separate pane. An optional histogram shows momentum as the cl

Indicator v6 Volatility & bandsOscillators & momentum
Updated 3 months ago · None stated GitHub repository of Bollinger Band Squeeze Detector
147 stars

This indicator generates trade entry signals and target levels optimized for 1-hour timeframes, designed for external signal extraction. It calculates 7-period and 16-period EMAs alongside 10-period RSI and ATR filters. Long signals occur when the fast EMA cro

Indicator v5 TrendOscillators & momentum
Updated 6 weeks ago · MIT GitHub repository of Signal Strategy 100 Candles of 1H Timeframe

Bubbles Indicator

by capissimo
114 stars

The Bubbles Indicator measures volatility squeezes and expansion bursts using Bollinger Bands combined with a sinusoid oscillator and RSI divergence. It processes price data through scaled Bollinger Bands to highlight volatility changes while confirming trend

Indicator v4 Volatility & bandsOscillators & momentum Repaints
Updated 1 year ago · None stated GitHub repository of Bubbles Indicator

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers