ThinkorSwim Earnings Date Indicator and Watchlist Column

esti0000

New member
VIP
thats a prebuilt scan already defined in TOS
I am using the prebuilt scanner but its not ideal I am hoping to refine it further. I want to build a scan that shows yesterdays AMO earnings and this mornings BMO earnings. I am trying to play earnings gaps.

One issue with the prebuilt scanner is that the previous days AMO earnings disappear as soon as the market opens.
 

mark0482

New member
VIP
Hello friends,
Great indicator, very useful, thank you
I have a question, do you know the similar indicator like above but with countdown to the rollover on contracts and expiration Friday on options?
It will be very useful to don't forgot about these days.
Best regards
 

stormy77

New member
Found this indicator created by Mobius while I was browsing the thinkScript Lounge. It adds two labels to your chart. One shows the next earning date for the stock. If the upcoming earning date is within five days, it will also add a bright red warning. It sort of acts as an attention grabber to let you know.

YWi7ai4.png


thinkScript Code

Code:
# Next Earnings Label
# Mobius

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;
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);

Shareable Link

https://tos.mx/FDrNKR

Warning: Some users have pointed out that this indicator and the data it provides may be inconsistent. An alternative script has been posted here.
This is EXACTLY what I wanted.
Is there a way to get the data directly and not from the chart? I don't normally use the daily aggregation so my dates are wrong.
can we not get the date via EarningTime function (the https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Corporate-Actions/HasEarnings) and then using the DaysFromDate function (https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Date---Time/DaysFromDate) to show the earnings date. and also ex-div date, regardless of what aggregation period I use, or regardless of how many bars expansion I have??
 

majidg

Member
@Sonima Ah! Now we are getting somewhere. I immediately see where the problem is. When this code was released in the ThinkScript Lounge months ago, several people pointed out that that code is FUBAR. Do not use that as it is inaccurate. Let me give you an example. Load the study that was posted in post #1 of this thread. Set your aggregation to DAILY and load up ticker symbol C. Just to be sure I have my expansion space set to 44.

What happens? Notice that that particular study reports that the next C earnings is on 12/33/2019. That is clearly wrong.

@BenTen Please take note and either DELETE or TAG that study as being inconsistent.

As a workaround, I have a study that I obtained from a long standing contributor in the ThinkScript Lounge. That study works much better and is an improved version over the original release that was created 4-5 years ago. It correctly reports that ticker C will report earnings in 25 days, on 1/14/2020.

Here is the code

Code:
# Next Earnings Date
# Paris
# 10.15.2019

# You have to have enough expansion area on your chart available to reach the actual Earnings date, so if you have 0 expansion area, an inconsistent date will be displayed

#HINT: watchlist label that shows days-to-earnings and next earnings date (if next earnings date is available).  Includes a visual alert if "EARNINGS TODAY"

#def allows you to teach ThinkScript new "words" to save time and typing by using your new "words" later in the code
def bn = BarNumber();
def na = Double.NaN;
def getNextEarnings = AbsValue(GetEventOffset(Events.EARNINGS, 0));
def findDay = GetDayOfMonth(GetYYYYMMDD());
def findMonth = GetMonth();
def findYear = GetYear();

#ThinkScript thinks in numbers, including converting dates into numbers and viewing each bar on the chart as a number.  Therefore you can use BarNumber to tell ThinkScript which bar, and use lines in ThinkScript code to 'trick' ThinkScript into displaying that daily bar in date format
def getNextEarningsBarNumber = if !isNaN(getNextEarnings) then bn + getNextEarnings else na;
def NextEarnings = bn == HighestAll(getNextEarningsBarNumber);
def getNextEarningsMonth = HighestAll(if NextEarnings then findMonth else na);
def getNextEarningsDay = HighestAll(if NextEarnings then findDay else na);
def getNextEarningsYear = HighestAll(if NextEarnings then findYear else na);

#plot tells ThinkScript what data you want displayed.  Hide() is used in this case because desired display is the label and not the numberic equivalent of the data
plot DaysToEarnings = getNextEarningsBarNumber;
DaysToEarnings.Hide();

AddLabel(getNextEarnings > 0, "Next Earnings: (" + getNextEarnings + (if getNextEarnings == 1 then " Day): " else " Days): ") + getNextEarningsMonth + "/" + getNextEarningsDay + "/" + AsPrice(getNextEarningsYear), Color.Pink);
AddLabel(getNextEarnings == 0, "  EARNINGS TODAY ", Color.Yellow);
# End Next Earnings Date
Hi, I used the above code, but I still get inconsistent data, I used expansion area of 10 to 30 days.
 

MerryDay

Administrative
Staff member
Staff
VIP
@majidg I rely heavily on the earnings date labels and do not have inconsistent data at all. My expansion area is 44. Adjust your expansion area and if still having issues, post a screenshot of your chart and label.
Below is a link of how to insert images into your post:
https://usethinkscript.com/threads/answers-to-commonly-asked-questions.6006/#post-58714

IdRCb2h.png

AlyuT91.png

Ruby:
# Next Earnings Date
# Paris
# 10.15.2019

## IMPORTANT!!!! 44 EXPANSION You have to have enough expansion area on your chart available to reach the actual Earnings date, so if you have 0 expansion area, an inconsistent date will be displayed

#HINT: watchlist label that shows days-to-earnings and next earnings date (if next earnings date is available).  Includes a visual alert if "EARNINGS TODAY"

#def allows you to teach ThinkScript new "words" to save time and typing by using your new "words" later in the code
def bn = BarNumber();
def na = Double.NaN;
def getNextEarnings = AbsValue(GetEventOffset(Events.EARNINGS, 0));
def findDay = GetDayOfMonth(GetYYYYMMDD());
def findMonth = GetMonth();
def findYear = GetYear();

#ThinkScript thinks in numbers, including converting dates into numbers and viewing each bar on the chart as a number.  Therefore you can use BarNumber to tell ThinkScript which bar, and use lines in ThinkScript code to 'trick' ThinkScript into displaying that daily bar in date format
def getNextEarningsBarNumber = if !isNaN(getNextEarnings) then bn + getNextEarnings else na;
def NextEarnings = bn == HighestAll(getNextEarningsBarNumber);
def getNextEarningsMonth = HighestAll(if NextEarnings then findMonth else na);
def getNextEarningsDay = HighestAll(if NextEarnings then findDay else na);
def getNextEarningsYear = HighestAll(if NextEarnings then findYear else na);

#plot tells ThinkScript what data you want displayed.  Hide() is used in this case because desired display is the label and not the numberic equivalent of the data
plot DaysToEarnings = getNextEarningsBarNumber;
DaysToEarnings.Hide();

DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Label2Green",  CreateColor(0, 200, 0)) ;
DefineGlobalColor("Violet", CreateColor (200, 125, 255)) ;
AddLabel(getNextEarnings > 0, "Next Earnings: (" + getNextEarnings + (if getNextEarnings == 1 then " Day): " else " Days): ") + getNextEarningsMonth + "/" + getNextEarningsDay + "/" + AsPrice(getNextEarningsYear),
if getNextEarnings > 5 then GlobalColor("Violet") else GlobalColor("LabelGreen"));
AddLabel(getNextEarnings == 0, "  EARNINGS TODAY ", GlobalColor("Pre_Cyan"));
# End Next Earnings Date
Ruby:
# Script displays earnings and securities reaction to the announcement
#Developed and Coded By Eric Rasmussen
# [email protected]
# IMPORTANT 44 EXPANSION
# 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.plum);

# Percentage of Earnings Beats Label
DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Label2Green",  CreateColor(0, 200, 0)) ;

input beatRatioLabel = yes;
AddLabel(beatRatioLabel, Concat(Concat("Earnings Beats: ", beatRatio), "%"), color =
if beatRatio >= 100 then GlobalColor("Pre_Cyan")  else
if beatRatio >= 80 then GlobalColor("LabelGreen") else
if beatRatio >= 55 then color.gray else
GlobalColor("LabelRed"));
 

majidg

Member
@majidg I rely heavily on the earnings date labels and do not have inconsistent data at all. My expansion area is 44. Adjust your expansion area and if still having issues, post a screenshot of your chart and label.
Below is a link of how to insert images into your post:
https://usethinkscript.com/threads/answers-to-commonly-asked-questions.6006/#post-58714

IdRCb2h.png

AlyuT91.png

Ruby:
# Next Earnings Date
# Paris
# 10.15.2019

## IMPORTANT!!!! 44 EXPANSION You have to have enough expansion area on your chart available to reach the actual Earnings date, so if you have 0 expansion area, an inconsistent date will be displayed

#HINT: watchlist label that shows days-to-earnings and next earnings date (if next earnings date is available).  Includes a visual alert if "EARNINGS TODAY"

#def allows you to teach ThinkScript new "words" to save time and typing by using your new "words" later in the code
def bn = BarNumber();
def na = Double.NaN;
def getNextEarnings = AbsValue(GetEventOffset(Events.EARNINGS, 0));
def findDay = GetDayOfMonth(GetYYYYMMDD());
def findMonth = GetMonth();
def findYear = GetYear();

#ThinkScript thinks in numbers, including converting dates into numbers and viewing each bar on the chart as a number.  Therefore you can use BarNumber to tell ThinkScript which bar, and use lines in ThinkScript code to 'trick' ThinkScript into displaying that daily bar in date format
def getNextEarningsBarNumber = if !isNaN(getNextEarnings) then bn + getNextEarnings else na;
def NextEarnings = bn == HighestAll(getNextEarningsBarNumber);
def getNextEarningsMonth = HighestAll(if NextEarnings then findMonth else na);
def getNextEarningsDay = HighestAll(if NextEarnings then findDay else na);
def getNextEarningsYear = HighestAll(if NextEarnings then findYear else na);

#plot tells ThinkScript what data you want displayed.  Hide() is used in this case because desired display is the label and not the numberic equivalent of the data
plot DaysToEarnings = getNextEarningsBarNumber;
DaysToEarnings.Hide();

DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Label2Green",  CreateColor(0, 200, 0)) ;
DefineGlobalColor("Violet", CreateColor (200, 125, 255)) ;
AddLabel(getNextEarnings > 0, "Next Earnings: (" + getNextEarnings + (if getNextEarnings == 1 then " Day): " else " Days): ") + getNextEarningsMonth + "/" + getNextEarningsDay + "/" + AsPrice(getNextEarningsYear),
if getNextEarnings > 5 then GlobalColor("Violet") else GlobalColor("LabelGreen"));
AddLabel(getNextEarnings == 0, "  EARNINGS TODAY ", GlobalColor("Pre_Cyan"));
# End Next Earnings Date
Ruby:
# Script displays earnings and securities reaction to the announcement
#Developed and Coded By Eric Rasmussen
# [email protected]
# IMPORTANT 44 EXPANSION
# 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.plum);

# Percentage of Earnings Beats Label
DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Label2Green",  CreateColor(0, 200, 0)) ;

input beatRatioLabel = yes;
AddLabel(beatRatioLabel, Concat(Concat("Earnings Beats: ", beatRatio), "%"), color =
if beatRatio >= 100 then GlobalColor("Pre_Cyan")  else
if beatRatio >= 80 then GlobalColor("LabelGreen") else
if beatRatio >= 55 then color.gray else
GlobalColor("LabelRed"));

@majidg I rely heavily on the earnings date labels and do not have inconsistent data at all. My expansion area is 44. Adjust your expansion area and if still having issues, post a screenshot of your chart and label.
Below is a link of how to insert images into your post:
https://usethinkscript.com/threads/answers-to-commonly-asked-questions.6006/#post-58714

IdRCb2h.png

AlyuT91.png

Ruby:
# Next Earnings Date
# Paris
# 10.15.2019

## IMPORTANT!!!! 44 EXPANSION You have to have enough expansion area on your chart available to reach the actual Earnings date, so if you have 0 expansion area, an inconsistent date will be displayed

#HINT: watchlist label that shows days-to-earnings and next earnings date (if next earnings date is available).  Includes a visual alert if "EARNINGS TODAY"

#def allows you to teach ThinkScript new "words" to save time and typing by using your new "words" later in the code
def bn = BarNumber();
def na = Double.NaN;
def getNextEarnings = AbsValue(GetEventOffset(Events.EARNINGS, 0));
def findDay = GetDayOfMonth(GetYYYYMMDD());
def findMonth = GetMonth();
def findYear = GetYear();

#ThinkScript thinks in numbers, including converting dates into numbers and viewing each bar on the chart as a number.  Therefore you can use BarNumber to tell ThinkScript which bar, and use lines in ThinkScript code to 'trick' ThinkScript into displaying that daily bar in date format
def getNextEarningsBarNumber = if !isNaN(getNextEarnings) then bn + getNextEarnings else na;
def NextEarnings = bn == HighestAll(getNextEarningsBarNumber);
def getNextEarningsMonth = HighestAll(if NextEarnings then findMonth else na);
def getNextEarningsDay = HighestAll(if NextEarnings then findDay else na);
def getNextEarningsYear = HighestAll(if NextEarnings then findYear else na);

#plot tells ThinkScript what data you want displayed.  Hide() is used in this case because desired display is the label and not the numberic equivalent of the data
plot DaysToEarnings = getNextEarningsBarNumber;
DaysToEarnings.Hide();

DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Label2Green",  CreateColor(0, 200, 0)) ;
DefineGlobalColor("Violet", CreateColor (200, 125, 255)) ;
AddLabel(getNextEarnings > 0, "Next Earnings: (" + getNextEarnings + (if getNextEarnings == 1 then " Day): " else " Days): ") + getNextEarningsMonth + "/" + getNextEarningsDay + "/" + AsPrice(getNextEarningsYear),
if getNextEarnings > 5 then GlobalColor("Violet") else GlobalColor("LabelGreen"));
AddLabel(getNextEarnings == 0, "  EARNINGS TODAY ", GlobalColor("Pre_Cyan"));
# End Next Earnings Date
Ruby:
# Script displays earnings and securities reaction to the announcement
#Developed and Coded By Eric Rasmussen
# [email protected]
# IMPORTANT 44 EXPANSION
# 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.plum);

# Percentage of Earnings Beats Label
DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Label2Green",  CreateColor(0, 200, 0)) ;

input beatRatioLabel = yes;
AddLabel(beatRatioLabel, Concat(Concat("Earnings Beats: ", beatRatio), "%"), color =
if beatRatio >= 100 then GlobalColor("Pre_Cyan")  else
if beatRatio >= 80 then GlobalColor("LabelGreen") else
if beatRatio >= 55 then color.gray else
GlobalColor("LabelRed"));
Thanks a lot, by changing the expansion time, I can consistently obtain the next earrings date
 

bigshow3

New member
Found this indicator created by Mobius while I was browsing the thinkScript Lounge. It adds two labels to your chart. One shows the next earning date for the stock. If the upcoming earning date is within five days, it will also add a bright red warning. It sort of acts as an attention grabber to let you know.

YWi7ai4.png


thinkScript Code

Code:
# Next Earnings Label
# Mobius

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;
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);

Shareable Link

https://tos.mx/FDrNKR

Warning: Some users have pointed out that this indicator and the data it provides may be inconsistent. An alternative script has been posted here.
@BenTen is there an indicator like this that has labels for how many trading days till options expiration?
 

FLTrader

New member
VIP
If someone could please help, i would greatly appreciate it.
I'm only seeing one of the labels and date is wrong.
l2EvU4q.gif
 

Nick

Active member
2019 Donor
VIP




@MerryDay I like the earnings labels very much as it gives me a quick check on the company growth. For strong stocks, I like to see consistent rising EPS growth for at least 3 qtr and Sales growth as well. Like to clarify if my interpretation of the earnings label is correct.

Background, PTON missed their earnings last week but the label shows beats earnings 75% (used on 1year Daily) and 50%(used on 6mths daily)

# 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);

May I know if the beatRatio is calculated based on the number of times in beats earnings for 1yr or 6mths respectively? Does it count the latest earning result? Is that the correct way of interpreting??

If I want to show how many times in 1yr the stock has missed earnings, I just need to change the condition here
def beatRatio = Round((TotalSum(EarningsMiss) / earningsSum) * 100); and it will show how many times it missed earnings

Is there a way to compare and show a label the difference between the current qtr earnings and the previous qtr ?

Thanks
 

skputts

New member
@Sonima Ah! Now we are getting somewhere. I immediately see where the problem is. When this code was released in the ThinkScript Lounge months ago, several people pointed out that that code is FUBAR. Do not use that as it is inaccurate. Let me give you an example. Load the study that was posted in post #1 of this thread. Set your aggregation to DAILY and load up ticker symbol C. Just to be sure I have my expansion space set to 44.

What happens? Notice that that particular study reports that the next C earnings is on 12/33/2019. That is clearly wrong.

@BenTen Please take note and either DELETE or TAG that study as being inconsistent.

As a workaround, I have a study that I obtained from a long standing contributor in the ThinkScript Lounge. That study works much better and is an improved version over the original release that was created 4-5 years ago. It correctly reports that ticker C will report earnings in 25 days, on 1/14/2020.

Here is the code

Code:
# Next Earnings Date
# Paris
# 10.15.2019

# You have to have enough expansion area on your chart available to reach the actual Earnings date, so if you have 0 expansion area, an inconsistent date will be displayed

#HINT: watchlist label that shows days-to-earnings and next earnings date (if next earnings date is available).  Includes a visual alert if "EARNINGS TODAY"

#def allows you to teach ThinkScript new "words" to save time and typing by using your new "words" later in the code
def bn = BarNumber();
def na = Double.NaN;
def getNextEarnings = AbsValue(GetEventOffset(Events.EARNINGS, 0));
def findDay = GetDayOfMonth(GetYYYYMMDD());
def findMonth = GetMonth();
def findYear = GetYear();

#ThinkScript thinks in numbers, including converting dates into numbers and viewing each bar on the chart as a number.  Therefore you can use BarNumber to tell ThinkScript which bar, and use lines in ThinkScript code to 'trick' ThinkScript into displaying that daily bar in date format
def getNextEarningsBarNumber = if !isNaN(getNextEarnings) then bn + getNextEarnings else na;
def NextEarnings = bn == HighestAll(getNextEarningsBarNumber);
def getNextEarningsMonth = HighestAll(if NextEarnings then findMonth else na);
def getNextEarningsDay = HighestAll(if NextEarnings then findDay else na);
def getNextEarningsYear = HighestAll(if NextEarnings then findYear else na);

#plot tells ThinkScript what data you want displayed.  Hide() is used in this case because desired display is the label and not the numberic equivalent of the data
plot DaysToEarnings = getNextEarningsBarNumber;
DaysToEarnings.Hide();

AddLabel(getNextEarnings > 0, "Next Earnings: (" + getNextEarnings + (if getNextEarnings == 1 then " Day): " else " Days): ") + getNextEarningsMonth + "/" + getNextEarningsDay + "/" + AsPrice(getNextEarningsYear), Color.Pink);
AddLabel(getNextEarnings == 0, "  EARNINGS TODAY ", Color.Yellow);
# End Next Earnings Date
This flashes back and forth with 2 different dates and doesn't come up as a study I can use in a watchlist? Thanks and I am brand new here.
 

skputts

New member
This flashes back and forth with 2 different dates and doesn't come up as a study I can use in a watchlist? Thanks and I am brand new here.
I changed the expansion area and now it does not flash back and forth on charts. Still cannot see this as a study I can use in watchlists. Any ideas. Thank you.
 

Similar threads

Top