Advance/Decline Line Indicator for ThinkorSwim


Well-known member
10:11 Mobius: AD (Advance/Decline Line) is an Intraday indicator. It's daily closing value isn't of any value since where it closes in relation to the closing price has no correlation.

# TD Ameritrade IP Company, Inc. (c) 2010-2020

declare lower;

input type = {default "Advance/Decline Line", "Advance/Decline Line (Breadth)", "Advance/Decline Line (Daily)", "Advance/Decline Ratio", "Advance/Decline Spread (Issues)", "Absolute Breadth Index"};
input exchange = {default NYSE, NASDAQ, AMEX};

def advances;
def declines;
switch (exchange) {
case NYSE:
    advances = close("$ADVN");
    declines = close("$DECN");
case NASDAQ:
    advances = close("$ADVN/Q");
    declines = close("$DECN/Q");
case AMEX:
    advances = close("$ADVA");
    declines = close("$DECA");
def advnDecl;
def level;
switch (type){
case "Advance/Decline Line":
    advnDecl = advnDecl[1] + if !IsNaN(advances - declines) then advances - declines else 0;
    level = 0;
case "Advance/Decline Line (Breadth)":
    advnDecl = advances / (advances + declines);
    level = 0.5;
case "Advance/Decline Line (Daily)":
    advnDecl = (advances - declines) / (advances + declines);
    level = 0;
case "Advance/Decline Ratio":
    advnDecl = advances / declines;
    level = 1;
case "Advance/Decline Spread (Issues)":
    advnDecl = advances - declines;
    level = 0;
case "Absolute Breadth Index":
    advnDecl = AbsValue(advances - declines);
    level = 0;

plot AD = if !IsNaN(close) then advnDecl else Double.NaN;
plot LevelLine = level;

AD.DefineColor("Up", Color.UPTICK);
AD.DefineColor("Down", Color.DOWNTICK);
AD.AssignValueColor(if advnDecl > advnDecl[1] then AD.color("Up") else AD.color("Down"));

AddLabel(type == type."Advance/Decline Ratio", (if advances > declines then round(advances / declines, 2) else round(-declines / advances, 2)) + ":1 Ratio");

Plots the Advance Decline Line Scaled to Current Price with a horizontal line at the RTH Open.

# AD Line Scaled and Plotted on Upper Graph
# Mobius

input sym = "$ADSPD"; #hint sym: Symbol to be scaled to current price chart.

def AD = close(symbol = sym);
def Min = lowestAll(low);
def Max = highestAll(high);
def bar = barNumber();
def Today = getDay() == getLastDay();
script ScaleFunction{
    input c = 0;
    input Min = -1;
    input Max = 1;
    def hh = HighestAll(c);
    def ll = LowestAll(c);
    plot Range = (((Max - Min) * (c - ll)) /  (hh - ll)) + Min;
script LinePlot {
    input LineLimit = 0;
    input OnExpansion = yes;
    input data = close;
    input bar = 0;
    def ThisBar = HighestAll(bar);
    def cLine = if bar == ThisBar
                then data
                else Double.NaN;
    def cond1 = CompoundValue(1, if IsNaN(data)
                                 then cond1[1]
                                 else data, data);
    plot P = if ThisBar - LineLimit <= bar
             then HighestAll(cLine)
             else Double.NaN;
plot ADline = if Today
              then scaleFunction(c = AD,
                   Min = Min,
                   Max = Max)
              else double.nan;
def RTH_Bar1 = if SecondsTillTime(0930) == 0 and
                  SecondsFromTime(0930) == 0
               then bar
               else RTH_Bar1[1];
def OpenAD = if bar == RTH_Bar1
             then ADline
             else OpenAD[1];
def ADLimit = if bar != RTH_Bar1
              then bar - RTH_Bar1
              else if bar == RTH_Bar1
                   then Double.NaN
                   else ADLimit[1];
plot AD_RTH_open = LinePlot(LineLimit = ADLimit,
                   data = OpenAD,
                   bar = RTH_Bar1);
AddLabel(1, "AD = " + AD, if AD > 0
# End Code AD Chart Line

Advance/Decline as Label on chart

# 10:14 Mobius: here is an AD label that includes the open, high and low of the day with bubbles plotted at those price locations on the chart.

# AD Label
# Mobius
# V01

def RTH = getTime() >= regularTradingStart(getYYYYMMDD()) and
          getTime() <= regularTradingEnd(getYYYYMMDD());

def o = if RTH and !RTH[1]
        then open("$ADSPD")
        else o[1];

def c = if isNaN(close("$ADSPD"))
        then c[1]
        else close("$ADSPD");

def x = barNumber();
def sumx = if RTH and !RTH[1]
            then 1
            else if RTH then sumx[1] + 1
            else if !RTH
            then sumx[1]
            else sumx[1];

def sumAD = if RTH and !RTH[1]
            then c
            else if RTH
            then sumAD[1] + c
            else sumAD[1];

def h = if isNaN(high("$ADSPD", "DAY"))
        then h[1]
        else high("$ADSPD", "DAY");

def ADHighBar = if high("$ADSPD") == h
                  then x
                  else double.nan;

AddChartBubble(barNumber() == HighestAll(ADHighBar),
               high + (2 * TickSize()),

def l = if isNaN(low("$ADSPD", "DAY"))
        then l[1]
        else low("$ADSPD", "DAY");

def ADLowBar = if low("$ADSPD") == l
                  then x
                  else double.nan;

AddChartBubble(barNumber() == HighestAll(ADLowBar),
               low - (2 * TickSize()),

def Avg = Round(sumAD / sumx, 0);

addLabel(1, "AD open " + o +

          "  high " + h +

          "  low " + l +

          "  close " + c +

          "  Avg " + Avg, if c < 0



# End Code AD Label

Code # 2 of 3

#10:18 Mobius: Here's AD Scaled to Price and plotted along with a plot of the AD zero line at price where crosses. Which is often a price pivot area.

# AD Scaled To Price
# Mobius
# Changed original code to use RegularTrading(Start, End) functions. Use RTH Only.
# V02 2019

script Scale {

    input h = high;
    input l = low;
    input c = close;
    def RTH = getTime() >= RegularTradingStart(getYYYYMMDD()) and
              getTime() <= RegularTradingEnd(getYYYYMMDD());
    def max = if RTH and !RTH[1]
              then high
              else if RTH and high > max[1]
              then high
              else max[1];
    def min = if RTH and !RTH[1]
              then low
              else if RTH and low < min[1]
              then low
              else min[1];
    def hh = if RTH and !RTH[1]
             then h
             else if RTH and h > hh[1]
             then h
             else hh[1];
     def ll = if RTH and !RTH[1]
              then l
              else if RTH and l < ll[1]
              then l
              else ll[1];
    plot Range = (((Max - Min) * (c - ll)) /  (hh - ll)) + Min;


plot Scaled_Symbol = scale(high("$ADSPD"), low("$ADSPD"), close("$ADSPD"));
     Scaled_Symbol.AssignValueColor(if Scaled_Symbol > Scaled_Symbol[1]

def zero = if close("$ADSPD") crosses 0
           then close
           else zero[1];
def zero_bar = if close("$ADSPD") crosses 0
               then barNumber()
               else double.nan;

plot zeroLine = if barNumber() >= highestAll(zero_bar)
                then highestAll(if isNaN(close[-1])
                                then zero
                                else double.nan)
                else double.nan;

AddChartBubble(barNumber() == HighestAll(barNumber()),
               "AD 0",

# End Code

#10:22 MTS1: Thanks Mobius!
#10:26 binh4984: Thank you very much Mobius for your help.
#10:33 Mobius: yw And, bin... you might consider the fact that AD is an oscillator that ranges around 0. So taking a daily average of it's closing value would be that same as taking the daily closing average of any oscillator
#10:35 Mobius: won't tell you anything of value. Now you could write a binary momentum indicator using AD on a daily basis that would tell you when a trend is in place and the momentum of that trend
#10:36 Mobius: See the True Momentum Indicator for a method to do that and adding a weight adjusted by the closing value of AD might be useful
#10:37 MTS1: I guess an average on a cumulative AD could be some sort of signal line. I know some analysts look at longer term MI's like that, also # stocks above or below an MA, new highs/lows etc. But I think AD / VOLD etc are probably more useful intraday.

(I would not endorse #3 of 3 as I don't see it's utility: markos)

Cumulative AD

#10:42 Mobius:
# Cumulative AD

declare lower;
plot Data = TotalSum(close("$ADSPD"));
plot "0" = 0;

Last edited:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

@markos Without a doubt, your posted code #1 is always on my charts whenever I trade. I know the forum participants would find this a very helpful tool!
Yup @tomsk I don't know how a day trader can operate without it. Knowing the daily bias is important to know whether to work the put or call side.
Are there any other posts about this that I could read up on to better understand what this is saying? thanks

How would i read that ?

Last edited by a moderator:
@Trading51 The important takeaway for you is that always pay attention to the market. Index component stocks are essentially "pawns". If the market is bearish, most index component stocks get bought up while if the scenario is bearish, most index component stocks get sold down.
@Trading51 There are a pile of market internals. Don't get hung up, keep it simple. ADSPD is the Daily Advance Decline Line for the S&P 500.
In the pic above, both the green and white label shows that there are currently 89 more stocks up than down. In the white label 'close' is the current price so that also says 89.

Why the high and low of the Green Label vs the Highest and lowest of the White Label are different because of the math in the codes. I won't take the time to figure it out as I use a simple label that just shows the current ADSPD, I don't day trade. It's up to you to decide which way to go.

If it shows a current level of 400, then 400 of the 500 S&P 500 stocks are currently up. If your position is moving down, there may OR may not be a reason.

Intraday price movement is considered random, keep that in mind.
@tomsk I got this from the TSL. Why might Mobius use aggWK on a daily chart? This is what I have on my chart.
# AD Label
# Mobius
# Chat Room Request 04.26.2016

input SYMB = "$ADSPD";

def Data = close(symbol = "$ADSPD", period = AggregationPeriod.WEEK);
addLabel(1, "AD = " + Data, if Data < 0
# End Code
@markos I just checked my files, not sure where you obtained your study from - directly from the chat or from JQ's archives or from somewhere else. Perhaps someone was playing with it and forgot to reset it. Even some of the variable names seem to be different. Here's what I have on mine, directly from the chat archives from 2016

# AD Label
# Mobius
# Chat Room Request 04.26.2016

input SYMB = "$ADSPD";

def AD = close(symbol = SYMB, period = AggregationPeriod.Day);
addLabel(1, "AD = " + AD, if AD < 0 then Color.RED else Color.GREEN);
# End Code
@tomsk Thanks for checking your archives. I don't know where I got it.
Maybe JQ's or UTC's OneNotes or StanL's Treepad files. Not sure, but thanks for straightening that out!
@San There are a group of ticker symbols that measure the underlying sentiment and health of the financial markets. Collectively these are known as market internals. Here is an analogy. If you are a pilot of a commercial jet airliner or even a captain of a passenger cruise liner, you absolutely need to have instrumentation to tell you the speed and other factors that help you make decisions for the duration of your journey so that your passengers remain safe on board. In a similar fashion, market internals gives traders information about the underlying state of the market, when it is safe to wander out and when it is best to stay defensive when trading the markets.

I found a relatively easy article on the Internet for beginners to understand market internals. It has easy to understand examples. Please note that there are a lot more that the article does not discuss but this should be sufficient to get you started in understanding the concept. Stay safe out there!
@tomsk ,Very good article, thanks for sharing! Do you consider up/ down volume, or is that a thing of the past because of short selling & hedging?
OR is that what the Tick and Trin help you divine?
I ask because of the markets that you and you trading partner(s) trade.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
314 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.