Is there a way to graph a specific strike's implied volatility or price over time?

Jeff1383

New member
I use calendars a lot. I'm trying to avoid the long back leg getting IV crushed during my trade duration which is short term (14 days or less). It would be great to see if the strike and date I choosing for the long back leg is elevated in any way before I place the trade. Thanks -
 
Solution
There are limits to what TOS can do. Disclaimer: I have not run this script so check its function) Here is a hybrid script where you will have to manually input some option data from the options pages and run this script on the stock chart. Labels will help inform you of your initial request - how it works:

Example: you are considering an ES calendar:

Sell 7 DTE 6000 Call
Buy 21 DTE 6000 Call

Set your inputs:

frontIV = front option IV
backIV = back option IV
backIVRank = approximate IV rank of the back expiration
strikePrice = 6000
frontDTE = 7
backDTE = 21

Best setup:

Score 80+ = tradable
Score 90+ = excellent
Below 70 = usually skip

The unspoken truth: this will not perfectly “predict” IV crush, but it will stop you from...
There are limits to what TOS can do. Disclaimer: I have not run this script so check its function) Here is a hybrid script where you will have to manually input some option data from the options pages and run this script on the stock chart. Labels will help inform you of your initial request - how it works:

Example: you are considering an ES calendar:

Sell 7 DTE 6000 Call
Buy 21 DTE 6000 Call

Set your inputs:

frontIV = front option IV
backIV = back option IV
backIVRank = approximate IV rank of the back expiration
strikePrice = 6000
frontDTE = 7
backDTE = 21

Best setup:

Score 80+ = tradable
Score 90+ = excellent
Below 70 = usually skip

The unspoken truth: this will not perfectly “predict” IV crush, but it will stop you from buying obviously inflated back-leg volatility, which is where many calendars quietly lose.

Code:
# Calendar Quality Score
# Hybrid TOS Version
# Use on UNDERLYING chart, not option chart

declare lower;

input frontIV = 25.0;
input backIV = 22.0;
input backIVRank = 35.0;
input strikePrice = 6000.0;

input frontDTE = 7;
input backDTE = 21;

input ivLookback = 252;
input atrLength = 14;
input bbLength = 20;
input adxLength = 14;

input eventRisk =
{default No_Event, Event_After_Front_Expiration, Event_During_Trade};

input showLabels = yes;

# ----------------------------
# Manual IV Structure
# ----------------------------

def termSpread = frontIV - backIV;

def termScore =
    if termSpread >= 5 then 40
    else if termSpread >= 3 then 32
    else if termSpread >= 1 then 24
    else if termSpread >= 0 then 12
    else 0;

def backIVScore =
    if backIVRank < 30 then 25
    else if backIVRank < 50 then 20
    else if backIVRank < 70 then 10
    else 0;

# ----------------------------
# Expected Move / Strike Placement
# ----------------------------

def expectedMove = close * (backIV / 100) * Sqrt(backDTE / 365);
def strikeDistance = AbsValue(close - strikePrice);
def distPctEM = if expectedMove != 0 then strikeDistance / expectedMove else 999;

def strikeScore =
    if distPctEM <= 0.10 then 20
    else if distPctEM <= 0.25 then 15
    else if distPctEM <= 0.50 then 8
    else 0;

# ----------------------------
# Event Risk
# ----------------------------

def eventScore =
    if eventRisk == eventRisk.No_Event then 15
    else if eventRisk == eventRisk.Event_After_Front_Expiration then 8
    else 0;

# ----------------------------
# Regime / Realized Volatility
# ----------------------------

def atr = Average(TrueRange(high, close, low), atrLength);
def atrPct = atr / close * 100;

def bbMid = Average(close, bbLength);
def bbDev = StDev(close, bbLength);
def bbUpper = bbMid + 2 * bbDev;
def bbLower = bbMid - 2 * bbDev;
def bbWidth = if bbMid != 0 then (bbUpper - bbLower) / bbMid * 100 else 0;

def bbWidthAvg = Average(bbWidth, 50);
def compression = bbWidth < bbWidthAvg;

def adx = ADX(adxLength);

def ema21 = ExpAverage(close, 21);
def ema50 = ExpAverage(close, 50);

def controlledTrend =
    close > ema21 and ema21 > ema50 and adx >= 15 and adx <= 28;

def expansionRisk =
    adx > 30 and bbWidth > bbWidthAvg;

def regimeBonus =
    if compression then 10
    else if controlledTrend then 7
    else if expansionRisk then 0
    else 5;

# ----------------------------
# Final Score
# ----------------------------

def baseScore = termScore + backIVScore + strikeScore + eventScore;
def finalScore = baseScore + regimeBonus;

plot CalendarScore = finalScore;
CalendarScore.SetLineWeight(3);
CalendarScore.AssignValueColor(
    if finalScore >= 90 then Color.GREEN
    else if finalScore >= 80 then Color.LIGHT_GREEN
    else if finalScore >= 70 then Color.YELLOW
    else if finalScore >= 60 then Color.ORANGE
    else Color.RED
);

plot PassLine = 60;
PassLine.SetDefaultColor(Color.GRAY);
PassLine.SetStyle(Curve.SHORT_DASH);

plot GoodLine = 80;
GoodLine.SetDefaultColor(Color.DARK_GREEN);
GoodLine.SetStyle(Curve.SHORT_DASH);

# ----------------------------
# Labels
# ----------------------------

def gradeAPlus = finalScore >= 90;
def gradeA = finalScore >= 80 and finalScore < 90;
def gradeB = finalScore >= 70 and finalScore < 80;
def gradeC = finalScore >= 60 and finalScore < 70;

AddLabel(showLabels,
    "CALENDAR SCORE: " + Round(finalScore, 0),
    if finalScore >= 80 then Color.GREEN
    else if finalScore >= 70 then Color.YELLOW
    else if finalScore >= 60 then Color.ORANGE
    else Color.RED
);

AddLabel(showLabels,
    "GRADE: " +
    if gradeAPlus then "A+"
    else if gradeA then "A"
    else if gradeB then "B"
    else if gradeC then "C"
    else "PASS",
    if finalScore >= 80 then Color.GREEN
    else if finalScore >= 70 then Color.YELLOW
    else if finalScore >= 60 then Color.ORANGE
    else Color.RED
);

AddLabel(showLabels,
    "TERM SPREAD: " + Round(termSpread, 2) + " pts",
    if termSpread > 3 then Color.GREEN
    else if termSpread >= 0 then Color.YELLOW
    else Color.RED
);

AddLabel(showLabels,
    "BACK IV RANK: " + Round(backIVRank, 0),
    if backIVRank < 50 then Color.GREEN
    else if backIVRank < 70 then Color.YELLOW
    else Color.RED
);

AddLabel(showLabels,
    "EXPECTED MOVE: " + Round(expectedMove, 2),
    Color.CYAN
);

AddLabel(showLabels,
    "STRIKE DIST: " + Round(strikeDistance, 2) +
    " / " + Round(distPctEM * 100, 0) + "% EM",
    if distPctEM <= 0.25 then Color.GREEN
    else if distPctEM <= 0.50 then Color.YELLOW
    else Color.RED
);

AddLabel(showLabels,
    "REGIME: " +
    if compression then "COMPRESSION"
    else if controlledTrend then "CONTROLLED TREND"
    else if expansionRisk then "EXPANSION RISK"
    else "BALANCED",
    if compression or controlledTrend then Color.GREEN
    else if expansionRisk then Color.RED
    else Color.YELLOW
);

AddLabel(showLabels,
    "ACTION: " +
    if finalScore >= 80 then "CALENDAR OK"
    else if finalScore >= 70 then "SMALL / CAUTION"
    else "PASS",
    if finalScore >= 80 then Color.GREEN
    else if finalScore >= 70 then Color.YELLOW
    else Color.RED
);
 
Solution
I'd simplify everything into 5 labels that matter. Ignore the rest.

1. CALENDAR SCORE- This is the master label.

Ideal Reading:

CALENDAR SCORE = 85+

Tradeable = 75-84

Pass- Below 75

For ES, I personally wouldn't get excited below 80.

2. TERM SPREAD- This is the most important label.

TERM SPREAD = Front IV - Back IV

Excellent = +3 or higher

Example:

Front IV = 27
Back IV = 23

Spread = +4

You're selling richer volatility and buying cheaper volatility. That's exactly what you want.

Neutral= 0 to +2 (Still acceptable.)

Danger = Negative

Example:

Front IV = 21
Back IV = 24

Spread = -3

You're buying the expensive volatility. Usually pass.

3. BACK IV RANK = This tells you if your long leg is overpriced.

Best

BACK IV RANK < 40

Good = 40-60

Caution= 60-70

Avoid >70 (The long leg is vulnerable to IV crush.)

4. REGIME = This is where your Institutional Regime Engine comes in.

Best

REGIME = COMPRESSION

or

REGIME = CONTROLLED TREND

These are calendar-friendly.

Neutral = REGIME = BALANCED

Still okay.

Dangerous = REGIME = EXPANSION RISK

This often means:
  • CPI move
  • FOMC move
  • Breakout day
  • Trend acceleration

Calendars can get run over.

5. ACTION = This is the one label I'd actually trade from.

Green = ACTION = CALENDAR OK

Take the trade.

Yellow = ACTION = SMALL / CAUTION

Half size.

Red = ACTION = PASS

Move on.

What an A+ Setup Looks Like

You open ES and see:
CALENDAR SCORE = 92

TERM SPREAD = +4.5

BACK IV RANK = 28

REGIME = COMPRESSION

ACTION = CALENDAR OK

That is exactly the type of calendar I'd hunt.

What a Trap Looks Like
You see:

CALENDAR SCORE = 61

TERM SPREAD = -2

BACK IV RANK = 82

REGIME = EXPANSION RISK

ACTION = PASS

Even if the option chain looks attractive, the volatility structure is stacked against you.
 
One more Label(Important sentiment label)
Add this section right before the AddLabel() section:
Code:
# ----------------------------
# EDGE SCORE
# ----------------------------

def edgeValue =
    (if termSpread >= 5 then 50
     else if termSpread >= 3 then 40
     else if termSpread >= 1 then 30
     else if termSpread >= 0 then 15
     else 0)

    +

    (if backIVRank < 30 then 50
     else if backIVRank < 50 then 40
     else if backIVRank < 70 then 20
     else 0);

def strongEdge = edgeValue >= 80;
def moderateEdge = edgeValue >= 50 and edgeValue < 80;
def weakEdge = edgeValue < 50;

Then add this to bottom of label section:
Code:
AddLabel(showLabels,
    "EDGE: " +
    if strongEdge then "STRONG"
    else if moderateEdge then "MODERATE"
    else "WEAK",
    if strongEdge then Color.GREEN
    else if moderateEdge then Color.YELLOW
    else Color.RED
);
 
One more thing - TOS does not have a way to easily give you IVRank.
What IV Rank Actually Is

Formula:
IV Rank = (Current IV - Lowest IV)/(Highest IV - Lowest IV)× 100

Example:
Current IV = 22

52 Week High IV = 40
52 Week Low IV = 10

Then:
(22 - 10)/(40 - 10)×100= 40

So: IV Rank = 40
 

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

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
1962 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.
Back
Top