Breadth Thrust Indicator for ThinkorSwim

Art

Member
Hi community, does anyone have/familiar with Whaley Breadth Thrust indicator for ThinkorSwim?

I found Zweig's market breadth indicator but I'm not sure whether that would be the same thing.

Code:
#Developed by Dr. Martin Zweig, the Breadth Thrust Indicator measures market momentum. The Breadth Thrust is calculated by dividing a 10-day exponential moving average of the number of advancing issues, by the number of advancing plus declining issues.

#A "Breadth Thrust" occurs when, during a 10-day period, the Breadth Thrust indicator rises from below 40% to above 61.5%. A "Thrust" indicates that the stock market has rapidly changed from an oversold condition to one of strength, but has not yet become overbought. According to Dr. Zweig, there have only been fourteen Breadth Thrusts since 1945. The average gain following these fourteen Thrusts was 24.6% in an average time-frame of eleven months. Dr. Zweig also points out that most bull markets begin with a Breadth Thrust. A weekly chart is best for this indicator.

declare lower;

plot zw = ExpAverage(data = close("$advn"), length = 10 ) /( ExpAverage(data=close("$advn"), length=10) + ExpAverage(data=close("$decn"), length = 10));
plot forty = 0.40;
forty.SetDefaultColor(Color.RED);
plot sixfifteen = 0.615;
sixfifteen.SetDefaultColor(Color.Yellow);
 

SilverSurferAI

New member
2019 Donor
I recently became interested in breadth thrusts deemer, desmond, whaley, & now zweig. I found this link on twitter.

Breakaway Momentum (Breadth Thrust) [Upper Study]

Code:
# Breakaway Momentum (Breadth Thrust)
# defined: 10d sma advances > 1.97 x 10d sma declines.
# article: https://www.walterdeemer.com/bam.htm
#
# Desmond Reversals
# defined: 1 or more 90% downvolume day(s) [panic selling] followed by 90% upvolume day or 2 80+% upvolume days [panic buying]
# article: https://data.bloomberglp.com/assets/sites/2/2014/01/Desmond-report.pdf
#
# Whaley Thrusts
# defined:
#    - breath thursts (ADT): 5day cumulative advance/total issues crossing above 75 [whaley1] or crossing below 25 [whaley2]
#    - volume thrusts (UDT): 5day cumulative upvolume/total volume crossing above 77.8 [whaley3] or crossing below 16.4 [whaley4]
#    - sprice thrusts (SPT): 5day cumulative SP500 price % change of +10.05% [whaley5] or -13.85% [whaley6]
# article: http://docs.mta.org/pdfs/dowaward-2010.pdf
#
# Zweig Thrust
# defined: 10d ema advances crosses above 4.0 and 6.1 within 10 trading days
# article: https://www.seeitmarket.com/did-zweig-breadth-thrust-indicator-flash-buy-signal-for-stock-market/
# sourcecode: @ClarenceCarr
#


declare upper;

input thrustType = {default "Breakaway", "Desmond", "Whaley|ADT", "Whaley|UDT", "Whaley|SPT", "Zweig"};
input exchange = {default NYSE, NASDAQ, SnP500, Nasdaq100, Russell2000, Dow30, AMEX};
input signalType = {"Off", default "Bubble", "VerticalLine"};
input signalLabel = {"Date", "Type", default "Type|Date"};
input showLabels = no;
input showClouds = yes;
input tradeDays = 60;
input showExtLine = yes;


def advanceI;
def declineI;
def advanceV;
def declineV;
switch (exchange) {
case NYSE:
    advanceI = close("$ADVN");
    declineI = close("$DECN");
    advanceV = close("$UVOL");
    declineV = close("$DVOL");
case NASDAQ:
    advanceI = close("$ADVN/Q");
    declineI = close("$DECN/Q");
    advanceV = close("$UVOL/Q");
    declineV = close("$DVOL/Q");
case SnP500:
    advanceI = close("$ADVSP");
    declineI = close("$DECLSP");
    advanceV = close("$UVOLSP");
    declineV = close("$DVOLSP");
case Nasdaq100:
    advanceI = close("$ADVND");
    declineI = close("$DECLND");
    advanceV = close("$UVOLND");
    declineV = close("$DVOLND");
case Russell2000:
    advanceI = close("$ADVRL");
    declineI = close("$DECLRL");
    advanceV = close("$UVOLRL");
    declineV = close("$DVOLRL");
case Dow30:
    advanceI = close("$ADVI");
    declineI = close("$DECLI");
    advanceV = close("$UVOLI");
    declineV = close("$DVOLI");
case AMEX:
    advanceI = close("$ADVA");
    declineI = close("$DECA");
    advanceV = close("$UVOLUS");
    declineV = close("$DVOLUS");
}

def aCount = if isnan(advanceI) then aCount[1] + 1 else 0;
def dCount = if isnan(declineI) then dCount[1] + 1 else 0;
def addI = if isnan(advanceI) then GetValue(advanceI, aCount) else advanceI;
def decI = if isnan(declineI) then GetValue(declineI, dCount) else declineI;
def totI = addI+decI;
def addIR = addI/totI;
def decIR = decI/totI;

def aVCount = if isnan(advanceV) then aVCount[1] + 1 else 0;
def dVCount = if isnan(declineV) then dVCount[1] + 1 else 0;
def addV = if isnan(advanceV) then GetValue(advanceV, aVCount) else advanceV;
def decV = if isnan(declineV) then GetValue(declineV, dVCount) else declineV;
def totV = addV + decV;
def addVR = addV/totV;
def decVR = decV/totV;

def SPChg = 100 * (close("SPX") / close("SPX")[1] - 1);


def advnDecl;
def mean;
def weak;
def thrust;
switch (thrustType){
case "Breakaway":
    advnDecl = round(average(addIR,10) - 1.97*average(decIR,10),2);
    mean = 0;
    weak = Double.NaN;
    thrust = Double.NaN;
case "Desmond":
    advnDecl = if addVR > decVR then round(addVR*100,2) else round(-decVR*100,2);
    mean = 0;
    weak = -80;
    thrust = 80;
case "Whaley|ADT":
    advnDecl = round(sum(addI,5)/sum(totI,5),3)*100;
    mean = 50;
    weak = 25;
    thrust = 75;
case "Whaley|UDT":
    advnDecl = round(sum(addV,5)/sum(totV,5),3)*100;
    mean = 50;
    weak = 16.4;
    thrust = 77.8;
case "Whaley|SPT":
    advnDecl = round(sum(SPChg,5),2);
    mean = 0;
    weak = -13.85;
    thrust = 10.05;
case "Zweig":
    advnDecl = round(ExpAverage(addIR,10),3);
    mean = 0.5;
    weak = 0.4;
    thrust = 0.61;
}

# -- plots
def ADExpAvg = if IsNaN(close) then double.nan else if IsNaN(advnDecl) then mean else advnDecl;


# -- signals
# breakaway signal
def breakaway = average(addIR,10) crosses above 1.97*average(decIR,10);
def breakaway2 = average(addIR,20) crosses above 1.72*average(decIR,20); # jan 2019 addendum
# desmond
def desmond1 = advnDecl[1]<=-90 and advnDecl>=90;
def desmond2 = advnDecl[2]<=-90 and advnDecl[1]>=80 and advnDecl>=80;
# whaley signal
def whaley1 = advnDecl crosses above thrust; #whaley1,3,&5
def whaley2 = advnDecl crosses below weak; #whaley2,4,&6
# zweig signal
def maxDays = 10;
def zCount = if advnDecl >= Weak then zCount[1] + 1 else 0;
def zweig = advnDecl crosses above Thrust and zCount <= maxDays;

def signal =
if thrustType == thrustType."breakaway" then (breakaway or breakaway2) else
if thrustType == thrustType."desmond" then (desmond1 or desmond2) else
if thrustType == thrustType."whaley|ADT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|UDT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|SPT" then (whaley1 or whaley2) else
if thrustType == thrustType."Zweig" then Zweig else
double.nan;

AddVerticalLine(signalType == signalType."VerticalLine" and signal,
(if signalLabel != signalLabel."Date" then
    " " + thrustType + ", " else ", ")
+
 (if GetMonth()==1 then " Jan " else
 if GetMonth()==2 then " Feb " else
 if GetMonth()==3 then " Mar " else
 if GetMonth()==4 then " Apr " else
 if GetMonth()==5 then " May " else
 if GetMonth()==6 then " Jun " else
 if GetMonth()==7 then " Jul " else
 if GetMonth()==8 then " Aug " else
 if GetMonth()==9 then " Sep " else
 if GetMonth()==10 then " Oct " else
 if GetMonth()==11 then " Nov " else
 " Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
+ (if thrustType == thrustType."Zweig" then " (" + zCount + " days)" else " ")
, globalcolor("signal"), 1);

Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Date" and signal, low, thrustType + (if breakaway2 then "2" else ""), globalcolor("signal"), 0);
Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Type" and signal, low,
 (if GetMonth()==1 then "Jan " else
 if GetMonth()==2 then "Feb " else
 if GetMonth()==3 then "Mar " else
 if GetMonth()==4 then "Apr " else
 if GetMonth()==5 then "May " else
 if GetMonth()==6 then "Jun " else
 if GetMonth()==7 then "Jul " else
 if GetMonth()==8 then "Aug " else
 if GetMonth()==9 then "Sep " else
 if GetMonth()==10 then "Oct " else
 if GetMonth()==11 then "Nov " else
 "Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
, color.light_gray, 0);


# -- clouds
def cond1 = if isnan(close) then double.nan else if signal or signal[1] then double.positive_INFINITY else Double.NaN;
def cond2 = if !showClouds then double.nan else double.negative_infinity;
AddCloud(cond1, cond2, globalcolor("signal"));
# zweig signal window
def ccross = advnDecl crosses above weak;
def ccloud = Sum(ccross, maxdays);
def value3 = if ccloud then double.positive_INFINITY else Double.NaN;
#AddCloud(if thrustType != thrustType."Zweig" then double.nan else value3, value2, color.light_gray);

# -- trade window
# sourcecode: @Pipsinger, bacontrading.com
Rec SignalBar = if barnumber() == 1 then double.nan else CompoundValue(1,if Signal then 0 else SignalBar[1] + 1,0);
def cond3 = if SignalBar <= tradeDays then double.positive_INFINITY else double.nan;
AddCloud(cond3, cond2, color.light_gray);


# -- thrust candles
# sourcecode: https://funwiththinkscript.com/adding-space-between-candles/
def o = open;
def h = high;
def l = low;
def c = close;

# up candles
def UpO;
def UpH;
def UpL;
def UpC;
if o <= c and signal
then {
    UpO = o;
    UpH = h;
    UpL = l;
    UpC = c;
} else {
    UpO = Double.NaN;
    UpH = Double.NaN;
    UpL = Double.NaN;
    UpC = Double.NaN;
}
AddChart(high = UpH, low = UpL, open = UpC, close = UpO, type = ChartType.CANDLE, growcolor = globalcolor("signal"));
AddChart(high = UpH, low = UpL, open = UpO, close = UpC, type = ChartType.CANDLE, growcolor = globalcolor("candlebody"));

# down candles
def DnO;
def DnH;
def DnL;
def DnC;
if o > c and signal
then {
    DnO = o;
    DnH = h;
    DnL = l;
    DnC = c;
} else {
    DnO = Double.NaN;
    DnH = Double.NaN;
    DnL = Double.NaN;
    DnC = Double.NaN;
}
AddChart(high = DnH, low = DnL, open = DnO, close = DnC, type = ChartType.CANDLE, growcolor = globalcolor("signal"));
AddChart(high = DnH, low = DnL, open = DnC, close = DnO, type = ChartType.CANDLE, growcolor = globalcolor("candlebody"));


# -- colors
defineglobalcolor("average", CreateColor(8,65,93)); #darker blue
#defineglobalcolor("average", CreateColor(0,102,153)); #blue
defineglobalcolor("candlebody", createcolor(25,25,25));
defineglobalcolor("signal", color.dark_orange);
defineglobalcolor("extLine", color.light_gray);


# -- labels
AddLabel(showLabels, " " + thrustType + " ", globalcolor("average"));
AddLabel(showLabels, " " + (if thrustType == thrustType."whaley|SPT" then "SnP500" else exchange) + " ", globalcolor("average"));

# breakaway labels
def ADRI =
if addI == 0 then 0 else
if decI == 0 then 0 else
if addI > decI then round(addI/decI,1) else round(-decI/addI, 1);
def ADRV =
if addV == 0 then 0 else
if decV == 0 then 0 else
if addV > decV then round(addV/decV,1) else round(-decV/addV, 1);

AddLabel(showLabels and thrustType == thrustType."breakaway",
if ADRI == 0 then " Iss: TILT " else
" Iss: " + ADRI + ":1 ", if addIR > decIR then color.uptick else if addIR < decIR then color.downtick else color.gray);
AddLabel(showLabels and thrustType == thrustType."breakaway", " " + round(addIR,2)*100 + "% ", if addIR > decIR then color.uptick else color.gray);
AddLabel(showLabels and thrustType == thrustType."breakaway", " " + round(decIR,2)*100 + "% ", if addIR > decIR then color.gray else color.downtick);

# desmond labels
AddLabel(showLabels and thrustType == thrustType."desmond",
if ADRV == 0 then " Vol: TILT " else
" Vol: " + ADRV + ":1 ", if addVR > decVR then color.uptick else if addVR < decVR then color.downtick else color.gray);
AddLabel(showLabels and thrustType == thrustType."desmond", " " + round(addVR,2)*100 + "% ", if addVR > decVR then color.uptick else color.gray);
AddLabel(showLabels and thrustType == thrustType."desmond", " " + round(decVR,2)*100 + "% ", if addVR > decVR then color.gray else color.downtick);

# whaley labels
AddLabel(showLabels and thrustType == thrustType."whaley|ADT", " " + ADExpAvg + "% ", if signal then globalcolor("signal") else globalcolor("average"));
AddLabel(showLabels and thrustType == thrustType."whaley|UDT", " " + ADExpAvg + "% ", if signal then globalcolor("signal") else globalcolor("average"));
AddLabel(showLabels and thrustType == thrustType."whaley|SPT", " " + ADExpAvg + "% Chg ", if signal then globalcolor("signal") else globalcolor("average"));

# zweig labels
AddLabel(showLabels and thrustType == thrustType."Zweig", " " + ADExpAvg * 100 + "% stocks ", if signal then globalcolor("signal") else if adexpavg crosses above Weak then color.magenta else globalcolor("average"));
AddLabel(showLabels and thrustType == thrustType."Zweig" and zCount <= maxDays, " AD >= Weak: " + zcount + " days ", color.light_gray);
#AddLabel(showLabels and thrustType == thrustType."Zweig" and zCount <= maxDays, " Signal Window: " + (10-zCount) + (if (10-zCount)<=1 then " day left" else " days "), if (10-zCount)<=2 then color.downtick else color.light_gray);
AddLabel(showLabels and thrustType == thrustType."Zweig" and zweig, " Thrust ", globalcolor("signal"));

# signal label
AddLabel(signal, " Alert ", globalcolor("signal"));


# -- extLine
def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(close), 0, barNumber));
def colorAvg = if isnan(close) then colorAvg[1] else if signal then 1 else 0;

def extend = if barNumber == 1 then Double.NaN else if barNumber == barCount then close
else if barNumber == barCount then Double.NaN else extend[1];
plot extLine = extend;
extLine.SetStyle(Curve.SHORT_DASH);
extLine.AssignValueColor(if colorAvg == 1 then globalcolor("signal") else globalcolor("extLine"));
#extLine.HideBubble();
extLine.HideTitle();
extLine.SetHiding(!showExtLine);

[Lower Study]

Code:
#
# Breakaway Momentum (Breadth Thrust)
# defined: 10d sma advances > 1.97 x 10d sma declines.
# article: https://www.walterdeemer.com/bam.htm
#
# Desmond Reversals
# defined: 1 or more 90% downvolume day(s) [panic selling] followed by 90% upvolume day or 2 80+% upvolume days [panic buying]
# article: https://data.bloomberglp.com/assets/sites/2/2014/01/Desmond-report.pdf
#
# Whaley Thrusts
# defined:
#    - breath thursts (ADT): 5day cumulative advance/total issues crossing above 75 [whaley1] or crossing below 25 [whaley2]
#    - volume thrusts (UDT): 5day cumulative upvolume/total volume crossing above 77.8 [whaley3] or crossing below 16.4 [whaley4]
#    - sprice thrusts (SPT): 5day cumulative SP500 price % change of +10.05% [whaley5] or -13.85% [whaley6]
# article: http://docs.mta.org/pdfs/dowaward-2010.pdf
#
# Zweig Thrust
# defined: 10d ema advances crosses above 4.0 and 6.1 within 10 trading days
# article: https://www.seeitmarket.com/did-zweig-breadth-thrust-indicator-flash-buy-signal-for-stock-market/
# sourcecode: @ClarenceCarr
#


declare lower;

input thrustType = {default "Breakaway", "Desmond", "Whaley|ADT", "Whaley|UDT", "Whaley|SPT", "Zweig"};
input exchange = {default NYSE, NASDAQ, SnP500, Nasdaq100, Russell2000, Dow30, AMEX};
input signalType = {"Off", default "Bubble", "VerticalLine"};
input signalLabel = {default "Date", "Type", "Type|Date"};


def advanceI;
def declineI;
def advanceV;
def declineV;
switch (exchange) {
case NYSE:
    advanceI = close("$ADVN");
    declineI = close("$DECN");
    advanceV = close("$UVOL");
    declineV = close("$DVOL");
case NASDAQ:
    advanceI = close("$ADVN/Q");
    declineI = close("$DECN/Q");
    advanceV = close("$UVOL/Q");
    declineV = close("$DVOL/Q");
case SnP500:
    advanceI = close("$ADVSP");
    declineI = close("$DECLSP");
    advanceV = close("$UVOLSP");
    declineV = close("$DVOLSP");
case Nasdaq100:
    advanceI = close("$ADVND");
    declineI = close("$DECLND");
    advanceV = close("$UVOLND");
    declineV = close("$DVOLND");
case Russell2000:
    advanceI = close("$ADVRL");
    declineI = close("$DECLRL");
    advanceV = close("$UVOLRL");
    declineV = close("$DVOLRL");
case Dow30:
    advanceI = close("$ADVI");
    declineI = close("$DECLI");
    advanceV = close("$UVOLI");
    declineV = close("$DVOLI");
case AMEX:
    advanceI = close("$ADVA");
    declineI = close("$DECA");
    advanceV = close("$UVOLUS");
    declineV = close("$DVOLUS");
}

def aCount = if isnan(advanceI) then aCount[1] + 1 else 0;
def dCount = if isnan(declineI) then dCount[1] + 1 else 0;
def addI = if isnan(advanceI) then GetValue(advanceI, aCount) else advanceI;
def decI = if isnan(declineI) then GetValue(declineI, dCount) else declineI;
def totI = addI+decI;
def addIR = addI/totI;
def decIR = decI/totI;

def aVCount = if isnan(advanceV) then aVCount[1] + 1 else 0;
def dVCount = if isnan(declineV) then dVCount[1] + 1 else 0;
def addV = if isnan(advanceV) then GetValue(advanceV, aVCount) else advanceV;
def decV = if isnan(declineV) then GetValue(declineV, dVCount) else declineV;
def totV = addV + decV;
def addVR = addV/totV;
def decVR = decV/totV;

def SPChg = 100 * (close("SPX") / close("SPX")[1] - 1);


def advnDecl;
def mean;
def weak;
def thrust;
def spaceU;
def spaceD;
switch (thrustType){
case "Breakaway":
    advnDecl = round(average(addIR,10) - 1.97*average(decIR,10),2);
    mean = 0;
    weak = Double.NaN;
    thrust = Double.NaN;
    spaceU = 1;
    spaceD = -1;
case "Desmond":
    advnDecl = if addVR > decVR then round(addVR*100,2) else round(-decVR*100,2);
    mean = 0;
    weak = -80;
    thrust = 80;
    spaceU = 100;
    spaceD = -100;
case "Whaley|ADT":
    advnDecl = round(sum(addI,5)/sum(totI,5),3)*100;
    mean = 50;
    weak = 25;
    thrust = 75;
    spaceU = 100;
    spaceD = 0;
case "Whaley|UDT":
    advnDecl = round(sum(addV,5)/sum(totV,5),3)*100;
    mean = 50;
    weak = 16.4;
    thrust = 77.8;
    spaceU = 100;
    spaceD = 0;
case "Whaley|SPT":
    advnDecl = round(sum(SPChg,5),2);
    mean = 0;
    weak = -13.85;
    thrust = 10.05;
    spaceU = 30;
    spaceD = -30;
case "Zweig":
    advnDecl = round(ExpAverage(addIR,10),3);
    mean = 0.5;
    weak = 0.4;
    thrust = 0.61;
    spaceU = 0.8;
    spaceD = 0.2;
}

# -- plots
plot ADAvg = if IsNaN(close) then double.nan else if IsNaN(advnDecl) then mean else advnDecl;
ADAvg.HideBubble();
ADAvg.HideTitle();
plot ADAvgDots = ADAvg;
ADAvgDots.SetPaintingStrategy(paintingStrategy.POINTS);
ADAvgDots.SetLineweight(2);
ADAvgDots.HideBubble();

plot ThrustLine = thrust;
ThrustLine.AssignValueColor(if thrustType == thrustType."desmond" then color.light_gray else Color.UPTICK);
ThrustLine.HideBubble();
ThrustLine.HideTitle();
plot MeanLine = Mean;
MeanLine.SetStyle(Curve.Short_Dash);
MeanLine.SetDefaultColor(color.gray);
MeanLine.HideBubble();
MeanLine.HideTitle();
plot WeakLine = weak;
WeakLine.AssignValueColor(if thrustType == thrustType."desmond" then color.light_gray else Color.DOWNTICK);
WeakLine.HideBubble();
WeakLine.HideTitle();


# -- signals
# breakaway signal
def breakaway = average(addIR,10) crosses above 1.97*average(decIR,10);
def breakaway2 = average(addIR,20) crosses above 1.72*average(decIR,20); # jan 2019 addendum
# desmond
def desmond1 = advnDecl[1] <= -90 and advnDecl >= 90;
def desmond2 = advnDecl[2] <= -90 and advnDecl[1] >= 80 and advnDecl >= 80;
# whaley signal
def whaley1 = advnDecl crosses above thrust; #whaley1,3,&5
def whaley2 = advnDecl crosses below weak; #whaley2,4,&6
# zweig signal
def maxDays = 10;
def zCount = if advnDecl >= weak then zCount[1] + 1 else 0;
def zweig = advnDecl crosses above Thrust and zCount <= maxDays;

def signal =
if thrustType == thrustType."breakaway" then (breakaway or breakaway2) else
if thrustType == thrustType."desmond" then (desmond1 or desmond2) else
if thrustType == thrustType."whaley|ADT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|UDT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|SPT" then (whaley1 or whaley2) else
if thrustType == thrustType."Zweig" then Zweig else
double.nan;

AddVerticalLine(signalType == signalType."VerticalLine" and signal,
(if signalLabel != signalLabel."Date" then
    " " + thrustType + ", " else " ")
+
(if signalLabel != signalLabel."Type" then
 (if GetMonth()==1 then " Jan " else
 if GetMonth()==2 then " Feb " else
 if GetMonth()==3 then " Mar " else
 if GetMonth()==4 then " Apr " else
 if GetMonth()==5 then " May " else
 if GetMonth()==6 then " Jun " else
 if GetMonth()==7 then " Jul " else
 if GetMonth()==8 then " Aug " else
 if GetMonth()==9 then " Sep " else
 if GetMonth()==10 then " Oct " else
 if GetMonth()==11 then " Nov " else
 " Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
else " ")
+
(if signalLabel != signalLabel."Date" and thrustType == thrustType."Zweig" then " (" + zCount + " days)" else " ")
, globalcolor("signal"), 1);

Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Date" and signal, adavg, thrustType + if breakaway2 then "2" else "" + (if thrustType == thrustType."Zweig" then " (" + zCount + " days)" else ""), globalcolor("signal"), if (breakaway or breakaway2)then 1 else if whaley2 then 0 else 1);
Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Type" and signal, adavg,
 (if GetMonth()==1 then "Jan " else
 if GetMonth()==2 then "Feb " else
 if GetMonth()==3 then "Mar " else
 if GetMonth()==4 then "Apr " else
 if GetMonth()==5 then "May " else
 if GetMonth()==6 then "Jun " else
 if GetMonth()==7 then "Jul " else
 if GetMonth()==8 then "Aug " else
 if GetMonth()==9 then "Sep " else
 if GetMonth()==10 then "Oct " else
 if GetMonth()==11 then "Nov " else
 "Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
, color.light_gray, if (breakaway or breakaway2) then 1 else if whaley2 then 0 else 1);


# -- clouds
def value1 = if isnan(close) then double.nan else if signal or signal[1] then double.positive_INFINITY else Double.NaN;
def value2 = double.negative_infinity;
AddCloud(value1, value2, globalcolor("signal"));
# zweig window
def ccross = advnDecl crosses above weak;
def ccloud = Sum(ccross, maxdays);
def value3 = if ccloud then double.positive_INFINITY else Double.NaN;
AddCloud(if thrustType != thrustType."Zweig" then double.nan else value3, value2, color.light_gray);


# -- colors
defineglobalcolor("average", CreateColor(8,65,93)); #darker blue
#defineglobalcolor("average", CreateColor(0,102,153)); #blue
defineglobalcolor("signal", color.dark_orange);
DefineGlobalColor("vline", CreateColor(102,102,102));

def colorAvg = if isnan(close) then colorAvg[1] else #if IsNaN(ADExpAvg) then 0 else
if barnumber() == 1 then 0 else
if thrustType == thrustType."breakaway" then if signal then 2 else 0 else
if thrustType == thrustType."desmond" then
    (if between(advnDecl,weak,thrust) then 0 else
    if signal then 2 else
    if advnDecl <= weak then -1 else
    if advnDecl >= thrust then 1 else 0)
else
if thrustType == thrustType."whaley|ADT" then if signal then 2 else 0 else
if thrustType == thrustType."whaley|UDT" then if signal then 2 else 0 else
if thrustType == thrustType."whaley|SPT" then if signal then 2 else 0 else
if thrustType == thrustType."Zweig" then
    (if signal then 2 else
    if ADAvg crosses above weak then 3 else 0)
else 0;

# plots
ADAvg.AssignValueColor(globalcolor("average"));
ADAvgDots.AssignValueColor(
if colorAvg == 3 then color.magenta else
if colorAvg == 2 then globalcolor("signal") else
if colorAvg == 1 then color.uptick else
if colorAvg == -1 then createcolor(204,51,0) else
globalcolor("average"));

# extension line
def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(close), 0, barNumber));
def extend = if barNumber == 1 then Double.NaN else if barNumber == barCount then ADAvg else if barNumber == barCount then Double.NaN else extend[1];
plot extLine = extend;
extLine.SetStyle(Curve.SHORT_DASH);
extLine.AssignValueColor(
if colorAvg == 3 then color.magenta else
if colorAvg == 2 then globalcolor("signal") else
if colorAvg == 1 then color.uptick else
if colorAvg == -1 then createcolor(204,51,0) else
globalcolor("average"));
#extLine.hidebubble();
extLine.hidetitle();


# -- labels
AddLabel(1, " " + thrustType + " ", globalcolor("average"));
AddLabel(1, " " + (if thrustType == thrustType."whaley|SPT" then "SnP500" else exchange) + " ", globalcolor("average"));

# breakaway labels, issues
def ADRI =
if addI == 0 then 0 else
if decI == 0 then 0 else
if addI > decI then round(addI/decI,1) else round(-decI/addI, 1);
AddLabel(thrustType == thrustType."breakaway",
if ADRI == 0 then " Iss: TILT " else
" Iss: " + ADRI + ":1 ", if addIR > decIR then color.uptick else if addIR < decIR then color.downtick else color.gray);
AddLabel(thrustType == thrustType."breakaway", " " + round(addIR,2)*100 + "% ", if addIR > decIR then color.uptick else color.gray);
AddLabel(thrustType == thrustType."breakaway", " " + round(decIR,2)*100 + "% ", if addIR > decIR then color.gray else color.downtick);

# desmond labels, volume
def ADRV =
if addV == 0 then 0 else
if decV == 0 then 0 else
if addV > decV then round(addV/decV,1) else round(-decV/addV, 1);
AddLabel(thrustType == thrustType."desmond",
if ADRV == 0 then " Vol: TILT " else
" Vol: " + ADRV + ":1 ", if addVR > decVR then color.uptick else if addVR < decVR then color.downtick else color.gray);
AddLabel(thrustType == thrustType."desmond", " " + round(addVR,2)*100 + "% ", if addVR > decVR then color.uptick else color.gray);
AddLabel(thrustType == thrustType."desmond", " " + round(decVR,2)*100 + "% ", if addVR > decVR then color.gray else color.downtick);

# whaley labels
AddLabel(thrustType == thrustType."whaley|ADT", " " + ADAvg + "% ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."whaley|UDT", " " + ADAvg + "% ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."whaley|SPT", " " + ADAvg + "% Chg ", ADAvg.TakeValueColor());

# zweig labels
AddLabel(thrustType == thrustType."Zweig", " " + ADAvg * 100 + "% stocks ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."Zweig" and zCount <= maxDays, " AD >= Weak: " + zcount + " days ", color.light_gray);
AddLabel(thrustType == thrustType."Zweig" and zweig, " Thrust ", globalcolor("signal"));

# signal label
AddLabel(signal, " Alert ", globalcolor("signal"));


# -- spacers
plot spaceUp = if barnumber() == 1 then spaceU else double.nan;
spaceUp.AssignValueCOlor(color.white);
spaceUp.HideBubble();
spaceUp.HideTitle();
plot spaceDn = if barnumber() == 1 then spaceD else double.nan;
spaceDn.AssignValueCOlor(color.white);
spaceDn.HideBubble();
spaceDn.HideTitle();


# -- yearly line
AddVerticalLine(GetYear() != GetYear()[1] and GetAggregationPeriod() >= AggregationPeriod.Day, " ", GlobalColor("vline"));

Desmond

Code:
#
# Breakaway Momentum (Breadth Thrust)
# defined: 10d sma advances > 1.97 x 10d sma declines.
# article: https://www.walterdeemer.com/bam.htm
#
# Desmond Reversals
# defined: 1 or more 90% downvolume day(s) [panic selling] followed by 90% upvolume day or 2 80+% upvolume days [panic buying]
# article: https://data.bloomberglp.com/assets/sites/2/2014/01/Desmond-report.pdf
#
# Whaley Thrusts
# defined:
#    - breath thursts (ADT): 5day cumulative advance/total issues crossing above 75 [whaley1] or crossing below 25 [whaley2]
#    - volume thrusts (UDT): 5day cumulative upvolume/total volume crossing above 77.8 [whaley3] or crossing below 16.4 [whaley4]
#    - sprice thrusts (SPT): 5day cumulative SP500 price % change of +10.05% [whaley5] or -13.85% [whaley6]
# article: http://docs.mta.org/pdfs/dowaward-2010.pdf
#
# Zweig Thrust
# defined: 10d ema advances crosses above 4.0 and 6.1 within 10 trading days
# article: https://www.seeitmarket.com/did-zweig-breadth-thrust-indicator-flash-buy-signal-for-stock-market/
# sourcecode: @ClarenceCarr
#


declare lower;

input thrustType = {default "Breakaway", "Desmond", "Whaley|ADT", "Whaley|UDT", "Whaley|SPT", "Zweig"};
input exchange = {default NYSE, NASDAQ, SnP500, Nasdaq100, Russell2000, Dow30, AMEX};
input signalType = {"Off", default "Bubble", "VerticalLine"};
input signalLabel = {default "Date", "Type", "Type|Date"};


def advanceI;
def declineI;
def advanceV;
def declineV;
switch (exchange) {
case NYSE:
    advanceI = close("$ADVN");
    declineI = close("$DECN");
    advanceV = close("$UVOL");
    declineV = close("$DVOL");
case NASDAQ:
    advanceI = close("$ADVN/Q");
    declineI = close("$DECN/Q");
    advanceV = close("$UVOL/Q");
    declineV = close("$DVOL/Q");
case SnP500:
    advanceI = close("$ADVSP");
    declineI = close("$DECLSP");
    advanceV = close("$UVOLSP");
    declineV = close("$DVOLSP");
case Nasdaq100:
    advanceI = close("$ADVND");
    declineI = close("$DECLND");
    advanceV = close("$UVOLND");
    declineV = close("$DVOLND");
case Russell2000:
    advanceI = close("$ADVRL");
    declineI = close("$DECLRL");
    advanceV = close("$UVOLRL");
    declineV = close("$DVOLRL");
case Dow30:
    advanceI = close("$ADVI");
    declineI = close("$DECLI");
    advanceV = close("$UVOLI");
    declineV = close("$DVOLI");
case AMEX:
    advanceI = close("$ADVA");
    declineI = close("$DECA");
    advanceV = close("$UVOLUS");
    declineV = close("$DVOLUS");
}

def aCount = if isnan(advanceI) then aCount[1] + 1 else 0;
def dCount = if isnan(declineI) then dCount[1] + 1 else 0;
def addI = if isnan(advanceI) then GetValue(advanceI, aCount) else advanceI;
def decI = if isnan(declineI) then GetValue(declineI, dCount) else declineI;
def totI = addI+decI;
def addIR = addI/totI;
def decIR = decI/totI;

def aVCount = if isnan(advanceV) then aVCount[1] + 1 else 0;
def dVCount = if isnan(declineV) then dVCount[1] + 1 else 0;
def addV = if isnan(advanceV) then GetValue(advanceV, aVCount) else advanceV;
def decV = if isnan(declineV) then GetValue(declineV, dVCount) else declineV;
def totV = addV + decV;
def addVR = addV/totV;
def decVR = decV/totV;

def SPChg = 100 * (close("SPX") / close("SPX")[1] - 1);


def advnDecl;
def mean;
def weak;
def thrust;
def spaceU;
def spaceD;
switch (thrustType){
case "Breakaway":
    advnDecl = round(average(addIR,10) - 1.97*average(decIR,10),2);
    mean = 0;
    weak = Double.NaN;
    thrust = Double.NaN;
    spaceU = 1;
    spaceD = -1;
case "Desmond":
    advnDecl = if addVR > decVR then round(addVR*100,2) else round(-decVR*100,2);
    mean = 0;
    weak = -80;
    thrust = 80;
    spaceU = 100;
    spaceD = -100;
case "Whaley|ADT":
    advnDecl = round(sum(addI,5)/sum(totI,5),3)*100;
    mean = 50;
    weak = 25;
    thrust = 75;
    spaceU = 100;
    spaceD = 0;
case "Whaley|UDT":
    advnDecl = round(sum(addV,5)/sum(totV,5),3)*100;
    mean = 50;
    weak = 16.4;
    thrust = 77.8;
    spaceU = 100;
    spaceD = 0;
case "Whaley|SPT":
    advnDecl = round(sum(SPChg,5),2);
    mean = 0;
    weak = -13.85;
    thrust = 10.05;
    spaceU = 30;
    spaceD = -30;
case "Zweig":
    advnDecl = round(ExpAverage(addIR,10),3);
    mean = 0.5;
    weak = 0.4;
    thrust = 0.61;
    spaceU = 0.8;
    spaceD = 0.2;
}

# -- plots
plot ADAvg = if IsNaN(close) then double.nan else if IsNaN(advnDecl) then mean else advnDecl;
ADAvg.HideBubble();
ADAvg.HideTitle();
plot ADAvgDots = ADAvg;
ADAvgDots.SetPaintingStrategy(paintingStrategy.POINTS);
ADAvgDots.SetLineweight(2);
ADAvgDots.HideBubble();

plot ThrustLine = thrust;
ThrustLine.AssignValueColor(if thrustType == thrustType."desmond" then color.light_gray else Color.UPTICK);
ThrustLine.HideBubble();
ThrustLine.HideTitle();
plot MeanLine = Mean;
MeanLine.SetStyle(Curve.Short_Dash);
MeanLine.SetDefaultColor(color.gray);
MeanLine.HideBubble();
MeanLine.HideTitle();
plot WeakLine = weak;
WeakLine.AssignValueColor(if thrustType == thrustType."desmond" then color.light_gray else Color.DOWNTICK);
WeakLine.HideBubble();
WeakLine.HideTitle();


# -- signals
# breakaway signal
def breakaway = average(addIR,10) crosses above 1.97*average(decIR,10);
def breakaway2 = average(addIR,20) crosses above 1.72*average(decIR,20); # jan 2019 addendum
# desmond
def desmond1 = advnDecl[1] <= -90 and advnDecl >= 90;
def desmond2 = advnDecl[2] <= -90 and advnDecl[1] >= 80 and advnDecl >= 80;
# whaley signal
def whaley1 = advnDecl crosses above thrust; #whaley1,3,&5
def whaley2 = advnDecl crosses below weak; #whaley2,4,&6
# zweig signal
def maxDays = 10;
def zCount = if advnDecl >= weak then zCount[1] + 1 else 0;
def zweig = advnDecl crosses above Thrust and zCount <= maxDays;

def signal =
if thrustType == thrustType."breakaway" then (breakaway or breakaway2) else
if thrustType == thrustType."desmond" then (desmond1 or desmond2) else
if thrustType == thrustType."whaley|ADT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|UDT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|SPT" then (whaley1 or whaley2) else
if thrustType == thrustType."Zweig" then Zweig else
double.nan;

AddVerticalLine(signalType == signalType."VerticalLine" and signal,
(if signalLabel != signalLabel."Date" then
    " " + thrustType + ", " else " ")
+
(if signalLabel != signalLabel."Type" then
 (if GetMonth()==1 then " Jan " else
 if GetMonth()==2 then " Feb " else
 if GetMonth()==3 then " Mar " else
 if GetMonth()==4 then " Apr " else
 if GetMonth()==5 then " May " else
 if GetMonth()==6 then " Jun " else
 if GetMonth()==7 then " Jul " else
 if GetMonth()==8 then " Aug " else
 if GetMonth()==9 then " Sep " else
 if GetMonth()==10 then " Oct " else
 if GetMonth()==11 then " Nov " else
 " Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
else " ")
+
(if signalLabel != signalLabel."Date" and thrustType == thrustType."Zweig" then " (" + zCount + " days)" else " ")
, globalcolor("signal"), 1);

Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Date" and signal, adavg, thrustType + if breakaway2 then "2" else "" + (if thrustType == thrustType."Zweig" then " (" + zCount + " days)" else ""), globalcolor("signal"), if (breakaway or breakaway2)then 1 else if whaley2 then 0 else 1);
Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Type" and signal, adavg,
 (if GetMonth()==1 then "Jan " else
 if GetMonth()==2 then "Feb " else
 if GetMonth()==3 then "Mar " else
 if GetMonth()==4 then "Apr " else
 if GetMonth()==5 then "May " else
 if GetMonth()==6 then "Jun " else
 if GetMonth()==7 then "Jul " else
 if GetMonth()==8 then "Aug " else
 if GetMonth()==9 then "Sep " else
 if GetMonth()==10 then "Oct " else
 if GetMonth()==11 then "Nov " else
 "Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
, color.light_gray, if (breakaway or breakaway2) then 1 else if whaley2 then 0 else 1);


# -- clouds
def value1 = if isnan(close) then double.nan else if signal or signal[1] then double.positive_INFINITY else Double.NaN;
def value2 = double.negative_infinity;
AddCloud(value1, value2, globalcolor("signal"));
# zweig window
def ccross = advnDecl crosses above weak;
def ccloud = Sum(ccross, maxdays);
def value3 = if ccloud then double.positive_INFINITY else Double.NaN;
AddCloud(if thrustType != thrustType."Zweig" then double.nan else value3, value2, color.light_gray);


# -- colors
defineglobalcolor("average", CreateColor(8,65,93)); #darker blue
#defineglobalcolor("average", CreateColor(0,102,153)); #blue
defineglobalcolor("signal", color.dark_orange);
DefineGlobalColor("vline", CreateColor(102,102,102));

def colorAvg = if isnan(close) then colorAvg[1] else #if IsNaN(ADExpAvg) then 0 else
if barnumber() == 1 then 0 else
if thrustType == thrustType."breakaway" then if signal then 2 else 0 else
if thrustType == thrustType."desmond" then
    (if between(advnDecl,weak,thrust) then 0 else
    if signal then 2 else
    if advnDecl <= weak then -1 else
    if advnDecl >= thrust then 1 else 0)
else
if thrustType == thrustType."whaley|ADT" then if signal then 2 else 0 else
if thrustType == thrustType."whaley|UDT" then if signal then 2 else 0 else
if thrustType == thrustType."whaley|SPT" then if signal then 2 else 0 else
if thrustType == thrustType."Zweig" then
    (if signal then 2 else
    if ADAvg crosses above weak then 3 else 0)
else 0;

# plots
ADAvg.AssignValueColor(globalcolor("average"));
ADAvgDots.AssignValueColor(
if colorAvg == 3 then color.magenta else
if colorAvg == 2 then globalcolor("signal") else
if colorAvg == 1 then color.uptick else
if colorAvg == -1 then createcolor(204,51,0) else
globalcolor("average"));

# extension line
def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(close), 0, barNumber));
def extend = if barNumber == 1 then Double.NaN else if barNumber == barCount then ADAvg else if barNumber == barCount then Double.NaN else extend[1];
plot extLine = extend;
extLine.SetStyle(Curve.SHORT_DASH);
extLine.AssignValueColor(
if colorAvg == 3 then color.magenta else
if colorAvg == 2 then globalcolor("signal") else
if colorAvg == 1 then color.uptick else
if colorAvg == -1 then createcolor(204,51,0) else
globalcolor("average"));
#extLine.hidebubble();
extLine.hidetitle();


# -- labels
AddLabel(1, " " + thrustType + " ", globalcolor("average"));
AddLabel(1, " " + (if thrustType == thrustType."whaley|SPT" then "SnP500" else exchange) + " ", globalcolor("average"));

# breakaway labels, issues
def ADRI =
if addI == 0 then 0 else
if decI == 0 then 0 else
if addI > decI then round(addI/decI,1) else round(-decI/addI, 1);
AddLabel(thrustType == thrustType."breakaway",
if ADRI == 0 then " Iss: TILT " else
" Iss: " + ADRI + ":1 ", if addIR > decIR then color.uptick else if addIR < decIR then color.downtick else color.gray);
AddLabel(thrustType == thrustType."breakaway", " " + round(addIR,2)*100 + "% ", if addIR > decIR then color.uptick else color.gray);
AddLabel(thrustType == thrustType."breakaway", " " + round(decIR,2)*100 + "% ", if addIR > decIR then color.gray else color.downtick);

# desmond labels, volume
def ADRV =
if addV == 0 then 0 else
if decV == 0 then 0 else
if addV > decV then round(addV/decV,1) else round(-decV/addV, 1);
AddLabel(thrustType == thrustType."desmond",
if ADRV == 0 then " Vol: TILT " else
" Vol: " + ADRV + ":1 ", if addVR > decVR then color.uptick else if addVR < decVR then color.downtick else color.gray);
AddLabel(thrustType == thrustType."desmond", " " + round(addVR,2)*100 + "% ", if addVR > decVR then color.uptick else color.gray);
AddLabel(thrustType == thrustType."desmond", " " + round(decVR,2)*100 + "% ", if addVR > decVR then color.gray else color.downtick);

# whaley labels
AddLabel(thrustType == thrustType."whaley|ADT", " " + ADAvg + "% ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."whaley|UDT", " " + ADAvg + "% ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."whaley|SPT", " " + ADAvg + "% Chg ", ADAvg.TakeValueColor());

# zweig labels
AddLabel(thrustType == thrustType."Zweig", " " + ADAvg * 100 + "% stocks ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."Zweig" and zCount <= maxDays, " AD >= Weak: " + zcount + " days ", color.light_gray);
AddLabel(thrustType == thrustType."Zweig" and zweig, " Thrust ", globalcolor("signal"));

# signal label
AddLabel(signal, " Alert ", globalcolor("signal"));


# -- spacers
plot spaceUp = if barnumber() == 1 then spaceU else double.nan;
spaceUp.AssignValueCOlor(color.white);
spaceUp.HideBubble();
spaceUp.HideTitle();
plot spaceDn = if barnumber() == 1 then spaceD else double.nan;
spaceDn.AssignValueCOlor(color.white);
spaceDn.HideBubble();
spaceDn.HideTitle();


# -- yearly line
AddVerticalLine(GetYear() != GetYear()[1] and GetAggregationPeriod() >= AggregationPeriod.Day, " ", GlobalColor("vline"));

Zweig

Code:
#
# Breakaway Momentum (Breadth Thrust)
# defined: 10d sma advances > 1.97 x 10d sma declines.
# article: https://www.walterdeemer.com/bam.htm
#
# Desmond Reversals
# defined: 1 or more 90% downvolume day(s) [panic selling] followed by 90% upvolume day or 2 80+% upvolume days [panic buying]
# article: https://data.bloomberglp.com/assets/sites/2/2014/01/Desmond-report.pdf
#
# Whaley Thrusts
# defined:
#    - breath thursts (ADT): 5day cumulative advance/total issues crossing above 75 [whaley1] or crossing below 25 [whaley2]
#    - volume thrusts (UDT): 5day cumulative upvolume/total volume crossing above 77.8 [whaley3] or crossing below 16.4 [whaley4]
#    - sprice thrusts (SPT): 5day cumulative SP500 price % change of +10.05% [whaley5] or -13.85% [whaley6]
# article: http://docs.mta.org/pdfs/dowaward-2010.pdf
#
# Zweig Thrust
# defined: 10d ema advances crosses above 4.0 and 6.1 within 10 trading days
# article: https://www.seeitmarket.com/did-zweig-breadth-thrust-indicator-flash-buy-signal-for-stock-market/
# sourcecode: @ClarenceCarr
#


declare lower;

input thrustType = {default "Breakaway", "Desmond", "Whaley|ADT", "Whaley|UDT", "Whaley|SPT", "Zweig"};
input exchange = {default NYSE, NASDAQ, SnP500, Nasdaq100, Russell2000, Dow30, AMEX};
input signalType = {"Off", default "Bubble", "VerticalLine"};
input signalLabel = {default "Date", "Type", "Type|Date"};


def advanceI;
def declineI;
def advanceV;
def declineV;
switch (exchange) {
case NYSE:
    advanceI = close("$ADVN");
    declineI = close("$DECN");
    advanceV = close("$UVOL");
    declineV = close("$DVOL");
case NASDAQ:
    advanceI = close("$ADVN/Q");
    declineI = close("$DECN/Q");
    advanceV = close("$UVOL/Q");
    declineV = close("$DVOL/Q");
case SnP500:
    advanceI = close("$ADVSP");
    declineI = close("$DECLSP");
    advanceV = close("$UVOLSP");
    declineV = close("$DVOLSP");
case Nasdaq100:
    advanceI = close("$ADVND");
    declineI = close("$DECLND");
    advanceV = close("$UVOLND");
    declineV = close("$DVOLND");
case Russell2000:
    advanceI = close("$ADVRL");
    declineI = close("$DECLRL");
    advanceV = close("$UVOLRL");
    declineV = close("$DVOLRL");
case Dow30:
    advanceI = close("$ADVI");
    declineI = close("$DECLI");
    advanceV = close("$UVOLI");
    declineV = close("$DVOLI");
case AMEX:
    advanceI = close("$ADVA");
    declineI = close("$DECA");
    advanceV = close("$UVOLUS");
    declineV = close("$DVOLUS");
}

def aCount = if isnan(advanceI) then aCount[1] + 1 else 0;
def dCount = if isnan(declineI) then dCount[1] + 1 else 0;
def addI = if isnan(advanceI) then GetValue(advanceI, aCount) else advanceI;
def decI = if isnan(declineI) then GetValue(declineI, dCount) else declineI;
def totI = addI+decI;
def addIR = addI/totI;
def decIR = decI/totI;

def aVCount = if isnan(advanceV) then aVCount[1] + 1 else 0;
def dVCount = if isnan(declineV) then dVCount[1] + 1 else 0;
def addV = if isnan(advanceV) then GetValue(advanceV, aVCount) else advanceV;
def decV = if isnan(declineV) then GetValue(declineV, dVCount) else declineV;
def totV = addV + decV;
def addVR = addV/totV;
def decVR = decV/totV;

def SPChg = 100 * (close("SPX") / close("SPX")[1] - 1);


def advnDecl;
def mean;
def weak;
def thrust;
def spaceU;
def spaceD;
switch (thrustType){
case "Breakaway":
    advnDecl = round(average(addIR,10) - 1.97*average(decIR,10),2);
    mean = 0;
    weak = Double.NaN;
    thrust = Double.NaN;
    spaceU = 1;
    spaceD = -1;
case "Desmond":
    advnDecl = if addVR > decVR then round(addVR*100,2) else round(-decVR*100,2);
    mean = 0;
    weak = -80;
    thrust = 80;
    spaceU = 100;
    spaceD = -100;
case "Whaley|ADT":
    advnDecl = round(sum(addI,5)/sum(totI,5),3)*100;
    mean = 50;
    weak = 25;
    thrust = 75;
    spaceU = 100;
    spaceD = 0;
case "Whaley|UDT":
    advnDecl = round(sum(addV,5)/sum(totV,5),3)*100;
    mean = 50;
    weak = 16.4;
    thrust = 77.8;
    spaceU = 100;
    spaceD = 0;
case "Whaley|SPT":
    advnDecl = round(sum(SPChg,5),2);
    mean = 0;
    weak = -13.85;
    thrust = 10.05;
    spaceU = 30;
    spaceD = -30;
case "Zweig":
    advnDecl = round(ExpAverage(addIR,10),3);
    mean = 0.5;
    weak = 0.4;
    thrust = 0.61;
    spaceU = 0.8;
    spaceD = 0.2;
}

# -- plots
plot ADAvg = if IsNaN(close) then double.nan else if IsNaN(advnDecl) then mean else advnDecl;
ADAvg.HideBubble();
ADAvg.HideTitle();
plot ADAvgDots = ADAvg;
ADAvgDots.SetPaintingStrategy(paintingStrategy.POINTS);
ADAvgDots.SetLineweight(2);
ADAvgDots.HideBubble();

plot ThrustLine = thrust;
ThrustLine.AssignValueColor(if thrustType == thrustType."desmond" then color.light_gray else Color.UPTICK);
ThrustLine.HideBubble();
ThrustLine.HideTitle();
plot MeanLine = Mean;
MeanLine.SetStyle(Curve.Short_Dash);
MeanLine.SetDefaultColor(color.gray);
MeanLine.HideBubble();
MeanLine.HideTitle();
plot WeakLine = weak;
WeakLine.AssignValueColor(if thrustType == thrustType."desmond" then color.light_gray else Color.DOWNTICK);
WeakLine.HideBubble();
WeakLine.HideTitle();


# -- signals
# breakaway signal
def breakaway = average(addIR,10) crosses above 1.97*average(decIR,10);
def breakaway2 = average(addIR,20) crosses above 1.72*average(decIR,20); # jan 2019 addendum
# desmond
def desmond1 = advnDecl[1] <= -90 and advnDecl >= 90;
def desmond2 = advnDecl[2] <= -90 and advnDecl[1] >= 80 and advnDecl >= 80;
# whaley signal
def whaley1 = advnDecl crosses above thrust; #whaley1,3,&5
def whaley2 = advnDecl crosses below weak; #whaley2,4,&6
# zweig signal
def maxDays = 10;
def zCount = if advnDecl >= weak then zCount[1] + 1 else 0;
def zweig = advnDecl crosses above Thrust and zCount <= maxDays;

def signal =
if thrustType == thrustType."breakaway" then (breakaway or breakaway2) else
if thrustType == thrustType."desmond" then (desmond1 or desmond2) else
if thrustType == thrustType."whaley|ADT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|UDT" then (whaley1 or whaley2) else
if thrustType == thrustType."whaley|SPT" then (whaley1 or whaley2) else
if thrustType == thrustType."Zweig" then Zweig else
double.nan;

AddVerticalLine(signalType == signalType."VerticalLine" and signal,
(if signalLabel != signalLabel."Date" then
    " " + thrustType + ", " else " ")
+
(if signalLabel != signalLabel."Type" then
 (if GetMonth()==1 then " Jan " else
 if GetMonth()==2 then " Feb " else
 if GetMonth()==3 then " Mar " else
 if GetMonth()==4 then " Apr " else
 if GetMonth()==5 then " May " else
 if GetMonth()==6 then " Jun " else
 if GetMonth()==7 then " Jul " else
 if GetMonth()==8 then " Aug " else
 if GetMonth()==9 then " Sep " else
 if GetMonth()==10 then " Oct " else
 if GetMonth()==11 then " Nov " else
 " Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
else " ")
+
(if signalLabel != signalLabel."Date" and thrustType == thrustType."Zweig" then " (" + zCount + " days)" else " ")
, globalcolor("signal"), 1);

Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Date" and signal, adavg, thrustType + if breakaway2 then "2" else "" + (if thrustType == thrustType."Zweig" then " (" + zCount + " days)" else ""), globalcolor("signal"), if (breakaway or breakaway2)then 1 else if whaley2 then 0 else 1);
Addchartbubble(signalType == signalType."Bubble" and signalLabel != signalLabel."Type" and signal, adavg,
 (if GetMonth()==1 then "Jan " else
 if GetMonth()==2 then "Feb " else
 if GetMonth()==3 then "Mar " else
 if GetMonth()==4 then "Apr " else
 if GetMonth()==5 then "May " else
 if GetMonth()==6 then "Jun " else
 if GetMonth()==7 then "Jul " else
 if GetMonth()==8 then "Aug " else
 if GetMonth()==9 then "Sep " else
 if GetMonth()==10 then "Oct " else
 if GetMonth()==11 then "Nov " else
 "Dec ")
+ getdayofmonth(getyyyymmdd()) + ", " + asprice(getyear())
, color.light_gray, if (breakaway or breakaway2) then 1 else if whaley2 then 0 else 1);


# -- clouds
def value1 = if isnan(close) then double.nan else if signal or signal[1] then double.positive_INFINITY else Double.NaN;
def value2 = double.negative_infinity;
AddCloud(value1, value2, globalcolor("signal"));
# zweig window
def ccross = advnDecl crosses above weak;
def ccloud = Sum(ccross, maxdays);
def value3 = if ccloud then double.positive_INFINITY else Double.NaN;
AddCloud(if thrustType != thrustType."Zweig" then double.nan else value3, value2, color.light_gray);


# -- colors
defineglobalcolor("average", CreateColor(8,65,93)); #darker blue
#defineglobalcolor("average", CreateColor(0,102,153)); #blue
defineglobalcolor("signal", color.dark_orange);
DefineGlobalColor("vline", CreateColor(102,102,102));

def colorAvg = if isnan(close) then colorAvg[1] else #if IsNaN(ADExpAvg) then 0 else
if barnumber() == 1 then 0 else
if thrustType == thrustType."breakaway" then if signal then 2 else 0 else
if thrustType == thrustType."desmond" then
    (if between(advnDecl,weak,thrust) then 0 else
    if signal then 2 else
    if advnDecl <= weak then -1 else
    if advnDecl >= thrust then 1 else 0)
else
if thrustType == thrustType."whaley|ADT" then if signal then 2 else 0 else
if thrustType == thrustType."whaley|UDT" then if signal then 2 else 0 else
if thrustType == thrustType."whaley|SPT" then if signal then 2 else 0 else
if thrustType == thrustType."Zweig" then
    (if signal then 2 else
    if ADAvg crosses above weak then 3 else 0)
else 0;

# plots
ADAvg.AssignValueColor(globalcolor("average"));
ADAvgDots.AssignValueColor(
if colorAvg == 3 then color.magenta else
if colorAvg == 2 then globalcolor("signal") else
if colorAvg == 1 then color.uptick else
if colorAvg == -1 then createcolor(204,51,0) else
globalcolor("average"));

# extension line
def barNumber = BarNumber();
def barCount = HighestAll(If(IsNaN(close), 0, barNumber));
def extend = if barNumber == 1 then Double.NaN else if barNumber == barCount then ADAvg else if barNumber == barCount then Double.NaN else extend[1];
plot extLine = extend;
extLine.SetStyle(Curve.SHORT_DASH);
extLine.AssignValueColor(
if colorAvg == 3 then color.magenta else
if colorAvg == 2 then globalcolor("signal") else
if colorAvg == 1 then color.uptick else
if colorAvg == -1 then createcolor(204,51,0) else
globalcolor("average"));
#extLine.hidebubble();
extLine.hidetitle();


# -- labels
AddLabel(1, " " + thrustType + " ", globalcolor("average"));
AddLabel(1, " " + (if thrustType == thrustType."whaley|SPT" then "SnP500" else exchange) + " ", globalcolor("average"));

# breakaway labels, issues
def ADRI =
if addI == 0 then 0 else
if decI == 0 then 0 else
if addI > decI then round(addI/decI,1) else round(-decI/addI, 1);
AddLabel(thrustType == thrustType."breakaway",
if ADRI == 0 then " Iss: TILT " else
" Iss: " + ADRI + ":1 ", if addIR > decIR then color.uptick else if addIR < decIR then color.downtick else color.gray);
AddLabel(thrustType == thrustType."breakaway", " " + round(addIR,2)*100 + "% ", if addIR > decIR then color.uptick else color.gray);
AddLabel(thrustType == thrustType."breakaway", " " + round(decIR,2)*100 + "% ", if addIR > decIR then color.gray else color.downtick);

# desmond labels, volume
def ADRV =
if addV == 0 then 0 else
if decV == 0 then 0 else
if addV > decV then round(addV/decV,1) else round(-decV/addV, 1);
AddLabel(thrustType == thrustType."desmond",
if ADRV == 0 then " Vol: TILT " else
" Vol: " + ADRV + ":1 ", if addVR > decVR then color.uptick else if addVR < decVR then color.downtick else color.gray);
AddLabel(thrustType == thrustType."desmond", " " + round(addVR,2)*100 + "% ", if addVR > decVR then color.uptick else color.gray);
AddLabel(thrustType == thrustType."desmond", " " + round(decVR,2)*100 + "% ", if addVR > decVR then color.gray else color.downtick);

# whaley labels
AddLabel(thrustType == thrustType."whaley|ADT", " " + ADAvg + "% ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."whaley|UDT", " " + ADAvg + "% ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."whaley|SPT", " " + ADAvg + "% Chg ", ADAvg.TakeValueColor());

# zweig labels
AddLabel(thrustType == thrustType."Zweig", " " + ADAvg * 100 + "% stocks ", ADAvg.TakeValueColor());
AddLabel(thrustType == thrustType."Zweig" and zCount <= maxDays, " AD >= Weak: " + zcount + " days ", color.light_gray);
AddLabel(thrustType == thrustType."Zweig" and zweig, " Thrust ", globalcolor("signal"));

# signal label
AddLabel(signal, " Alert ", globalcolor("signal"));


# -- spacers
plot spaceUp = if barnumber() == 1 then spaceU else double.nan;
spaceUp.AssignValueCOlor(color.white);
spaceUp.HideBubble();
spaceUp.HideTitle();
plot spaceDn = if barnumber() == 1 then spaceD else double.nan;
spaceDn.AssignValueCOlor(color.white);
spaceDn.HideBubble();
spaceDn.HideTitle();


# -- yearly line
AddVerticalLine(GetYear() != GetYear()[1] and GetAggregationPeriod() >= AggregationPeriod.Day, " ", GlobalColor("vline"));

My entire grid setup: https://tos.mx/VqsmiPC
 

wtf_dude

Active member
@SilverSurferAI Duuuude! Thanks, I've been looking for an all in one for a long damn time. Don't know if anybody follows these (I'm still on the fence), but the breakaway thrust just triggered, which hasn't happened since early Jan 2019.
 

radnor

New member
The Whaley SPT signals off of the March lows might have been expected for a bounce given the sharpness of the decline. But, the recent Breakaway (6/3 & 6/5) plus Whaley ADT on 6/8/20 coming this late in a rally are unusual indicators that the rally may have legs.
The lower indicators appear to be broken for Desmond and Whaley UDT when using NYSE (showing errors the last few weeks). I had to change those to NASDAQ composite.
 

wtf_dude

Active member
I just use them as the upper indicators with the vertical lines. As much as I hate this rally, this thing has some strong momentum. The thing that worries me the most is the spy to qqq ratio. Lowest it's been since the dot-com boom. The only difference being the RSI is no way near as sunk as back then.
 

radnor

New member
Certainly a tech heavy uptrend. Ongoing strength in NASDAQ (COMP & NDX) vs middling SPX vs weaker $DJI vs even weaker RUT.
The upper indicators (vertical lines) show thrust dates based on the lower indicators. NYSE and AMEX inputs have been broken for several weeks in Desmond and Whaley UDT. Weird that they still show good data for earlier in the year, though.
 

Similar threads

Top