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.
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: