OptionVue's VXX Trading System

Back in 2012 Larry McMillan wrote about a system for trading the VXX & XIV in his newsletter based on the price difference between the first two months in VIX futures. If you understand how the ETNs are managed it isn't difficult to come up with your own rules to back test.

True, that's what Len Yates cites as his original motivation to study the topic. Developments and research since then result in systems that are much better than Larry's original system. For example, blending roll yield principles such as McMillan first discussed with measuring the volatility risk premium and momentum characteristics of price and roll yield changes improve upon a simple measurement of amount of contango or backwardation .
 
Chris:
For some reason I am no longer able to post files here, but here is a link.
Changes to the script:
2nd input now named "flavor"
flavor=0; Original implementation of cumulative difference in BM-FM VX Futures
flavor=1; Relative cumulative difference in BM-FM VX Futures
flavor=2; Absolute difference of BM-FM VX Futures (your request)
you may wish to turn off bubbles input for this;
The contango thinkscript for BM-FM VX futures plot.
http://tos.mx/wrCbV8


I like this view. Thnx for the suggestion!

Let me know if you spot issues, as I did very little verification.
Regards,
Gary

I am having trouble installing the script from the above link. Is it possible to post the file instead? many thanks!

Posted by AndrewC
 
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);
 
Thanks much GaryW for the quick response! very much appreciated!

Posted by AndrewC
 
I think this is the original paper Yates published years ago:

http://www.optionvue.com/files/Trading_the_VXX.pdf

After it came out I attempted to replicate the results but was unable to do so. Yates' backtesting methodology was a bit flawed and he made assumptions he shouldn't have (long XIV and short VXX are not mirror images, especially when the differences compound over time). I corresponded with him to point this out and his reply was basically "go away". He also has a bad habit of changing the model after experiencing a drawdown. While he calls it "improving" the system I call it over-fitting the data. Bottom line, in my opinion his system is far from robust.

I personally have subscribed to two newsletters/signal services for a couple years... vixstrategies.com and tradingvolatility.net... that trade XIV and VXX long-only. Both are the best I've come across and they both return in the ballpark of 120% average annual return and 35% drawdown. And they don't change their models after every drawdown. Plenty of good info on both websites regarding their approaches for those who wish to attempt to replicate their models for themself. Tradingvolatility.net has the more useful website with vol-related data, and you can monitor the signal intraday to watch for potential signal changes. (I have no connection to either site other than being a subscriber.)

Hope this helps...

Hi Chris, can you share more which of the two subscription services is better? do you trade the signal?

Posted by Alvin
 
Top
Contact Us