November 1, 2013
By

(This article was first published on Systematic Investor » R, and kindly contributed to R-bloggers)

I recently came across a very interesting idea at the The Problem with Market Neutral (and an Answer) post by Mebane Faber. Today I want to show how you can test such strategy using the Systematic Investor Toolbox:

###############################################################################
# Load Systematic Investor Toolbox (SIT)
# http://systematicinvestor.wordpress.com/systematic-investor-toolbox/
###############################################################################
setInternet2(TRUE)
con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb'))
source(con)
close(con)

#*****************************************************************
#******************************************************************

data = new.env()

ret = temp[[1]]$Mkt.RF + temp[[1]]$RF
price = bt.apply.matrix(ret / 100, function(x) cumprod(1 + x))
data$SPY = make.stock.xts( price ) # load historical momentum returns temp = get.fama.french.data('10_Portfolios_Prior_12_2', periodicity = '',download = T, clean = T) ret = temp[[1]] price = bt.apply.matrix(ret / 100, function(x) cumprod(1 + x)) data$HI.MO = make.stock.xts( price$High ) data$LO.MO = make.stock.xts( priceLow ) # align dates bt.prep(data, align='remove.na') #***************************************************************** # Code Strategies #***************************************************************** models = list() dataweight[] = NA
data$weight$SPY[] = 1
models$SPY = bt.run.share(data, clean.signal=T) data$weight[] = NA
data$weight$HI.MO[] = 1
models$HI.MO = bt.run.share(data, clean.signal=T) data$weight[] = NA
data$weight$LO.MO[] = 1
models$LO.MO = bt.run.share(data, clean.signal=T) data$weight[] = NA
data$weight$HI.MO[] = 1
data$weight$LO.MO[] = -1
models$MKT.NEUTRAL = bt.run.share(data, clean.signal=F) #***************************************************************** # Modified MN # The modified strategy below starts 100% market neutral, and depending on the drawdown bucket # will reduce the shorts all the way to zero once the market has declined by 50% # (in 20% steps for every 10% decline in stocks) #***************************************************************** market.drawdown = -100 * compute.drawdown(data$prices$SPY) market.drawdown.10.step = 10 * floor(market.drawdown / 10) short.allocation = 100 - market.drawdown.10.step * 2 short.allocation[ short.allocation < 0 ] = 0 data$weight[] = NA
data$weight$HI.MO[] = 1
data$weight$LO.MO[] = -1 * short.allocation / 100
models\$Modified.MN = bt.run.share(data, clean.signal=F)

#*****************************************************************
# Create Report
#*****************************************************************
strategy.performance.snapshoot(models, T)


Mebane thank you very much for sharing this great observation and great strategy that works! I would encourage readers to experiment with idea and share their findings.

If you want to concentrate on the long side, one idea that comes to mind is to start not fully invested say at 90% allocation, and once the market hits say 20% draw-down to invest 100% in expectation of quick recovery.

To view the complete source code for this example, please have a look at the bt.mebanefaber.modified.mn.test() function in bt.test.r at github.