Earnings IV Crush Label

bp805

New member
I'm trying to create a study that will plot a chart bubble on the earnings date that will show what the % IV drop was from IV % prior to the earnings report to the IV % on the day after the report. The below code is what I came up with but not sure if it is correct or not. I also am getting an "expected double" error. Can anyone help figure this out? Also, is it possible to have this use the IV% from the soonest expiring options contract, or does the ImpVolatility() pull a different value than the soonest expiring contract? Thanks for any help that can be provided!

Code:
def isBefore = HasEarnings(EarningTime.BEFORE_MARKET);
def isAfter  = HasEarnings(EarningTime.AFTER_MARKET);

def vol = imp_volatility();
def beforevol = if isAfter then vol else if isBefore then vol[1] else 0;
def aftervol = if isAfter then vol[-1] else if isBefore then vol else 0;

def volcalc = (aftervol - beforevol) / beforevol;
def downvol = volcalc < 0;

AddChartBubble(downvol, high[1], "IV Crush: " + AsPercent(aftervol - beforevol) / beforevol, Color.YELLOW);
 

halcyonguy

Member
VIP
in the bubble function, the aspercent( ) formula is dividing by 0 (beforevol) , which causes n/a , which causes the error message

change your volcalc formula, to check for a 0 value. then use this variable in the bubble, instead of recreating the formula
Ruby:
  def volcalc =  if beforevol == 0  then 0 else  (AsPercent(aftervol - beforevol) / beforevol);

to help me find this, i added this to your code ,to see variable values on each bar

Ruby:
addchartbubble( 1, high, isbefore + "\n" + isafter + "\n" + volcalc, color.cyan, yes);

skRmHWJ.jpg
 
Last edited:

bp805

New member
in the bubble function, the aspercent( ) formula is dividing by 0 (beforevol) , which causes n/a , which causes the error message

change your volcalc formula, to check for a 0 value. then use this variable in the bubble, instead of recreating the formula
Ruby:
  def volcalc =  if beforevol == 0  then 0 else  (AsPercent(aftervol - beforevol) / beforevol);

to help me find this, i added this to your code ,to see variable values on each bar

Ruby:
addchartbubble( 1, high, isbefore + "\n" + isafter + "\n" + volcalc, color.cyan, yes);

skRmHWJ.jpg
I changed the code and replaced the volcalc line and the chart bubble line with your two suggested edits, but I still get an "expected double" error. What am I missing here?

Ruby:
def isBefore = HasEarnings(EarningTime.BEFORE_MARKET);
def isAfter  = HasEarnings(EarningTime.AFTER_MARKET);

def vol = imp_volatility();
def beforevol = if isAfter then vol else if isBefore then vol[1] else 0;
def aftervol = if isAfter then vol[-1] else if isBefore then vol else 0;


def volcalc =  if beforevol == 0  then 0 else  (AsPercent(aftervol - beforevol) / beforevol);

def downvol = volcalc < 0;

#AddChartBubble(downvol, high[1], "IV Crush: " + AsPercent(aftervol - beforevol) / beforevol, Color.YELLOW);

AddChartBubble( 1, high, isBefore + "\n" + isAfter + "\n" + volcalc, Color.CYAN, yes);
 

halcyonguy

Member
VIP
that's odd. it worked on mine. i don't see the issue in your code on my cell.... i will check back in an hour or so.
try to find the error code line, by starting at the last code line, and adding a # in front of the line. if the error still exists, move up and do the previous line.
 

Slippage

Active member
I'm trying to create a study that will plot a chart bubble on the earnings date that will show what the % IV drop was from IV % prior to the earnings report to the IV % on the day after the report. The below code is what I came up with but not sure if it is correct or not. I also am getting an "expected double" error. Can anyone help figure this out? Also, is it possible to have this use the IV% from the soonest expiring options contract, or does the ImpVolatility() pull a different value than the soonest expiring contract? Thanks for any help that can be provided!

Code:
def isBefore = HasEarnings(EarningTime.BEFORE_MARKET);
def isAfter  = HasEarnings(EarningTime.AFTER_MARKET);

You can't rely on those two HasEarnings() calls alone. Sometimes TOS doesn't know whether earnings is/was before or after the session. Look at Twitter's last few earnings and you'll find one like I'm saying. The solution is to make a call to HasEarnings() without specifying any parameter and make a judgement call about whether you want to treat that as before or after the session and likely no bubble will show when it should for the ones where the assumption is wrong.

Ruby:
def isAfter = HasEarnings(EarningTime.AFTER_MARKET);
def isBefore = HasEarnings() and !isAfter;

Your expected double error is because of your AsPercent() call which converts the number to a string of text. If you remove that the error goes away. You can apply whatever formatting you need in the AddChartBubble() call instead.

Ruby:
def isAfter = HasEarnings(EarningTime.AFTER_MARKET);
def isBefore = HasEarnings() and !isAfter;

def vol = imp_volatility();
def beforevol = if isAfter then vol else if isBefore then vol[1] else 0;
def aftervol = if isAfter then vol[-1] else if isBefore then vol else 0;

def volcalc =  if beforevol == 0 then 0 else (aftervol - beforevol) / beforevol;
def downvol = volcalc < 0;

AddChartBubble(downvol, high[1], "IV Crush: " + AsPercent(volcalc), Color.YELLOW);
 
Last edited:

bp805

New member
Ok, thank you both for the clarification.

I'm thinking that that due to the low %s that this script returns (AAPL IV crush on earnings is about -17% on average over the last 2 years) that imp_volatility() pulls the overall IV value of the ticker vs. the IV value for the closest options contract expiration (which is what I'm looking to achieve)? Is that correct? Is there any way to use the IV value for the soonest expiring options contract? See the pic below for clarification. (Wanting to use #1 instead of #2 in the picture if possible).

CHirjoO.jpg
 

Slippage

Active member
Looking at the ThinkScript Reference it looks like you might be able to cobble something together. Something like (untested, just writing this here)...

def v = imp_volatility(GetATMOption(GetSymbol(), GetYYYYMMDD()));

It looks like no default is supplied for the date so you'd have to experiment. See what it returns if you use GetYYYYMMDD(). If that returns something but not the upcoming expiration then you can use GetNextExpirationOption(String optionCode) to find the next expiration. Otherwise you might just have to hard code the date and keep updating it manually. There's other functions if you want ITM or OTM strikes.
 

halcyonguy

Member
VIP
You can't rely on those two HasEarnings() calls alone. Sometimes TOS doesn't know whether earnings is/was before or after the session. Look at Twitter's last few earnings and you'll find one like I'm saying. The solution is to make a call to HasEarnings() without specifying any parameter and make a judgement call about whether you want to treat that as before or after the session and likely no bubble will show when it should for the ones where the assumption is wrong.

Ruby:
def isAfter = HasEarnings(EarningTime.AFTER_MARKET);
def isBefore = HasEarnings() and !isAfter;

Your expected double error is because of your AsPercent() call which converts the number to a string of text. If you remove that the error goes away. You can apply whatever formatting you need in the AddChartBubble() call instead.

Ruby:
def isAfter = HasEarnings(EarningTime.AFTER_MARKET);
def isBefore = HasEarnings() and !isAfter;

def vol = imp_volatility();
def beforevol = if isAfter then vol else if isBefore then vol[1] else 0;
def aftervol = if isAfter then vol[-1] else if isBefore then vol else 0;

def volcalc =  if beforevol == 0 then 0 else (aftervol - beforevol) / beforevol;
def downvol = volcalc < 0;

AddChartBubble(downvol, high[1], "IV Crush: " + AsPercent(volcalc), Color.YELLOW);
thank you for correcting me. i learned something.
 

rad14733

Well-known member
VIP
I forgot to post after testing this the other night... What I found was that the error went away when the AddChartBubble() was commented out and also that both HasEarnings() calls returned 0... I didn't get any further, however, but that indicated an issue with HasEarnings()... I used AddLabel() to display the values being derived to get as far as I got...
 

bp805

New member
Here is the final of what I came up with. I added an average IV crush label at the top as well to average everything from each earnings report displayed. Found it odd also that there were instances were I got no value for a certain earnings date and thought that maybe the IV didn't drop on that specific report? So I added a bubble to calculate expansion of IV and magically it plotted a bubble for that given earnings report. (See AAPL for July and November reports of 2020).

Regarding the closest options series IV, I emailed the thinkscript desk at TOS asking if it was possible to get the options series IV. They said that they don't have a function that would return that value. I then asked how the options series IV is calculated and if putting that Imp_Volatility() calculation into a study would return the correct value...still waiting for a response.

So @Slippage, that is my next question I guess. Do you know how the options series IV is calculated (presumably some equation incorporating the overall IV)? If so, would it be possible then to calculate it and arrive at the closest expiring options series IV? Im guessing this data is maybe only available for the last year to be able to work with, but would be better than nothing. Thanks!

Ruby:
def isAfter = HasEarnings(EarningTime.AFTER_MARKET);
def isBefore = HasEarnings() and !isAfter;

def vol = imp_volatility();
def beforevol = if isAfter then vol else if isBefore then vol[1] else 0;
def aftervol = if isAfter then vol[-1] else if isBefore then vol else 0;

#Calculates % change of IV from day prior to the earnings date to the day after the report.
def volcalc =  if beforevol == 0 then 0 else (aftervol - beforevol) / beforevol;

#Defines # of positive or negative vol crush after earnings.
def negvolcalc = volcalc < 0;
def posvolcalc = volcalc > 0;

AddChartBubble(negvolcalc, high[1], "IV Crush: " + AsPercent(volcalc), Color.YELLOW);
AddChartBubble(posvolcalc, high[1], "IV Expansion: " + AsPercent(volcalc), color.green);

AddLabel(1,"Average IV Crush : " + aspercent(totalsum(volcalc)/(totalsum(negvolcalc) + totalsum(posvolcalc))), color.yellow);
 

bp805

New member
The below code will arrive at the current weekly options series IV. Doesn't look like it has any historical data, but I'm not certain. I replaced "def vol" in the code above with the code below, and changed the "vol" within the code to "series 1" but it didn't give me any results in the bubbles or label.

Ruby:
def series1 = if isNaN(SeriesVolatility(series = 1)) then series1[1] else SeriesVolatility(series = 1);
 

Similar threads

Top