def priceH = high;
def priceL = low;
def priceC = close;
def o = open;
def h = high;
def l = low;
def c = close;
input percentageReversal = 2;
input absoluteReversal = 0.0;
input atrLength = 2;
input atrReversal = 1;
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();
#####################################################################
## Change Pct ##
#####################################################################
def chg = round((close / close[1] -1),2);
#####################################################################
## Bar lookBack ##
#####################################################################
def na = Double.NaN;
def bn = BarNumber();
input LookBack = 10;#hint LookBack: Number of bars to look back
def start = !IsNaN(close[-LookBack + 1]) and IsNaN(close[-LookBack]);
def end = !IsNaN(close[0]) and IsNaN(close[-1]);
def startbn2 = if start then bn else 0;
def startbn = HighestAll(startbn2);
def endbn = lowestall(startbn + LookBack);
def endbn2 = if end then bn else 0;
def chg_pct = if bn == 1 then 0 else if bn >= startbn and bn <= endbn then chg_pct[1] + chg else chg_pct[1];
def change = (chg_pct * 100);
addverticalline(start, " START", color.cyan);
AddVerticalLine(end, " END", Color.CYAN);
# Without subscript
def bar = BarNumber();
def y = close;
def x1 = startbn2; # starting bar of slope calculation
def x2 = endbn2; # 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" = (startbn - (endbn));
def mx = "y-axis" / "x-axis";
def angle = round(atan(mx) * 180 / double.Pi, 0);
AddLabel(1, "Chg %:" + " " + change, Color.CYAN);
addlabel(1, "y1: "+y1_r);
addlabel(1, "y2: "+y2_r);
AddLabel(1, "x1:" + " " + startbn, color.yellow);
AddLabel(1, "x2:" + " " + endbn, color.yellow);
AddLabel(1, "y-axis:" + " " + "y-axis", Color.orange);
AddLabel(1, "x-axis:" + " " + "x-axis", Color.orange);
AddLabel(1, "m:" + " " + mx, Color.orange);
AddLabel(1, "Angle:" + " " + angle+"°", Color.orange);