# ------------------------START BELOW THIS LINE-------------------------- # # tastytrade/dough Research Team # Michael Rechenthin, Ph.D. # Follow me on twitter: @mrechenthin # # IV Rank is a description of where the current IV lies in comparison # to its yearly high and low IV # # IV Percentile gives the percentage of days over the last year, that # were below the current IV. If the IV Rank is above 50%, then # the script will highlight it green; otherwise red. # # For information on the two, see Skinny on Options Data Science, # titled "IV Rank and IV Percentile (w/ thinkscript)" on Nov 12, 2015 # http://ontt.tv/1Nt4fcS # # version 3.2 # declare lower; declare hide_on_intraday; # do not display when using intra-day plots input days_back = 252; # it is most common to use 1-year (or 252 trading days) def x; if GetAggregationPeriod() > AggregationPeriod.DAY { x=1; } else { x=2; } AddLabel(yes, if (x==1) then "This script should be used on daily charts only" else ""); # implied volatility # using proxies for futures def df = if (GetSymbol() == "/ES") then close("VIX") / 100 else if (GetSymbol() == "/CL") then close("OIV") / 100 else if (GetSymbol() == "/GC") then close("GVX") / 100 else if (GetSymbol() == "/SI") then close("VXSLV") / 100 else if (GetSymbol() == "/NQ") then close("VXN") / 100 else if (GetSymbol() == "/TF") then close("RVX") / 100 else if (GetSymbol() == "/YM") then close("VXD") / 100 else if (GetSymbol() == "/6E") then close("EVZ") / 100 else if (GetSymbol() == "/6J") then close("JYVIX") / 100 else if (GetSymbol() == "/6B") then close("BPVIX") / 100 else if (GetSymbol() == "/ZN") then close("TYVIX") / 100 else if (Getsymbol() == "/ZW") then close("WIV") / 100 else if (Getsymbol() == "/ZB") then imp_volatility("TLT") else if (Getsymbol() == "/ZC") then imp_volatility("CORN") else if (Getsymbol() == "/ZS") then imp_volatility("SOYB") else if (Getsymbol() == "/KC") then imp_volatility("JO") else if (Getsymbol() == "/NG") then imp_volatility("UNG") else if (Getsymbol() == "/6S") then imp_volatility("FXF") else imp_volatility(); def df1 = if !IsNaN(df) then df else df[-1]; # display regular implied volatility # --------------------------- AddLabel(yes, "IV: " + Round(df1 * 100.0, 0), Color.ORANGE); # calculate the IV rank # --------------------------- # calculate the IV rank def low_over_timespan = Lowest(df1, days_back); def high_over_timespan = Highest(df1, days_back); def iv_rank = Round( (df1 - low_over_timespan) / (high_over_timespan - low_over_timespan) * 100.0, 0); AddLabel(yes, "IV Rank: " + iv_rank + "%", if iv_rank > 50 then Color.GREEN else Color.RED); # calculate the IV percentile # --------------------------- # how many times over the past year, has IV been below the current IV def counts_below = fold i = 1 to days_back + 1 with count = 0 do if df1[0] > df1[i] then count + 1 else count; def iv_percentile = Round(counts_below / days_back * 100.0, 0); plot IVs = df1 * 100; IVs.SetLineWeight(3); IVs.AssignValueColor(if iv_rank > 50 then Color.GREEN else Color.RED); AddLabel(yes, "IV Percentile: " + iv_percentile + "% of days were below the past year's IV", if iv_percentile > 50 then Color.GREEN else Color.RED); # thanks to Kevin Osborn for the following line AddLabel(yes, if (GetSymbol() == "/6S" or GetSymbol() == "/ZB" or GetSymbol() == "/ZC" or GetSymbol() == "/NG" or GetSymbol() == "/ZS" or GetSymbol() == "/KC") then "* ETF based" else "", Color.BLACK); # ------------------------END ABOVE THIS LINE--------------------------