I recently became interested in breadth thrusts deemer, desmond, whaley, & now zweig. I found this link on twitter.
mod note:
How To Use The Breath Thrust Indicator
This script watches market internals (advancers/decliners, up/down volume, S&P price changes) and alerts you when the market shows rare “surge” behavior that historically marks major turning points.
Think of it as a market weather siren: it lights up when conditions shift dramatically.
This script uses the best breadth and volume data available; but retail data feeds do not provide the actual data used in the real Desmond, Whaley, or Zweig research. Treat these signals as approximations — helpful for context
Step 1 — Choose the Type of Thrust You Want to Track
The script has a dropdown called thrustType with these options:
Pick one thrust type at a time so you don’t confuse the signals.
Step 2 — Choose the Exchange
The script can analyze:
Step 3 — Turn On How You Want Signals Displayed
The script can show signals as:
Step 4 — Interpret the Signals
When a thrust occurs, the script:
A thrust is not a buy signal by itself.It’s a “market regime change” alert.
After a thrust, the script shades the next 60 trading days.
This is the “statistical edge” window where thrusts historically matter.
You don’t buy because of the thrust.You trade with the wind at your back during the window.
Step 6 — Just Starting Out? Keep It Simple:
Breakaway Momentum (Breadth Thrust) [Upper Study]
[Lower Study]
Desmond
Zweig
My entire grid setup: https://tos.mx/VqsmiPC
mod note:
How To Use The Breath Thrust Indicator
This script watches market internals (advancers/decliners, up/down volume, S&P price changes) and alerts you when the market shows rare “surge” behavior that historically marks major turning points.
Think of it as a market weather siren: it lights up when conditions shift dramatically.
Step 1 — Choose the Type of Thrust You Want to Track
The script has a dropdown called thrustType with these options:
- Breakaway Momentum
- Desmond Reversal
- Whaley ADT / UDT / SPT
- Zweig Breadth Thrust
| Thrust Type | What It Detects | Why It Matters |
|---|---|---|
| Breakaway | Sudden surge in advancing stocks | Often marks the start of major bull runs |
| Desmond | Panic selling → panic buying | Capitulation bottoms |
| Whaley | Strong moves in breadth, volume, or price | Momentum shifts |
| Zweig | Extremely rare breadth surge | Historically powerful buy signals |
Step 2 — Choose the Exchange
The script can analyze:
- NYSE
- NASDAQ
- S&P 500
- Nasdaq 100
- Russell 2000
- Dow 30
- AMEX
Step 3 — Turn On How You Want Signals Displayed
The script can show signals as:
- Vertical lines on the chart
- Bubbles under the candles
- Labels at the top
- Clouds highlighting the thrust window
- VerticalLine = ON
- showLabels = YES
- showClouds = YES
Step 4 — Interpret the Signals
When a thrust occurs, the script:
- Draws a vertical orange line
- Adds a label saying “Alert”
- Highlights the trade window (default 60 days)
- Colors the candles during the thrust
- Look for confirmation from price (higher highs, breakouts)
- Avoid fighting the signal (don’t short into a thrust)
- Use it to shift bias from bearish → bullish or vice versa
After a thrust, the script shades the next 60 trading days.
This is the “statistical edge” window where thrusts historically matter.
You don’t buy because of the thrust.You trade with the wind at your back during the window.
Step 6 — Just Starting Out? Keep It Simple:
- ThrustType = Zweig (rare, clean, powerful)
- Exchange = NYSE
- SignalType = VerticalLine
- showClouds = YES
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
Last edited by a moderator: