Earnings, Dividend and P/E Labels for ThinkorSwim


Well-known member
Posted via the thinkScript lounge by Nube.

22:40 Nube: Price to Earnings lines have come up a few times without a good answer. This isn't a good answer either, but it shows one way to do it. This will draw lines for 5 input PE values at the 2 most recent earnings releases. If someone desires the lines going further back, they can expand the script using more of the same logic

Here's the code:

# Earnings, Dividend and P/E Labels
# Nube
# v01 7.3.18
# http://tos.mx/ieYc5f#
#hint: Displays the previous annual earnings for the 2 most recent quarters and the previous 4 dividends in labels as well as 5 user selectable P/E values for two most recent quarters. Method can be duplicated to draw PE lines for previous quarters.

declare hide_on_intraday;

input PEOne   = 9;
input PETwo   = 13;
input PEThree = 15;
input PEFour  = 16;
input PEFive  = 18;

def c  = close;
def na = Double.NaN;
def bn = BarNumber();
def Earnings = GetActualEarnings();
def Dividend = GetDividend();

def currentBar = if   !IsNaN(c) and IsNaN(c[-1])
                 then bn
                 else currentBar[1];
    # section below identifies the bars at which earnings were released
def earningsBar = if   !IsNaN(Earnings)
                  then bn
                  else earningsBar[1];
def prevEarningsBar1 = if   earningsBar != earningsBar[1]
                       then earningsBar[1]
                       else prevEarningsBar1[1];
def prevEarningsBar2 = if   prevEarningsBar1 != prevEarningsBar1[1]
                       then prevEarningsBar1[1]
                       else prevEarningsBar2[1];
def prevEarningsBar3 = if   prevEarningsBar2 != prevEarningsBar2[1]
                       then prevEarningsBar2[1]
                       else prevEarningsBar3[1];
def prevEarningsBar4 = if   prevEarningsBar3 != prevEarningsBar3[1]
                       then prevEarningsBar3[1]
                       else prevEarningsBar4[1];
    # identifies the which bars are the previous 1,2,3 etc earnings bars as of the current time
def hEB   = HighestAll(earningsBar);
def hpEB1 = HighestAll(prevEarningsBar1);
def hpEB2 = HighestAll(prevEarningsBar2);
def hpEB3 = HighestAll(prevEarningsBar3);
def hpEB4 = HighestAll(prevEarningsBar4);
    # getting the four most recent earnings values
def currentEarnings = if   bn == hEB
                      then Earnings
                      else currentEarnings[1];
def secondEarnings  = if   bn == hEB
                      then GetValue(Earnings, hEB - prevEarningsBar1)
                      else secondEarnings[1];
def thirdEarnings   = if   bn == hEB
                      then GetValue(Earnings, hEB - prevEarningsBar2)
                      else thirdEarnings[1];
def fourthEarnings  = if   bn == hEB
                      then GetValue(Earnings, hEB - prevEarningsBar3)
                      else fourthEarnings[1];
    # getting 4 earnings values up until second most recent earnings bar
def lQfirstEarnings   = if   bn == hpEB1
                      then Earnings
                      else lQfirstEarnings[1];
def lQsecondEarnings   = if   bn == hpEB1
                      then GetValue(Earnings, hpEB1 - hpEB2)
                      else lQsecondEarnings[1];
def lQthirdEarnings = if   bn == hpEB1
                      then GetValue(Earnings, hpEB1 - hpEB3)
                      else lQthirdEarnings[1];
def lQfourthEarnings  = if   bn == hpEB1
                      then GetValue(Earnings, hpEB1 - hpEB4)
                      else lQfourthEarnings[1];

def currentAnnualEarnings = currentEarnings + secondEarnings + thirdEarnings + fourthEarnings;
def lastQannualEarning = lQfirstEarnings + lQsecondEarnings + lQthirdEarnings + lQfourthEarnings;
def cAE  = currentAnnualEarnings;
def lQaE = lastQannualEarning;
def annualEarnings = if   bn == hpEB1
                     then lQaE
                     else if bn == hEB
                          then cAE
                          else annualEarnings[1];
def AE = annualEarnings; 
def PE = c / AE;
    # same process for getting the dividend bars
def dividendBar      = if   !IsNaN(Dividend)
                       then bn
                       else dividendBar[1];
def prevDividendBar1 = if   DividendBar != DividendBar[1]
                       then DividendBar[1]
                       else prevDividendBar1[1];
def prevDividendBar2 = if   prevDividendBar1 != prevDividendBar1[1]
                       then prevDividendBar1[1]
                       else prevDividendBar2[1];
def prevDividendBar3 = if   prevDividendBar2 != prevDividendBar2[1]
                       then prevDividendBar2[1]
                       else prevDividendBar3[1];
    # again, same process for getting the dividend values
def currentDividend  = if   bn == DividendBar
                       then Dividend
                       else currentDividend[1];
def secondDividend = GetValue(Dividend, currentBar - prevDividendBar1);
def thirdDividend  = GetValue(Dividend, currentBar - prevDividendBar2);
def fourthDividend = GetValue(Dividend, currentBar - prevDividendBar3);
def annualDividend = currentDividend + secondDividend + thirdDividend + fourthDividend;
def AD = annualDividend;
def yield = AD / c;

"P/E 1" = AE * PEOne;
"P/E 1".  SetDefaultColor(CreateColor(100,225,100));
"P/E 1".  SetPaintingStrategy(PaintingStrategy.DASHES);

"P/E 2" = AE * PETwo;
"P/E 2".  SetDefaultColor(CreateColor(75,175,225));
"P/E 2".  SetPaintingStrategy(PaintingStrategy.DASHES);

"P/E 3" = AE * PEThree;
"P/E 3".  SetDefaultColor(CreateColor(250,175,50));
"P/E 3".  SetPaintingStrategy(PaintingStrategy.DASHES);

"P/E 4" = AE * PEFour;
"P/E 4".  SetDefaultColor(CreateColor(200,100,200));
"P/E 4".  SetPaintingStrategy(PaintingStrategy.DASHES);

"P/E 5" = AE * PEFive;
"P/E 5".  SetDefaultColor(CreateColor(225,100,100));
"P/E 5".  SetPaintingStrategy(PaintingStrategy.DASHES);

def locate = !IsNaN(c[3]) && IsNaN(c[2]);
AddChartBubble(locate, "P/E 1", "P/E: "+PEOne+ "\n$"+"P/E 1",
AddChartBubble(locate, "P/E 2", "P/E: "+PETwo+ "\n$"+"P/E 2",
AddChartBubble(locate, "P/E 3", "P/E: "+PEThree+ "\n$"+"P/E 3",
AddChartBubble(locate, "P/E 4", "P/E: "+PEFour+ "\n$"+"P/E 4",
AddChartBubble(locate, "P/E 5", "P/E: "+PEFive+ "\n$"+"P/E 5",
Addlabel(1, "Earnings 1: $" +currentEarnings+" Earnings 2: $" +secondEarnings+" Earnings 3: $" +thirdEarnings+" Earnings 4: $" +fourthEarnings, CreateColor(200,200,100));
Addlabel(1, " Last Q Earnings 1: $" +lQfirstEarnings+" Last Q Earnings 2: $" +lQsecondEarnings+" Last Q Earnings 3: $" +lQthirdEarnings+" Last Q Earnings 4: $" +lQfourthEarnings, CreateColor(225,175,75));
Addlabel(1, "Dividend 1: $" +currentDividend+" Dividend 2: $"      +secondDividend+" Dividend 3: $" +thirdDividend+" Dividend 4: $" +fourthDividend, CreateColor(250,150,0)); 
AddLabel(1," Annual Earnings: $"+AE, CreateColor(100,225,100));
AddLabel(1," Annual Earnings Last Q: $"+lQaE, CreateColor(100,225,100));
AddLabel(1," Annual Dividend: $"+AD, CreateColor(100,225,100));
AddLabel(yes, "P/E Ratio: " + Round(PE,2),
AddLabel(yes, "Yield: " + AsPercent(yield),

# f/ Earnings, Dividend and P/E Labels

Ex-dividend Days Label
# WatchList of Label Days Till X Dividend
# If over 30 days away shows 30
# Mobius
input DaysTillXdiv = 30;

def LastDividendBar = AbsValue(GetEventOffset(Events.DIVIDEND, 0));
def NextDividend = if isNaN(LastDividendBar) then 0 else LastDividendBar;
AddLabel(NextDividend == DaysTillXdiv, "Dividend More than 30 days out", color.white);
AddLabel(NextDividend <= DaysTillXdiv-1 and NextDividend > 0, "Dividend in " + NextDividend + " days", Color.Red);
Last edited by a moderator:


Staff member
@Miket You can easily find this out by searching through the existing watchlist columns that ThinkorSwim provided.


Doesn't exist. It would be great to know when the date of record is to try to scalp some dividends.


Staff member
@Miket The TD app has it. You can try that or their webapp as well.



Hello friends,

Can anyone please watch the following webinar and create the Earning Hotzone indicator. It is looking cool and very helpful for trading earnings.

Thank you,


New member
Will be good if someone can indeed came up with the Earning Hotzone indicator. Possible to share if you have the thinkscript as I am interested to try it out as it looks promising.

Thank You


New member
Hello All,

I am new on this great community. I added the code to create the hotzones and labels on the one developed by Eric Rasmussen some time ago; is the first little script I do for TOS so feel free to improve the code or do some recommendations:

# Script displays earnings and securities reaction to the announcement, it displays a counter and hotzones

# HotZones added by Hugo Valencia

# Twitter: [USER=11164]@1HugoValencia[/USER]

# Finding the Earnings Dates

def isBefore = HasEarnings(EarningTime.BEFORE_MARKET);

def isAfter = HasEarnings(EarningTime.AFTER_MARKET);

# Earnings Move Up or Down

def afterCalc = AbsValue(Round(close[-1] - close));

def beforeCalc = AbsValue(Round(close - close[1]));

def afterAbs = if isAfter then Round(AbsValue(((close[-1] - close) / close) * 100)) else 0;

def beforeAbs =  if isBefore then Round(AbsValue(((close - close[1]) / close) * 100)) else 0;

def earningsPrice = if isAfter then afterCalc else if isBefore then beforeCalc else 0;

# Price Percent Calculations

def afterPercent = if isAfter then Round(((close[-1] - close) / close) * 100) else 0;

def beforePercent = if isBefore then Round(((close - close[1]) / close) * 100) else 0;

def earningsPercent = if isAfter then afterPercent else if isBefore then beforePercent else 0;

def absPercent = if isAfter then afterAbs else if isBefore then beforeAbs else 0;

# Records Number of Earnings Periods

def aMove = if HasEarnings(EarningTime.AFTER_MARKET) then TotalSum(earningsPrice) else aMove[1];

def bMove = if HasEarnings(EarningTime.BEFORE_MARKET) then TotalSum(earningsPrice) else bMove[1];

def earningsPeriods = if HasEarnings() then 1 else 0;

# Average Earnings Move calculation

def periodSum = Sum(earningsPeriods, length = 252);

def Sum = Sum(earningsPrice, length = 252);

def averageMove = Sum / periodSum;

def percentSum = Sum(absPercent, length = 252);

def percentAvg = percentSum / periodSum;

def avgMove = if !IsNaN(averageMove) then averageMove else avgMove[1];

def percentAvgMove = if !IsNaN(averageMove) then percentAvg else percentAvgMove[1];

# Actual Earnings and Estimates Info

def AECont = if HasEarnings() then GetActualEarnings() else AECont[1];

def EECont = if HasEarnings() then GetEstimatedEarnings() else EECont[1];

def actualEarnings = if !IsNaN(AECont) then AECont else actualEarnings[1];

def estimatedEarnings = if !IsNaN(EECont) then EECont else estimatedEarnings[1];

def EarningsBeat =  !IsNaN(GetActualEarnings()) and HasEarnings() and actualEarnings > estimatedEarnings;

def EarningsMiss =  !IsNaN(GetActualEarnings()) and HasEarnings() and actualEarnings < estimatedEarnings;

# Earnings Move Calculations

def aCalc =  Round(close[-1] - close);

def bCalc = Round(close - close[1]);

def ePrice = if isAfter then aCalc else if isBefore then bCalc else ePrice[1];

def earningsNaN = if HasEarnings() and IsNaN(GetEstimatedEarnings()) then 1 else earningsNaN[1];

def earningsSum = TotalSum(HasEarnings()) - earningsNaN;

def earningsMove =  if HasEarnings() then ePrice else earningsMove[1];

def uM = HasEarnings() and earningsMove > 0;

def dM = HasEarnings() and earningsMove < 0;

def beatRatio =  Round((TotalSum(EarningsBeat) / earningsSum) * 100);

# Look And Feel

# Average Move Label (Percentage)

input percentLabel = yes;

AddLabel(percentLabel, Concat(Concat("Average Earnings Move: ", Round(percentAvgMove, 2)), "%"), if earningsPrice[1] > avgMove[1] then Color.MAGENTA else Color.LIME);

# Percentage of Earnings Beats Label

input beatRatioLabel = yes;

AddLabel(beatRatioLabel, Concat(Concat("Earnings Beats: ", beatRatio), "%"), color = if beatRatio >= 80 then Color.GREEN else Color.RED);

# Bubbles Showing Percent Moves After Earnings

input percentBubbles = yes;

AddChartBubble("price location" = high, text = Concat(earningsPercent, "%"), "time condition" =  if percentBubbles == yes then earningsPercent else 0, color = if isAfter and close[-1] > close then Color.MAGENTA else if isAfter and close[-1] < close then Color.LIME else if isBefore and close > close[1] then Color.MAGENTA else if isBefore and close < close[1] then Color.LIME else Color.BLACK);

# Date Line for Earnings

input text = no;

AddVerticalLine(HasEarnings() and EarningsBeat and uM, color = Color.CYAN, stroke = Curve.FIRM, text = if text == yes then Concat(if isBefore then "(Before) " else "(After) ", Concat("$", Concat(EECont, Concat(" Actual", Concat("  $", Concat(AECont, " Estimated")))))) else "");

AddVerticalLine(HasEarnings() and EarningsBeat and dM, color = Color.MAGENTA, stroke = Curve.FIRM, text = if text == yes then Concat(if isBefore then "(Before) " else "(After) ", Concat("$", Concat(EECont, Concat(" Actual", Concat("  $", Concat(AECont, " Estimated")))))) else "");

AddVerticalLine(HasEarnings() and EarningsMiss and uM, color = Color.LIME, stroke = Curve.FIRM, text = if text == yes then Concat(if isBefore then "(Before) " else "(After) ", Concat("$", Concat(EECont, Concat(" Actual", Concat("  $", Concat(AECont, " Estimated")))))) else "");

AddVerticalLine(HasEarnings() and EarningsMiss and dM, color = Color.RED, stroke = Curve.FIRM, text = if text == yes then Concat(if isBefore then "(Before) " else "(After) ", Concat("$", Concat(EECont, Concat(" Actual", Concat("  $", Concat(AECont, " Estimated")))))) else "");

#Hotzones: Days before earnings

def Earnings = AbsValue(GetEventOffset(Events.Earnings, 0));

def NextEarnings = if isNaN(Earnings)

                   then 0

                   else Earnings;

def Month = getMonth();

def year = getYear();

def DOW = getDayOfWeek(getYYYYMMDD());

def today = getDayOfMonth(getYYYYMMDD());

def EarningDay = if NextEarnings + DOW <= 5

                 then NextEarnings + today

                 else if NextEarnings + DOw > 5

                 then NextEarnings + today + 2

                 else NextEarnings;

input Hotzone1 = 14;

input Hotzone2 = 21;

def HotZone1def = if Earnings <= Hotzone1 then Double.POSITIVE_INFINITY else Double.NaN;

def HotZone2def = if Earnings <= Hotzone2 and Earnings >= Hotzone1 then Double.POSITIVE_INFINITY else Double.NaN;

AddCloud(HotZone1def, -HotZone1def, Color.lIGHT_red, Color.current, yes);

AddCloud(HotZone2def, -HotZone2def, Color.lIGHT_green, Color.current, no);

AddLabel(1, "Next " + getSymbol() + " earnings " + Month + "/" + EarningDay + "/" + AsPrice(year), color.white);

AddLabel(NextEarnings < 30 and NextEarnings > 0,
        "Earnings in " + NextEarnings +
       " trading days", if NextEarnings <= 4
                then Color.Red
                else Color.White);
Notes: - I added labels.
- Make sure the Autoexpand to fix Corporate actions is set (under the Time axis tab)
Last edited:

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.