Help Needed with Upper and Lower zigzag band

british43

Member
VIP
I'm trying to code an upper/lower band on the zigzag indicator based on user input but having some difficulty aligning the pivots. Any assistance would be appreciated.


3XXHqJx.png


Ruby:
def bn = BarNumber();
def na = Double.NaN;

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;

def hibn = HighestAll(bn);
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

def priceH = high;
def priceL = low;
def priceC = close;

def o = open;
def h = high;
def l = low;
def c = close;

input percentageReversal = 3;
input absoluteReversal = 0.0;
input atrLength = 2;
input atrReversal = 2;
input tickReversal = 0;

Assert(percentageReversal >= 0, "'percentage reversal' must not be negative: " + percentageReversal);
Assert(absoluteReversal >= 0, "'absolute reversal' must not be negative: " + absoluteReversal);
Assert(atrReversal >= 0, "'atr reversal' must not be negative: " + atrReversal);
Assert(tickReversal >= 0, "'ticks' must not be negative: " + tickReversal);
Assert(percentageReversal != 0 or absoluteReversal != 0 or atrReversal != 0 or tickReversal != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def absReversal;
if (absoluteReversal != 0) {
    absReversal = absoluteReversal;
} else {
    absReversal =  tickReversal * TickSize();
}

def hlPivot;
if (atrReversal != 0) {
    hlPivot = percentageReversal / 100 + WildersAverage(TrueRange(high, close, low), atrLength) / close * atrReversal;
} else {
    hlPivot = percentageReversal / 100;
}


def state = {default init, undefined, uptrend, downtrend};
def maxPriceH;
def minPriceL;
def newMax;
def newMin;
def prevMaxH = GetValue(maxPriceH, 1);
def prevMinL = GetValue(minPriceL, 1);

if GetValue(state, 1) == GetValue(state.init, 0) {
    maxPriceH = priceH;
    minPriceL = priceL;
    newMax = yes;
    newMin = yes;
    state = state.undefined;
} else if GetValue(state, 1) == GetValue(state.undefined, 0) {
    if priceH >= prevMaxH {
        state = state.uptrend;
        maxPriceH = priceH;
        minPriceL = prevMinL;
        newMax = yes;
        newMin = no;
    } else if priceL <= prevMinL {
        state = state.downtrend;
        maxPriceH = prevMaxH;
        minPriceL = priceL;
        newMax = no;
        newMin = yes;
    } else {
        state = state.undefined;
        maxPriceH = prevMaxH;
        minPriceL = prevMinL;
        newMax = no;
        newMin = no;
    }
} else if GetValue(state, 1) == GetValue(state.uptrend, 0) {
    if priceL <= prevMaxH - prevMaxH * hlPivot - absReversal {
        state = state.downtrend;
        maxPriceH = prevMaxH;
        minPriceL = priceL;
        newMax = no;
        newMin = yes;
    } else {
        state = state.uptrend;
        if (priceH >= prevMaxH) {
            maxPriceH = priceH;
            newMax = yes;
        } else {
            maxPriceH = prevMaxH;
            newMax = no;
        }
        minPriceL = prevMinL;
        newMin = no;
    }
} else {
    if priceH >= prevMinL + prevMinL * hlPivot + absReversal {
        state = state.uptrend;
        maxPriceH = priceH;
        minPriceL = prevMinL;
        newMax = yes;
        newMin = no;
    } else {
        state = state.downtrend;
        maxPriceH = prevMaxH;
        newMax = no;
        if (priceL <= prevMinL) {
            minPriceL = priceL;
            newMin = yes;
        } else {
            minPriceL = prevMinL;
            newMin = no;
        }
    }
}



def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(priceH), 0, barNumber));
def newState = GetValue(state, 0) != GetValue(state, 1);
def offset = barCount - barNumber + 1;
def highPoint = state == state.uptrend and priceH == maxPriceH;
def lowPoint = state == state.downtrend and priceL == minPriceL;

def lastH;
if highPoint and offset > 1 {
    lastH = fold iH = 1 to offset with tH = priceH while !IsNaN(tH) and !GetValue(newState, -iH) do if GetValue(newMax, -iH) or iH == offset - 1 and GetValue(priceH, -iH) == tH then Double.NaN else tH;
} else {
    lastH = Double.NaN;
}


def lastL;
if lowPoint and offset > 1 {
    lastL = fold iL = 1 to offset with tL = priceL while !IsNaN(tL) and !GetValue(newState, -iL) do if GetValue(newMin, -iL) or iL == offset - 1 and GetValue(priceL, -iL) == tL then Double.NaN else tL;
} else {
    lastL = Double.NaN;
}


plot ZZ;
if barNumber == 1 {
    ZZ = fold iF = 1 to offset with tP = Double.NaN while IsNaN(tP) do if GetValue(state, -iF) == GetValue(state.uptrend, 0) then priceL else if GetValue(state, -iF) == GetValue(state.downtrend, 0) then priceH else Double.NaN;
} else if barNumber == barCount {
    ZZ = if highPoint or state == state.downtrend and priceL > minPriceL then priceH else if lowPoint or state == state.uptrend and priceH < maxPriceH then priceL else Double.NaN;
} else {
    ZZ = if !IsNaN(lastH) then lastH else if !IsNaN(lastL) then lastL else Double.NaN;
}
ZZ.SetDefaultColor(GetColor(1));
ZZ.EnableApproximation();


input toggle = yes;
input reversalamount = 8.0;



def chg = close - GetValue(zz, 1);
def isUp = chg >= 0;
def isdn = chg <= 0;
def isConf = AbsValue(chg) >= reversalamount or (IsNaN(GetValue(ZZ, 1)) and GetValue(isConf, 1));


ZZ.DefineColor("Up Trend", Color.UPTICK);
ZZ.DefineColor("Down Trend", Color.DOWNTICK);
ZZ.DefineColor("Undefined", Color.DARK_ORANGE);
ZZ.AssignValueColor(if !isConf then ZZ.Color("Undefined") else if isUp then ZZ.Color("Up Trend") else ZZ.Color("Down Trend"));
DefineGlobalColor("Unconfirmed", Color.DARK_ORANGE);
DefineGlobalColor("Up", Color.UPTICK);
DefineGlobalColor("Down", Color.DOWNTICK);


#Upper Band
input WMA = 5;
def wma_wma_c  = close  + wma;
def wma_bn = BarNumber();
def wma_na = Double.NaN;

def wma_o = open + wma;
def wma_h = high+ wma;
def wma_l = low + wma ;
def wma_c = close + wma;

def wma_lastbn = HighestAll(If(IsNaN(wma_c ), 0, wma_bn));
def wma_lastbar = if (wma_bn == wma_lastbn) then 1 else 0;

def wma_hibn = HighestAll(wma_bn);
#def wma_lastbar = !isnan(wma_wma_c [0]) and isnan(wma_wma_c [-1]);

def wma_priceH = high + wma;
def wma_priceL = low  + wma;
def wma_priceC = close  + wma;


input wma_percentageReversal= 3;
input wma_absoluteReversal = 0.0;
input wma_atrLength  = 2;
input wma_atrReversal  = 2;
input wma_tickReversal  = 0;

Assert(wma_percentageReversal>= 0, "'percentage reversal' must not be negative: " + wma_percentageReversal);
Assert(wma_absoluteReversal >= 0, "'absolute reversal' must not be negative: " + wma_absoluteReversal);
Assert(wma_atrReversal  >= 0, "'atr reversal' must not be negative: " + wma_atrReversal );
Assert(wma_tickReversal  >= 0, "'ticks' must not be negative: " + wma_tickReversal );
Assert(wma_percentageReversal!= 0 or wma_absoluteReversal != 0 or wma_atrReversal  != 0 or wma_tickReversal  != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def wma_absReversal ;
if (wma_absoluteReversal != 0) {
    wma_absReversal  = absoluteReversal;
} else {
    wma_absReversal  =  wma_tickReversal  * TickSize();
}

def wma_hlPivot  ;
if (wma_atrReversal  != 0) {
    wma_hlPivot   = wma_percentageReversal/ 100 + WildersAverage(TrueRange(wma_h , wma_c , wma_l ), wma_atrLength ) / wma_c  * wma_atrReversal ;
} else {
    wma_hlPivot   = wma_percentageReversal/ 100;
}


def wma_state = {default init, undefined, uptrend, downtrend};
def wma_maxPriceH;
def wma_minPriceL;
def wma_newMax;
def wma_newMin;
def wma_prevMaxH = GetValue(wma_maxPriceH, 1);
def wma_prevMinL  = GetValue(wma_minPriceL, 1);

if GetValue(wma_state, 1) == GetValue(wma_state.init, 0) {
    wma_maxPriceH = wma_priceH;
    wma_minPriceL = wma_priceL;
    wma_newMax = yes;
    wma_newMin = yes;
    wma_state = wma_state.undefined;
} else if GetValue(wma_state, 1) == GetValue(wma_state.undefined, 0) {
    if wma_priceH >= wma_prevMaxH {
        wma_state = wma_state.uptrend;
        wma_maxPriceH = wma_priceH;
        wma_minPriceL = wma_prevMinL ;
        wma_newMax = yes;
        wma_newMin = no;
    } else if wma_priceL <= wma_prevMinL  {
        wma_state = wma_state.downtrend;
        wma_maxPriceH = prevMaxH;
        wma_minPriceL = wma_priceL;
        wma_newMax = no;
        wma_newMin = yes;
    } else {
        wma_state = wma_state.undefined;
        wma_maxPriceH = prevMaxH;
        wma_minPriceL = wma_prevMinL ;
        wma_newMax = no;
        wma_newMin = no;
    }
} else if GetValue(wma_state, 1) == GetValue(wma_state.uptrend, 0) {
    if wma_priceL <= wma_prevMaxH - wma_prevMaxH * wma_hlPivot   - wma_absReversal  {
        wma_state = wma_state.downtrend;
        wma_maxPriceH = prevMaxH;
        wma_minPriceL = wma_priceL;
        wma_newMax = no;
        wma_newMin = yes;
    } else {
        wma_state = wma_state.uptrend;
        if (wma_priceH >= prevMaxH) {
            wma_maxPriceH = wma_priceH;
            wma_newMax = yes;
        } else {
            wma_maxPriceH = prevMaxH;
            wma_newMax = no;
        }
        wma_minPriceL = wma_prevMinL ;
        wma_newMin = no;
    }
} else {
    if wma_priceH >= wma_prevMinL  + wma_prevMinL  * wma_hlPivot   + wma_absReversal  {
        wma_state = wma_state.uptrend;
        wma_maxPriceH = wma_priceH;
        wma_minPriceL = wma_prevMinL ;
        wma_newMax = yes;
        wma_newMin = no;
    } else {
        wma_state = wma_state.downtrend;
        wma_maxPriceH = prevMaxH;
        wma_newMax = no;
        if (wma_priceL <= wma_prevMinL ) {
            wma_minPriceL = wma_priceL;
            wma_newMin = yes;
        } else {
            wma_minPriceL = wma_prevMinL ;
            wma_newMin = no;
        }
    }
}



def wma_barNumber  = BarNumber();
def wma_barCount  = HighestAll(If(IsNaN(wma_priceH), 0, wma_barNumber ));
def wma_newState  = GetValue(wma_state, 0) != GetValue(wma_state, 1);
def wma_offset  = wma_barCount  - wma_barNumber  + 1;
def wma_highPoint = wma_state == wma_state.uptrend and wma_priceH == wma_maxPriceH;
def wma_lowPoint = wma_state == wma_state.downtrend and wma_priceL == wma_minPriceL;

def wma_lastH ;
if wma_highPoint and wma_offset  > 1 {
    wma_lastH  = fold aH = 1 to wma_offset  with kH = wma_priceH while !IsNaN(kH) and !GetValue(wma_newState , -aH) do if GetValue(wma_newMax, -aH) or aH == wma_offset  - 1 and GetValue(wma_priceH, -aH) == kH then Double.NaN else kH;
} else {
    wma_lastH  = Double.NaN;
}


def wma_lastL ;
if wma_lowPoint and wma_offset  > 1 {
    wma_lastL  = fold xL = 1 to wma_offset  with gL = wma_priceL while !IsNaN(gL) and !GetValue(wma_newState , -xL) do if GetValue(wma_newMin, -xL) or xL == wma_offset  - 1 and GetValue(wma_priceL, -xL) == gL then Double.NaN else gL;
} else {
    wma_lastL  = Double.NaN;
}


plot wma_ZZ;
if barNumber == 1 {
    wma_ZZ = fold dF = 1 to wma_offset with fP = Double.NaN while IsNaN(fP) do if GetValue(state, -dF) == GetValue(wma_state.uptrend, 0) then wma_priceL else if GetValue(wma_state, -dF) == GetValue(wma_state.downtrend, 0) then wma_priceH else Double.NaN;
} else if barNumber == wma_barCount {
    wma_ZZ = if wma_highPoint or wma_state == wma_state.downtrend and wma_priceL > wma_minPriceL then wma_priceH else if wma_lowPoint or wma_state == wma_state.uptrend and wma_priceH < wma_maxPriceH then wma_priceL else Double.NaN;
} else {
    wma_ZZ = if !IsNaN(wma_lastH) then wma_lastH else if !IsNaN(wma_lastL) then wma_lastL else Double.NaN;
}
wma_ZZ.SetDefaultColor(GetColor(1));
wma_ZZ.EnableApproximation();
 
Last edited:
I'm trying to code an upper/lower band on the zigzag indicator based on user input but having some difficulty aligning the pivots. Any assistance would be appreciated.


3XXHqJx.png


Ruby:
def bn = BarNumber();
def na = Double.NaN;

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;

def hibn = HighestAll(bn);
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

def priceH = high;
def priceL = low;
def priceC = close;

def o = open;
def h = high;
def l = low;
def c = close;

input percentageReversal = 3;
input absoluteReversal = 0.0;
input atrLength = 2;
input atrReversal = 2;
input tickReversal = 0;

Assert(percentageReversal >= 0, "'percentage reversal' must not be negative: " + percentageReversal);
Assert(absoluteReversal >= 0, "'absolute reversal' must not be negative: " + absoluteReversal);
Assert(atrReversal >= 0, "'atr reversal' must not be negative: " + atrReversal);
Assert(tickReversal >= 0, "'ticks' must not be negative: " + tickReversal);
Assert(percentageReversal != 0 or absoluteReversal != 0 or atrReversal != 0 or tickReversal != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def absReversal;
if (absoluteReversal != 0) {
    absReversal = absoluteReversal;
} else {
    absReversal =  tickReversal * TickSize();
}

def hlPivot;
if (atrReversal != 0) {
    hlPivot = percentageReversal / 100 + WildersAverage(TrueRange(high, close, low), atrLength) / close * atrReversal;
} else {
    hlPivot = percentageReversal / 100;
}


def state = {default init, undefined, uptrend, downtrend};
def maxPriceH;
def minPriceL;
def newMax;
def newMin;
def prevMaxH = GetValue(maxPriceH, 1);
def prevMinL = GetValue(minPriceL, 1);

if GetValue(state, 1) == GetValue(state.init, 0) {
    maxPriceH = priceH;
    minPriceL = priceL;
    newMax = yes;
    newMin = yes;
    state = state.undefined;
} else if GetValue(state, 1) == GetValue(state.undefined, 0) {
    if priceH >= prevMaxH {
        state = state.uptrend;
        maxPriceH = priceH;
        minPriceL = prevMinL;
        newMax = yes;
        newMin = no;
    } else if priceL <= prevMinL {
        state = state.downtrend;
        maxPriceH = prevMaxH;
        minPriceL = priceL;
        newMax = no;
        newMin = yes;
    } else {
        state = state.undefined;
        maxPriceH = prevMaxH;
        minPriceL = prevMinL;
        newMax = no;
        newMin = no;
    }
} else if GetValue(state, 1) == GetValue(state.uptrend, 0) {
    if priceL <= prevMaxH - prevMaxH * hlPivot - absReversal {
        state = state.downtrend;
        maxPriceH = prevMaxH;
        minPriceL = priceL;
        newMax = no;
        newMin = yes;
    } else {
        state = state.uptrend;
        if (priceH >= prevMaxH) {
            maxPriceH = priceH;
            newMax = yes;
        } else {
            maxPriceH = prevMaxH;
            newMax = no;
        }
        minPriceL = prevMinL;
        newMin = no;
    }
} else {
    if priceH >= prevMinL + prevMinL * hlPivot + absReversal {
        state = state.uptrend;
        maxPriceH = priceH;
        minPriceL = prevMinL;
        newMax = yes;
        newMin = no;
    } else {
        state = state.downtrend;
        maxPriceH = prevMaxH;
        newMax = no;
        if (priceL <= prevMinL) {
            minPriceL = priceL;
            newMin = yes;
        } else {
            minPriceL = prevMinL;
            newMin = no;
        }
    }
}



def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(priceH), 0, barNumber));
def newState = GetValue(state, 0) != GetValue(state, 1);
def offset = barCount - barNumber + 1;
def highPoint = state == state.uptrend and priceH == maxPriceH;
def lowPoint = state == state.downtrend and priceL == minPriceL;

def lastH;
if highPoint and offset > 1 {
    lastH = fold iH = 1 to offset with tH = priceH while !IsNaN(tH) and !GetValue(newState, -iH) do if GetValue(newMax, -iH) or iH == offset - 1 and GetValue(priceH, -iH) == tH then Double.NaN else tH;
} else {
    lastH = Double.NaN;
}


def lastL;
if lowPoint and offset > 1 {
    lastL = fold iL = 1 to offset with tL = priceL while !IsNaN(tL) and !GetValue(newState, -iL) do if GetValue(newMin, -iL) or iL == offset - 1 and GetValue(priceL, -iL) == tL then Double.NaN else tL;
} else {
    lastL = Double.NaN;
}


plot ZZ;
if barNumber == 1 {
    ZZ = fold iF = 1 to offset with tP = Double.NaN while IsNaN(tP) do if GetValue(state, -iF) == GetValue(state.uptrend, 0) then priceL else if GetValue(state, -iF) == GetValue(state.downtrend, 0) then priceH else Double.NaN;
} else if barNumber == barCount {
    ZZ = if highPoint or state == state.downtrend and priceL > minPriceL then priceH else if lowPoint or state == state.uptrend and priceH < maxPriceH then priceL else Double.NaN;
} else {
    ZZ = if !IsNaN(lastH) then lastH else if !IsNaN(lastL) then lastL else Double.NaN;
}
ZZ.SetDefaultColor(GetColor(1));
ZZ.EnableApproximation();


input toggle = yes;
input reversalamount = 8.0;



def chg = close - GetValue(zz, 1);
def isUp = chg >= 0;
def isdn = chg <= 0;
def isConf = AbsValue(chg) >= reversalamount or (IsNaN(GetValue(ZZ, 1)) and GetValue(isConf, 1));


ZZ.DefineColor("Up Trend", Color.UPTICK);
ZZ.DefineColor("Down Trend", Color.DOWNTICK);
ZZ.DefineColor("Undefined", Color.DARK_ORANGE);
ZZ.AssignValueColor(if !isConf then ZZ.Color("Undefined") else if isUp then ZZ.Color("Up Trend") else ZZ.Color("Down Trend"));
DefineGlobalColor("Unconfirmed", Color.DARK_ORANGE);
DefineGlobalColor("Up", Color.UPTICK);
DefineGlobalColor("Down", Color.DOWNTICK);


#Upper Band
input WMA = 5;
def wma_wma_c  = close  + wma;
def wma_bn = BarNumber();
def wma_na = Double.NaN;

def wma_o = open + wma;
def wma_h = high+ wma;
def wma_l = low + wma ;
def wma_c = close + wma;

def wma_lastbn = HighestAll(If(IsNaN(wma_c ), 0, wma_bn));
def wma_lastbar = if (wma_bn == wma_lastbn) then 1 else 0;

def wma_hibn = HighestAll(wma_bn);
#def wma_lastbar = !isnan(wma_wma_c [0]) and isnan(wma_wma_c [-1]);

def wma_priceH = high + wma;
def wma_priceL = low  + wma;
def wma_priceC = close  + wma;


input wma_percentageReversal= 3;
input wma_absoluteReversal = 0.0;
input wma_atrLength  = 2;
input wma_atrReversal  = 2;
input wma_tickReversal  = 0;

Assert(wma_percentageReversal>= 0, "'percentage reversal' must not be negative: " + wma_percentageReversal);
Assert(wma_absoluteReversal >= 0, "'absolute reversal' must not be negative: " + wma_absoluteReversal);
Assert(wma_atrReversal  >= 0, "'atr reversal' must not be negative: " + wma_atrReversal );
Assert(wma_tickReversal  >= 0, "'ticks' must not be negative: " + wma_tickReversal );
Assert(wma_percentageReversal!= 0 or wma_absoluteReversal != 0 or wma_atrReversal  != 0 or wma_tickReversal  != 0, "Either 'percentage reversal' or 'absolute reversal' or 'atr reversal' or 'tick reversal' must not be zero");

def wma_absReversal ;
if (wma_absoluteReversal != 0) {
    wma_absReversal  = absoluteReversal;
} else {
    wma_absReversal  =  wma_tickReversal  * TickSize();
}

def wma_hlPivot  ;
if (wma_atrReversal  != 0) {
    wma_hlPivot   = wma_percentageReversal/ 100 + WildersAverage(TrueRange(wma_h , wma_c , wma_l ), wma_atrLength ) / wma_c  * wma_atrReversal ;
} else {
    wma_hlPivot   = wma_percentageReversal/ 100;
}


def wma_state = {default init, undefined, uptrend, downtrend};
def wma_maxPriceH;
def wma_minPriceL;
def wma_newMax;
def wma_newMin;
def wma_prevMaxH = GetValue(wma_maxPriceH, 1);
def wma_prevMinL  = GetValue(wma_minPriceL, 1);

if GetValue(wma_state, 1) == GetValue(wma_state.init, 0) {
    wma_maxPriceH = wma_priceH;
    wma_minPriceL = wma_priceL;
    wma_newMax = yes;
    wma_newMin = yes;
    wma_state = wma_state.undefined;
} else if GetValue(wma_state, 1) == GetValue(wma_state.undefined, 0) {
    if wma_priceH >= wma_prevMaxH {
        wma_state = wma_state.uptrend;
        wma_maxPriceH = wma_priceH;
        wma_minPriceL = wma_prevMinL ;
        wma_newMax = yes;
        wma_newMin = no;
    } else if wma_priceL <= wma_prevMinL  {
        wma_state = wma_state.downtrend;
        wma_maxPriceH = prevMaxH;
        wma_minPriceL = wma_priceL;
        wma_newMax = no;
        wma_newMin = yes;
    } else {
        wma_state = wma_state.undefined;
        wma_maxPriceH = prevMaxH;
        wma_minPriceL = wma_prevMinL ;
        wma_newMax = no;
        wma_newMin = no;
    }
} else if GetValue(wma_state, 1) == GetValue(wma_state.uptrend, 0) {
    if wma_priceL <= wma_prevMaxH - wma_prevMaxH * wma_hlPivot   - wma_absReversal  {
        wma_state = wma_state.downtrend;
        wma_maxPriceH = prevMaxH;
        wma_minPriceL = wma_priceL;
        wma_newMax = no;
        wma_newMin = yes;
    } else {
        wma_state = wma_state.uptrend;
        if (wma_priceH >= prevMaxH) {
            wma_maxPriceH = wma_priceH;
            wma_newMax = yes;
        } else {
            wma_maxPriceH = prevMaxH;
            wma_newMax = no;
        }
        wma_minPriceL = wma_prevMinL ;
        wma_newMin = no;
    }
} else {
    if wma_priceH >= wma_prevMinL  + wma_prevMinL  * wma_hlPivot   + wma_absReversal  {
        wma_state = wma_state.uptrend;
        wma_maxPriceH = wma_priceH;
        wma_minPriceL = wma_prevMinL ;
        wma_newMax = yes;
        wma_newMin = no;
    } else {
        wma_state = wma_state.downtrend;
        wma_maxPriceH = prevMaxH;
        wma_newMax = no;
        if (wma_priceL <= wma_prevMinL ) {
            wma_minPriceL = wma_priceL;
            wma_newMin = yes;
        } else {
            wma_minPriceL = wma_prevMinL ;
            wma_newMin = no;
        }
    }
}



def wma_barNumber  = BarNumber();
def wma_barCount  = HighestAll(If(IsNaN(wma_priceH), 0, wma_barNumber ));
def wma_newState  = GetValue(wma_state, 0) != GetValue(wma_state, 1);
def wma_offset  = wma_barCount  - wma_barNumber  + 1;
def wma_highPoint = wma_state == wma_state.uptrend and wma_priceH == wma_maxPriceH;
def wma_lowPoint = wma_state == wma_state.downtrend and wma_priceL == wma_minPriceL;

def wma_lastH ;
if wma_highPoint and wma_offset  > 1 {
    wma_lastH  = fold aH = 1 to wma_offset  with kH = wma_priceH while !IsNaN(kH) and !GetValue(wma_newState , -aH) do if GetValue(wma_newMax, -aH) or aH == wma_offset  - 1 and GetValue(wma_priceH, -aH) == kH then Double.NaN else kH;
} else {
    wma_lastH  = Double.NaN;
}


def wma_lastL ;
if wma_lowPoint and wma_offset  > 1 {
    wma_lastL  = fold xL = 1 to wma_offset  with gL = wma_priceL while !IsNaN(gL) and !GetValue(wma_newState , -xL) do if GetValue(wma_newMin, -xL) or xL == wma_offset  - 1 and GetValue(wma_priceL, -xL) == gL then Double.NaN else gL;
} else {
    wma_lastL  = Double.NaN;
}


plot wma_ZZ;
if barNumber == 1 {
    wma_ZZ = fold dF = 1 to wma_offset with fP = Double.NaN while IsNaN(fP) do if GetValue(state, -dF) == GetValue(wma_state.uptrend, 0) then wma_priceL else if GetValue(wma_state, -dF) == GetValue(wma_state.downtrend, 0) then wma_priceH else Double.NaN;
} else if barNumber == wma_barCount {
    wma_ZZ = if wma_highPoint or wma_state == wma_state.downtrend and wma_priceL > wma_minPriceL then wma_priceH else if wma_lowPoint or wma_state == wma_state.uptrend and wma_priceH < wma_maxPriceH then wma_priceL else Double.NaN;
} else {
    wma_ZZ = if !IsNaN(wma_lastH) then wma_lastH else if !IsNaN(wma_lastL) then wma_lastL else Double.NaN;
}
wma_ZZ.SetDefaultColor(GetColor(1));
wma_ZZ.EnableApproximation();

sorry, i don't understand what you are trying to do.
i don't understand why you have all that code in the 2nd half, after #Upper Band, why all that wma stuff?

if you want band lines, then add and subtract from the original signal.
add this to the end of the study.

Code:
input vert = 4.0;
plot z1 = zz + vert;
Z1.SetDefaultColor(color.yellow);
Z1.EnableApproximation();

plot z2 = zz - vert;
Z2.SetDefaultColor(color.yellow);
Z2.EnableApproximation();

qgQbhzz.jpg
 
@halcyonguy Still struggling with the vertical line. I'm trying to figure the specific barnumber or value to use for start and end point for each upper and lower band pivots.

check for a valid number, with zz.
the plot is mostly na, and a valid number on peaks and valleys.

def na = double.nan;
def vlinetop = if !isnan(zz) then z1 else na;
def vlinebot = if !isnan(zz) then z2 else na;

AddChart(vlinetop, vlinebot, 0, 0, ChartType.BAR, Color.YELLOW);
 
check for a valid number, with zz.
the plot is mostly na, and a valid number on peaks and valleys.

def na = double.nan;
def vlinetop = if !isnan(zz) then z1 else na;
def vlinebot = if !isnan(zz) then z2 else na;

AddChart(vlinetop, vlinebot, 0, 0, ChartType.BAR, Color.YELLOW);
Try replacing the above with

Code:
def na = double.nan;
def vlinetop = if !isnan(zz) then z1 else na;
def vlinebot = if !isnan(zz) then z2 else na;

AddChart(vlinetop, vlinebot, na, na, ChartType.BAR, Color.YELLOW);
 
@SleepyZ The reason for me asking is I'm trying to get the angle for each zigag. Below is the script but the angle are not correct.

def start_bn = if !IsNaN(ZZ) then barnumber() else double.NaN;
addlabel(1, start_bn);
def end_bn = if !IsNaN(ZZ[1]) then barnumber() else double.NaN;
addlabel(1, end_bn);

def bar = BarNumber();
def y = !IsNaN(ZZ);
def x1 = start_bn; # starting bar of slope calculation
def x2 = end_bn; # ending bar of slop calculation
def y1_r = if bar == x1 then y else y1_r[1];
def y2_r = if bar == x2 then l else y2_r[1];

def "y-axis" = y1_r - y2_r;
def "x-axis" = (x1 - (x2));
def mx = "y-axis" / "x-axis";
def angle = AbsValue(Round(ATan(mx) * 180 / Double.Pi, 0));
 
Last edited:
@SleepyZ The reason for me asking is I'm trying to get the angle for each zigag. Below is the script but the angle are not correct.

def start_bn = if !IsNaN(ZZ) then barnumber() else double.NaN;
addlabel(1, start_bn);
def end_bn = if !IsNaN(ZZ[1]) then barnumber() else double.NaN;
addlabel(1, end_bn);

def bar = BarNumber();
def y = !IsNaN(ZZ);
def x1 = start_bn; # starting bar of slope calculation
def x2 = end_bn; # ending bar of slop calculation
def y1_r = if bar == x1 then y else y1_r[1];
def y2_r = if bar == x2 then l else y2_r[1];

def "y-axis" = y1_r - y2_r;
def "x-axis" = (x1 - (x2));
def mx = "y-axis" / "x-axis";
def angle = AbsValue(Round(ATan(mx) * 180 / Double.Pi, 0));

See if this helps

Screenshot 2023-06-29 074334.png
Code:
def start_bn = if !IsNaN(ZZ) then barnumber() else start_bn[1];
addlabel(1, start_bn);
def end_bn = if start_bn!=start_bn[1] then start_bn[1] else end_bn[1];
addlabel(1, end_bn);

def bar = BarNumber();
def y = !IsNaN(ZZ);
def x1 = start_bn; # starting bar of slope calculation
def x2 = end_bn; # ending bar of slop calculation
def y1_r = if bar == x1 then y else y1_r[1];
def y2_r = if bar == x2 then l else y2_r[1];

def "y-axis" = y1_r - y2_r;
def "x-axis" = (x1 - (x2));
def mx = "y-axis" / "x-axis";
def angle = AbsValue(Round(ATan(mx) * 180 / Double.Pi, 0));
addlabel(1,angle);
 
@SleepyZ Yes but it is based on user input I was looking for something automated that plot the upper trendline and lower trendline.


ooh , i think i understand. you want trend lines to automatically be drawn...
i was hung up on the zigzag part.

why do you want lines on every bar? why not just the last segment?
an auto trend line study
https://usethinkscript.com/threads/auto-trend-lines-indicator-for-thinkorswim.31/


every study has constants, parameters , set in the code. there is no such thing as automated.
you need to think about what defines these lines you want.

does the top line start from a specific bar?
does the top line have to start or stop on a zigzag peak?
..or can they connect to any 2 peaks between zigzags?
do they have to connect to 2 highs? 3 or more highs? ( 2, 3 would be a parameter)
...or be within x% of the highs? ( x% would be a parameter)

the human eye can look at a chart and determine where a trend line should go, that passes above a group of bars.
but to do that with math is complicated. on every bar, you would have to run loops to look at future bars, and somehow determine which combinations are close to the highs. also would have to determine when to stop the line. then compare those combinations to determine which is the best fit. it probably will get bogged down by too many loops.


idea, maybe having linear regression lines anchored to zigzag peaks and valleys would be close?
a line that passes through the middle of a trend.


examples, linear regression studies
https://usethinkscript.com/threads/auto-trend-lines-indicator-for-thinkorswim.31/

https://usethinkscript.com/threads/...on-from-the-centerline-for-thinkorswim.10726/
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
423 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top