This post deals with an impossible-to-implement statistical arbitrage strategy using VXX and XIV. The strategy is simple: if the average daily return of VXX and XIV was positive, short both of them at the close. This strategy makes two assumptions of varying dubiousness: that one can “observe the close and act on the close”, and that one can short VXX and XIV.

So, recently, I decided to play around with everyone’s two favorite instruments on this blog–VXX and XIV, with the idea that “hey, these two instruments are diametrically opposed, so shouldn’t there be a stat-arb trade here?”

So, in order to do a lick-finger-in-the-air visualization, I implemented Mike Harris’s momersion indicator.

momersion <- function(R, n, returnLag = 1) { momentum <- sign(R * lag(R, returnLag)) momentum[momentum < 0] <- 0 momersion <- runSum(momentum, n = n)/n * 100 colnames(momersion) <- "momersion" return(momersion) }

And then I ran the spread through it.

xiv <- xts(read.zoo("longXIV.txt", format="%Y-%m-%d", sep=",", header=TRUE)) vxx <- xts(read.zoo("longVXX.txt", format="%Y-%m-%d", sep=",", header=TRUE)) xivRets <- Return.calculate(Cl(xiv)) vxxRets <- Return.calculate(Cl(vxx)) volSpread <- xivRets + vxxRets volSpreadMomersion <- momersion(volSpread, n = 252) plot(volSpreadMomersion)

In other words, this spread is certainly mean-reverting at just about all times.

And here is the code for the results from 2011 onward, from when the XIV and VXX actually started trading.

#both sides sig <- -lag(sign(volSpread)) longShort <- sig * volSpread charts.PerformanceSummary(longShort['2011::'], main = 'long and short spread') #long spread only sig <- -lag(sign(volSpread)) sig[sig < 0] <- 0 longOnly <- sig * volSpread charts.PerformanceSummary(longOnly['2011::'], main = 'long spread only') #short spread only sig <- -lag(sign(volSpread)) sig[sig > 0] <- 0 shortOnly <- sig * volSpread charts.PerformanceSummary(shortOnly['2011::'], main = 'short spread only') threeStrats <- na.omit(cbind(longShort, longOnly, shortOnly))["2011::"] colnames(threeStrats) <- c("LongShort", "Long", "Short") rbind(table.AnnualizedReturns(threeStrats), CalmarRatio(threeStrats))

Here are the equity curves:

Long-short:

Long-only:

Short-only:

With the following statistics:

LongShort Long Short Annualized Return 0.115400 0.0015000 0.113600 Annualized Std Dev 0.049800 0.0412000 0.027900 Annualized Sharpe (Rf=0%) 2.317400 0.0374000 4.072100 Calmar Ratio 1.700522 0.0166862 7.430481

In other words, the short side is absolutely amazing as a trade–except for the one small fact of having it be impossible to actually execute, or at least as far as I’m aware. Anyhow, this was simply a for-fun post, but hopefully it served some purpose.

Thanks for reading.

NOTE: I am currently contracting and am looking to network in the Chicago area. You can find my LinkedIn here.