#Combined ZigZagSign and Donchian Channel Signals-----------------------------------
#ZigZag Code Used-------------------------------------------------------------------
## START CODE
## ZigZagSign TOMO modification, v0.2 written by Linus @Thinkscripter Lounge adapted from Thinkorswim ZigZagSign Script
input price = close;
input priceH = high; # swing high
input priceL = low; # swing low
input ATRreversalfactor = 3.2;
def ATR = reference ATR(length = 5);
def reversalAmount = ATRreversalfactor * ATR;
input showlines = yes;
input displace = 1;
input showBubbleschange = yes;
def X = Highest(open, 12);
def lastbar = HighestAll(if IsNaN(close) then 0 else BarNumber());
plot condition = if BarNumber() <= lastbar - 19 and BarNumber() >= lastbar - 20 then GetValue(X, BarNumber() - lastbar) else Double.NaN;
AddChartBubble(BarNumber() == lastbar - 19, condition, " ", Color.YELLOW, 0);
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;
#Higher/Lower/Equal High, Higher/Lower/Equal Low
def xxhigh = if zzSave == priceH then Round(high, 2) else Round(xxhigh[1], 2);
def chghigh = Round(Round(high, 2) - Round(xxhigh[1], 2), 2);
def xxlow = if zzSave == priceL then Round(low, 2) else Round(xxlow[1], 2);
def chglow = Round(Round(low, 2) - Round(xxlow[1], 2), 2);
rec isConf = AbsValue(chg) >= reversalAmount or (IsNaN(GetValue("ZZ$", 1)) and GetValue(isConf, 1));
"ZZ$".EnableApproximation();
"ZZ$".DefineColor("Up Trend", Color.UPTICK);
"ZZ$".DefineColor("Down Trend", Color.DOWNTICK);
"ZZ$".DefineColor("Undefined", Color.WHITE);
"ZZ$".AssignValueColor(if !isConf then "ZZ$".Color("Undefined" ) else if isUp then "ZZ$".Color("Up Trend" ) else "ZZ$".Color("Down Trend" ));
DefineGlobalColor("Unconfirmed", Color.WHITE);
DefineGlobalColor("Up", Color.UPTICK);
DefineGlobalColor("Down", Color.DOWNTICK);
#Donchian Channel Code Used------------------------------------------------------------------------
#Name: DonchianChannel
#Programmed By: Chris Ball ([email protected]) on 10/23/08
#Posted At: http://chartingwithchris.blogspot.com
#Description: This is a channel system that is used frequently for trend trading. Google the term "turtle trader" for more information.
#Updated 9/15/21 by Stoneybucks to add upsignal when price fails to make a new Lower Low (value from the last 25 periods) in the current period compared to the previous period, and add a downsignal when when price failes to make a new Higher Higher (value from the last 25 periods) in the current period compared to the previous period. These are minimum conditions for spotting potential trend reversals.
######################################################################
##DonchianChannel
input showchannel = no;
input displace1 = 0;
input length = 25;
plot upperBand = Highest(high[-displace1 + 1], length);
plot lowerBand = Lowest(low[-displace1 + 1], length);
plot middleBand = (upperBand + lowerBand) / 2;
upperBand.SetDefaultColor(Color.WHITE);
lowerBand.SetDefaultColor(Color.WHITE);
middleBand.SetDefaultColor(Color.WHITE);
upperBand.SetHiding(!showchannel);
lowerBand.SetHiding(!showchannel);
middleBand.SetHiding(!showchannel);
#DefineScenarios - Combined ZZ and Donchian-----------------------------------------------------
def H = high;
def L = low;
def longentry = (L > L[1] and L[1] <= lowerBand[1]);
def shortentry = (H < H[1] and H[1] >= upperBand[1]);
#Arrows-----------------------------------------------------------------------------------------
plot downsignal = if upperBand == zzSave and isUp and shortentry and !longentry then high else Double.NaN;
downsignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
downsignal.SetDefaultColor(Color.RED);
downsignal.SetLineWeight(5);
plot upsignal = if lowerBand == zzSave and isUp and longentry and !shortentry then low else Double.NaN;
upsignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
upsignal.SetDefaultColor(Color.GREEN);
upsignal.SetLineWeight(5);
#Bubbles----------------------------------------------------------------------------
input bubbledisplace = 2.00;
AddChartBubble(showBubbleschange and high == downsignal, high + bubbledisplace, AsText(high) , GlobalColor("Down" ) , yes);
AddChartBubble(showBubbleschange and low == upsignal, low - bubbledisplace, AsText(low) , GlobalColor("Up" ) , no);