AndrewC:
Here is a text of the current version of that script. (VX front and next month Contango):
# Display Contango relationship between the Front and Back Month
# VX Futures.
# This removes the VIX absolute level, to allow visiability of the
# contango only.
# This is merely the Back Month VX futures minus the Front Month
# VX futures.
# Inflections of positive to negative and visa versa are flaged and
# enumerated.
# By Gary Whitlock
# Sep 2016
# 3/12/17 Added support for "
http://seekingalpha.com/article/3958001-modified-volatility-pair-trading-strategy"
# observations.
# 4/10/2017: GCW: Cleaned up input configuration.
#input bubles = 0;
input configuration = {default percent, commulative };
input Threshold_shortVol = 6.77;
input Threshold_longVol = 0; # 2.90; The URL above uses 2.90 for this threshold,
# Default is Contango threshold (zero)
declare lower;
# Below flags the date for expiring FrontMonth VX Futures per CBOE specs.
# Note: Regardding the Holidays, only one occurrance since 2010, which is
# hard coded in line below.
# For some unknown reason, TOS does not respond to daily VX futures per
# specification before August 2010, so data seems valid after Aug 2010.
# In debugging this, observed that TOS has some issues. Sometimes TOS misses
# complete trading days of info, the "/VX" reference in TOS does not
# match the CBOE spec for settlement, so beware. The TOS "opportunities"
# seem to be dynamic (not static bugs). At the time of this note, TOS
# inferred no trading of "/VX" between 7/16/2013 and 7/22/2016. (Missing 3 days of trading)
script VXexp {
def date = GetYYYYMMDD();
def isholiday = date == 20140319; # Manual injection of holiday on 4/18/14 which alteres VX settlement date in March.
def n3rdfa = Next3rdFriday(1);
def n3rdfb = Next3rdFriday(2);
def n3rdf = if (n3rdfa < 4) then n3rdfb else n3rdfa; # Pick Next month's expiration, not this month.
plot VXexp = if (isholiday) then 1 else ((n3rdf == 30) and !isholiday[1]);#and (dow == 3);
} # End of script for VXexp
# LsD extracts least significant digit of the number (date)
script LsD {
input date = 20100101;
plot LsD = (date - RoundDown(date / 10, 0) * 10);
} # End of script for LsD
def InContango;
def NotContango;
def ContangoBias;
def fm;
def bm;
def date = GetYYYYMMDD();
def dom = GetDayOfMonth(date);
def newmo = dom < dom[1];
def incmo = if newmo then 0 else if VXexp() then 1 else incmo[1];
def Y_ = GetYear();
def Y = LsD(Y_);
def MM = GetMonth();
fm = if (MM + incmo) > 12 then 1 else (MM + incmo) ;
def fmchange = fm != fm[1];
def fmY = if fmchange then (if (MM + incmo) > 12 then LsD(Y + 1) else Y) else fmY[1];
bm = if (fm + 1) > 12 then 1 else (fm + 1) ;
def bmY = if fmchange then (if (bm < 3) then LsD(Y + 1) else Y) else bmY[1];
def fmp = close( "/VX" + (if fm == 1 then "F" else
if fm == 2 then "G" else
if fm == 3 then "H" else
if fm == 4 then "J" else
if fm == 5 then "K" else
if fm == 6 then "M" else
if fm == 7 then "N" else
if fm == 8 then "Q" else
if fm == 9 then "U" else
if fm == 10 then "V" else
if fm == 11 then "X" else
if fm == 12 then "Z" else " ") + fmY);
def bmp = close( "/VX" + (if bm == 1 then "F" else
if bm == 2 then "G" else
if bm == 3 then "H" else
if bm == 4 then "J" else
if bm == 5 then "K" else
if bm == 6 then "M" else
if bm == 7 then "N" else
if bm == 8 then "Q" else
if bm == 9 then "U" else
if bm == 10 then "V" else
if bm == 11 then "X" else
if bm == 12 then "Z" else " ") + bmY);
# TOS may miss some vx futures quotes, so if this occurs
# re-use the prior day close for the missing entry.
# The filter below accomplishes this.
def fmpfiltered = if IsNaN(fmp) then fmpfiltered[1] else fmp;
def bmpfiltered = if IsNaN(bmp) then bmpfiltered[1] else bmp;
def reladj = if (bmpfiltered > 0) then bmpfiltered else 1;
def AbsDiffContango = if (BarNumber() < 5) then 0 else (if (configuration == configuration.commulative) then (bmpfiltered - fmpfiltered) / reladj else (bmpfiltered - fmpfiltered));
ContangoBias = if (BarNumber() < 5) then 0 else ContangoBias[1] + (if (configuration == configuration.commulative) then (bmpfiltered - fmpfiltered) / reladj else (bmpfiltered - fmpfiltered));
def bmfmReference=bmpfiltered; # bmpfiltered;
plot FmBmContango = if IsNaN(fmp) then Double.NaN
else if (configuration == configuration.percent) then Double.NaN else ContangoBias;
def ContanoPerCentage = 100 * AbsDiffContango / bmfmReference;
#def ContanoPerCentage = 100 * AbsDiffContango / bmpfiltered;
FmBmContango.DefineColor("green", Color.GREEN);
FmBmContango.DefineColor("red", Color.RED);
FmBmContango.DefineColor("white", Color.WHITE);
plot Cper = if ((configuration == configuration.percent) and (IsNaN(fmp)==0)) then ContanoPerCentage else Double.NaN;
Cper.DefineColor("green", Color.GREEN);
Cper.DefineColor("red", Color.RED);
Cper.DefineColor("white", Color.WHITE);
Cper.AssignValueColor(if (ContanoPerCentage > Threshold_shortVol) then Cper.Color("green") else if (ContanoPerCentage > Threshold_longVol) then Cper.Color("white") else Cper.Color("red"));
Cper.SetPaintingStrategy(PaintingStrategy.POINTS);
def Direction = ContangoBias > ContangoBias[1];
def DirectionChanges = if (BarNumber() == 1) then 0 else if (Direction != Direction[1]) then DirectionChanges[1] + 1 else DirectionChanges[1];
FmBmContango.AssignValueColor(if (ContangoBias > ContangoBias[1]) then FmBmContango.Color("green") else if (ContangoBias == ContangoBias[1]) then FmBmContango.Color("white") else FmBmContango.Color("red"));
FmBmContango.SetPaintingStrategy(PaintingStrategy.POINTS);
InContango = if ((BarNumber() == 1) or (DirectionChanges < 1)) then 0 else InContango[1] + (bmpfiltered > fmpfiltered);
NotContango = if ((BarNumber() == 1) or (DirectionChanges < 1)) then 0 else NotContango[1] + (bmpfiltered <= fmpfiltered);
plot UpperThreshold = if (configuration ==configuration.percent) then Threshold_shortVol else Double.nan;
plot LowerThreshold = if (configuration ==configuration.percent) then Threshold_longVol else Double.nan;
AddLabel(1, Concat("Contango inflections : ", DirectionChanges) + ", Time(bars) in Contango: " + InContango + " of " + BarNumber()+" (" + aspercent(InContango/ (InContango + NotContango))+") " + if (configuration==configuration.commulative) then "), Bars in Backwardation or same: "+ NotContango else "" , Color.GRAY);
AddLabel((configuration == configuration.percent), "" +aspercent(AbsDiffContango / bmfmReference), Cper.TakeValueColor());
AddChartBubble((configuration == configuration.commulative) and Direction and !Direction[1], ContangoBias, DirectionChanges, Color.GRAY, 1);
AddChartBubble((configuration == configuration.commulative) and !Direction and Direction[1], ContangoBias, DirectionChanges, Color.YELLOW, 0);
AddVerticalLine(VXexp(), "VX" + (if bm == 1 then "F" else
if bm == 2 then "G" else
if bm == 3 then "H" else
if bm == 4 then "J" else
if bm == 5 then "K" else
if bm == 6 then "M" else
if bm == 7 then "N" else
if bm == 8 then "Q" else
if bm == 9 then "U" else
if bm == 10 then "V" else
if bm == 11 then "X" else
if bm == 12 then "Z" else " ") + bmY
+ (if (configuration==configuration.percent) then " vs VX" else " - VX") + (if fm == 1 then "F" else
if fm == 2 then "G" else
if fm == 3 then "H" else
if fm == 4 then "J" else
if fm == 5 then "K" else
if fm == 6 then "M" else
if fm == 7 then "N" else
if fm == 8 then "Q" else
if fm == 9 then "U" else
if fm == 10 then "V" else
if fm == 11 then "X" else
if fm == 12 then "Z" else " ") + fmY, Color.DARK_GREEN);#color.light_orange);