def price = close;
def priceH = high; # swing high
def priceL = low; # swing low
input ATRreversalfactor = 3.0;#Hint ATRreversalfactor: 3 is standard, adjust
input ATRlength = 5;#Hint ATRlength: 5 is standard, adjust to whatever
input zigzagpercent = 0.80;#LAR original is 0.2, but modified in testing
input zigzagamount = .15;
def ATR = reference ATR(length = ATRlength);
def reversalAmount = if (close * zigzagpercent / 100) > Max
(zigzagamount < ATRreversalfactor * ATR, zigzagamount) then
(close * zigzagpercent / 100) else if zigzagamount < ATRreversalfactor * ATR then
ATRreversalfactor * ATR else zigzagamount;
input showSupplyDemand = {Off, default Arrow, Pivot};
input showArrows = yes; #orignal by LAR was no
input useAlerts = no; #orignal by LAR was no
#Original TOS ZigZag code Modified by Linus
def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(price), 0, barNumber));
rec state = {default init, undefined, uptrend, downtrend};
rec minMaxPrice;
if (GetValue(state, 1) == GetValue(state.init, 0)) {
minMaxPrice = price;
state = state.undefined;
} else if (GetValue(state, 1) == GetValue(state.undefined, 0)) {
if (price <= GetValue(minMaxPrice, 1) - reversalAmount) {
state = state.downtrend;
minMaxPrice = priceL;
} else if (price >= GetValue(minMaxPrice, 1) + reversalAmount) {
state = state.uptrend;
minMaxPrice = priceH;
} else {
state = state.undefined;
minMaxPrice = GetValue(minMaxPrice, 1);
}
} else if (GetValue(state, 1) == GetValue(state.uptrend, 0)) {
if (price <= GetValue(minMaxPrice, 1) - reversalAmount) {
state = state.downtrend;
minMaxPrice = priceL;
} else {
state = state.uptrend;
minMaxPrice = Max(priceH, GetValue(minMaxPrice, 1));
}
} else {
if (price >= GetValue(minMaxPrice, 1) + reversalAmount) {
state = state.uptrend;
minMaxPrice = priceH;
} else {
state = state.downtrend;
minMaxPrice = Min(priceL, GetValue(minMaxPrice, 1));
}
}
def isCalculated = GetValue(state, 0) != GetValue(state, 1) and barNumber >= 1;
def futureDepth = barCount - barNumber;
def tmpLastPeriodBar;
if (isCalculated) {
if (futureDepth >= 1 and GetValue(state, 0) == GetValue(state, -1)) {
tmpLastPeriodBar = fold lastPeriodBarI = 2 to futureDepth + 1 with
lastPeriodBarAcc = 1
while lastPeriodBarAcc > 0
do if (GetValue(state, 0) != GetValue(state, -lastPeriodBarI))
then -lastPeriodBarAcc
else lastPeriodBarAcc + 1;
} else {
tmpLastPeriodBar = 0;
}
} else {
tmpLastPeriodBar = Double.NaN;
}
def lastPeriodBar = if (!IsNaN(tmpLastPeriodBar)) then -AbsValue
(tmpLastPeriodBar) else -futureDepth;
rec currentPriceLevel;
rec currentPoints;
if (state == state.uptrend and isCalculated) {
currentPriceLevel =
fold barWithMaxOnPeriodI = lastPeriodBar to 1 with barWithMaxOnPeriodAcc
= minMaxPrice
do Max(barWithMaxOnPeriodAcc, GetValue(minMaxPrice,
barWithMaxOnPeriodI));
currentPoints =
fold maxPointOnPeriodI = lastPeriodBar to 1 with maxPointOnPeriodAcc =
Double.NaN
while IsNaN(maxPointOnPeriodAcc)
do if (GetValue(priceH, maxPointOnPeriodI) == currentPriceLevel)
then maxPointOnPeriodI
else maxPointOnPeriodAcc;
} else if (state == state.downtrend and isCalculated) {
currentPriceLevel =
fold barWithMinOnPeriodI = lastPeriodBar to 1 with barWithMinOnPeriodAcc
= minMaxPrice
do Min(barWithMinOnPeriodAcc, GetValue(minMaxPrice,
barWithMinOnPeriodI));
currentPoints =
fold minPointOnPeriodI = lastPeriodBar to 1 with minPointOnPeriodAcc =
Double.NaN
while IsNaN(minPointOnPeriodAcc)
do if (GetValue(priceL, minPointOnPeriodI) == currentPriceLevel)
then minPointOnPeriodI
else minPointOnPeriodAcc;
} else if (!isCalculated and (state == state.uptrend or state ==
state.downtrend)) {
currentPriceLevel = GetValue(currentPriceLevel, 1);
currentPoints = GetValue(currentPoints, 1) + 1;
} else {
currentPoints = 1;
currentPriceLevel = GetValue(price, currentPoints);
}
plot "ZZ$" = if (barNumber == barCount or barNumber == 1) then if state ==
state.uptrend then priceH else priceL else if (currentPoints == 0) then
currentPriceLevel else Double.NaN;
rec zzSave = if !IsNaN("ZZ$") then if (barNumber == barCount or barNumber == 1)
then if IsNaN(barNumber[-1]) and state == state.uptrend then priceH else priceL
else currentPriceLevel else GetValue(zzSave, 1);
def chg = (if barNumber == barCount and currentPoints < 0 then priceH else if
barNumber == barCount and currentPoints > 0 then priceL else currentPriceLevel)
- GetValue(zzSave, 1);
def isUp = chg >= 0;
rec isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue("ZZ$", 1)) and
GetValue(isConf, 1));
"ZZ$".EnableApproximation();
"ZZ$".DefineColor("Up Trend", Color.GREEN);
"ZZ$".DefineColor("Down Trend", Color.RED);
"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"));
"ZZ$".SetLineWeight(2);
DefineGlobalColor("Unconfirmed", Color.DARK_ORANGE);
DefineGlobalColor("Up", Color.GREEN);
DefineGlobalColor("Down", Color.RED);
#Arrows
def zzL = if !IsNaN("ZZ$") and state == state.downtrend then priceL else
GetValue(zzL, 1);
def zzH = if !IsNaN("ZZ$") and state == state.uptrend then priceH else GetValue
(zzH, 1);
def dir = CompoundValue(1, if zzL != zzL[1] then 1 else if zzH != zzH[1] then -1
else dir[1], 0);
def signal = CompoundValue(1,
if dir > 0 and low > zzL then
if signal[1] <= 0 then 1 else signal[1]
else if dir < 0 and high < zzH then
if signal[1] >= 0 then -1 else signal[1]
else signal[1]
, 0);
plot U1 = showArrows and signal > 0 and signal[1] <= 0;
U1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
U1.SetDefaultColor(Color.GREEN);
U1.SetLineWeight(4);
plot D1 = showArrows and signal < 0 and signal[1] >= 0;
D1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
D1.SetDefaultColor(Color.RED);
D1.SetLineWeight(4);
Alert(useAlerts and U1, "ZIG-UP", Alert.BAR, Sound.Bell);
Alert(useAlerts and D1, "ZAG-DOWN", Alert.BAR, Sound.Chimes);
#Supply Demand Areas
def idx = if showSupplyDemand == showSupplyDemand.Pivot then 1 else 0;
def rLow;
def rHigh;
if BarNumber() == 1 {
rLow = Double.NaN;
rHigh = Double.NaN;
} else if signal crosses 0 {
rLow = low[idx];
rHigh = high[idx];
} else {
rLow = rLow[1];
rHigh = rHigh[1];
}
plot HighLine = if showSupplyDemand and !IsNaN(close) then rHigh else
Double.NaN;
HighLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
HighLine.AssignValueColor(if signal > 0 then Color.GREEN else Color.RED);
plot LowLine = if showSupplyDemand and !IsNaN(close) then rLow else Double.NaN;
LowLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
LowLine.AssignValueColor(if signal > 0 then Color.GREEN else Color.RED);
def hlUp = if signal > 0 then HighLine else Double.NaN;
def hlDn = if signal < 0 then HighLine else Double.NaN;
AddCloud(hlUp, LowLine, Color.GREEN, Color.GREEN);
AddCloud(hlDn, LowLine, Color.RED, Color.RED);
def zzsave1 = if zzSave != zzSave[1] then zzSave[1] else zzsave1[1];
def zzsave2 = if zzsave1 != zzsave1[1] then zzsave1[1] else zzsave2[1];
def lastbar = if !IsNaN(close) and IsNaN(close[-1]) then BarNumber() else Double.NaN;
input debug = no;
AddLabel(debug, zzSave + " " + zzsave1 + " " + zzsave2, Color.WHITE);
AddChartBubble(BarNumber() != HighestAll(lastbar) and priceH == "ZZ$", high, if zzSave > zzsave2 then "HH" else "LH", if zzSave > zzsave2 then Color.GREEN else Color.RED);
AddChartBubble(BarNumber() != HighestAll(lastbar) and priceL == "ZZ$", low, if zzSave > zzsave2 then "HL" else "LL", if zzSave > zzsave2 then Color.GREEN else Color.RED, no);
## END CODE