The Wave Projection Bands indicator transforms the traditional WaveTrend oscillator into a dynamic price overlay, projecting momentum and overbought/oversold zones directly onto the price chart.
Rather than forcing traders to constantly compare price action with a lower-panel oscillator, the indicator converts oscillator values into adaptive price bands surrounding a projected trend centerline. This creates a visual map showing where WaveTrend considers price to be statistically stretched or compressed in real time.
At its core is a smoothed adaptive centerline that represents the market's current equilibrium. Around this equilibrium, multiple dynamic bands expand and contract with changing market volatility using WaveTrend's channel calculations. As volatility increases, the bands naturally widen. During quieter conditions they contract, providing proportional price targets regardless of market regime.
The indicator divides price into progressive momentum zones ranging from mild extension to extreme overbought and oversold conditions. These zones help traders identify:
- Areas where pullbacks become increasingly probable
- Potential trend continuation zones
- High-probability reversal regions
- Relative momentum strength
- Risk versus reward before entering trades
Additional features include:
- Adaptive projected centerline
- Multi-level dynamic overbought/oversold bands
- Volatility-sensitive zone shading
- Automatic bar coloring by momentum zone
- Forward projection of all bands for anticipating future support and resistance
Code:
# Wave_Projection_Bands
# Inspired by the Wavetrend Oscillator
# Created by Chewie 7/23/26
declare upper;
input colorBars = yes;
input showBands = yes;
input showZoneShading = yes;
input showCenterLine = yes;
input period = 14; # "Period"
input ExtendBands = 10; # "Extend Bands"
input bandChannelLen = 25; # Separate, slower baseline used ONLY for band width
input bandWidthMultiplier = 3.0; # Manual width dial - raise/lower to match your eye
input obLevel0 = 15;
input obLevel1 = 30;
input obLevel2 = 50;
input obLevel3 = 60;
input osLevel0 = -15;
input osLevel1 = -30;
input osLevel2 = -50;
input osLevel3 = -60;
def wtMASource = hlc3;
def price = close;
def na = Double.NaN;
def extBand = Max(ExtendBands, 5);
Script smma {
input src = close;
input length = 100;
def sma = Average(src, length);
def smma_value = CompoundValue(1, (smma_value[1] * (length - 1) + src) / length, sma);
plot out = smma_value;
}
def smma = smma(price, period);
Script extendLine {
input src = close;
input extend = 30;
def slop_i = Round(extend/10, 0);
def slope = (src - src[slop_i]) / slop_i;
def ext; def y1; def slp;
if !isNaN(close) {
ext = 0;
y1 = src;
slp = slope;
} else {
ext = if ext[1] >= extend then Double.NaN else ext[1] + 1;
y1 = y1[1];
slp = slp[1];
}
plot line = y1 +(ext * slp);}
def l_m = extendLine(smma, extBand);
def tfsrc = wtMASource;
def esaBand = ExpAverage(tfsrc, bandChannelLen);
def deBand = ExpAverage(AbsValue(tfsrc - esaBand), bandChannelLen);
def bandScale = 0.015 * deBand * bandWidthMultiplier;
#-- Project OB/OS levels into price
def bandOB0 = l_m + obLevel0 * bandScale;
def bandOB1 = l_m + obLevel1 * bandScale;
def bandOB2 = l_m + obLevel2 * bandScale;
def bandOB3 = l_m + obLevel3 * bandScale;
def bandOS0 = l_m + osLevel0 * bandScale;
def bandOS1 = l_m + osLevel1 * bandScale;
def bandOS2 = l_m + osLevel2 * bandScale;
def bandOS3 = l_m + osLevel3 * bandScale;
plot CenterLine = if showCenterLine then l_m else na;
CenterLine.assignValueColor(if Centerline > Centerline[1] then color.cyan else color.magenta);
Centerline.setlineWeight(4);
CenterLine.HideBubble();
def Volatility_Band1 = 20;
plot DYNAverage1 = Average(CenterLine, Volatility_Band1);
DYNAverage1.SetLineWeight(2);
DYNAverage1.SetDefaultColor(Color.cyan);
AddCloud(DYNAverage1, CenterLine, Color.RED, Color.GREEN);
def bandOB0a = extendLine(bandOB0, extBand);
def bandOB1a = extendLine(bandOB1, extBand);
def bandOB2a = extendLine(bandOB2, extBand);
def bandOB3a = extendLine(bandOB3, extBand);
def bandOS0a = extendLine(bandOS0, extBand);
def bandOS1a = extendLine(bandOS1, extBand);
def bandOS2a = extendLine(bandOS2, extBand);
def bandOS3a = extendLine(bandOS3, extBand);
plot OB0 = if showBands then bandOB0a else na;
plot OB1 = if showBands then bandOB1a else na;
plot OB2 = if showBands then bandOB2a else na;
plot OB3 = if showBands then bandOB3a else na;
plot OS0 = if showBands then bandOS0a else na;
plot OS1 = if showBands then bandOS1a else na;
plot OS2 = if showBands then bandOS2a else na;
plot OS3 = if showBands then bandOS3a else na;
OB0.SetDefaultColor(Color.RED);
OB1.SetDefaultColor(Color.RED);
OB2.SetDefaultColor(Color.MAGENTA);
OB3.SetDefaultColor(Color.MAGENTA);
OS0.SetDefaultColor(Color.GREEN);
OS1.SetDefaultColor(Color.GREEN);
OS2.SetDefaultColor(Color.CYAN);
OS3.SetDefaultColor(Color.CYAN);
OB0.HideTitle(); OB0.HideBubble();
OB1.HideTitle(); OB1.HideBubble();
OB2.HideTitle(); OB2.HideBubble();
OB3.HideTitle(); OB3.HideBubble();
OS0.HideTitle(); OS0.HideBubble();
OS1.HideTitle(); OS1.HideBubble();
OS2.HideTitle(); OS2.HideBubble();
OS3.HideTitle(); OS3.HideBubble();
AddCloud(if showZoneShading then OB0 else na, ob1, createcolor(120,0,0), createcolor(120,0,0));
AddCloud(if showZoneShading then OB1 else na, ob2, createcolor(200,0,0), createcolor(200,0,0));
AddCloud(if showZoneShading then OB2 else na, ob3, Color.MAGENTA, Color.MAGENTA);
AddCloud(os1, if showZoneShading then OS0 else na, createcolor(10,100,0), createcolor(10,100,0));
AddCloud(os2, if showZoneShading then OS1 else na, createcolor(50,150,0), createcolor(50,150,0));
AddCloud(os3, if showZoneShading then OS2 else na, Color.CYAN, Color.CYAN);
#-- Bar coloring by which projected zone price is currently sitting in
def barCol = if high > bandOB2 then 2 else
if high > bandOB1 then 1 else
if low < bandOS2 then -2 else
if low < bandOS1 then -1 else 0;
AssignPriceColor(if !colorBars then Color.CURRENT else
if barCol == 2 then Color.MAGENTA else
if barCol == 1 then Color.RED else
if barCol == -1 then Color.GREEN else
if barCol == -2 then Color.CYAN else Color.light_GRAY);
#-- END of CODE