Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

The end of the month effect was examined by MarketSci in the The Last Day of the Month Blahs post. The idea is simple: buy on the last day of the month and sell a few days later. This idea was put into a strategy by Quanting Dutchman in the Strategy 2 – Monthly End-of-the-Month (MEOM) post.

I will follow the outline of the Quanting Dutchman’s strategy and will implement it using the backtesting library in the Systematic Investor Toolbox.

The strategy invests into the top 2 ETFs that are trading above a medium term moving avarage (WMA89) from the universe of 26 ETF’s: DIA, EEM, EFA, EWH, EWJ, EWT, EWZ, FXI, GLD, GSG, IEF, ILF, IWM, IYR, QQQ, SPY, VNQ, XLB, XLE, XLF, XLI, XLP, XLU, XLV, XLY, XLK. The strategy enters positions on the last day of the month at the close. The strategy exits positions two days later at the close. I will study two ranking schemes to select top two ETFs each month:

• Rank1 = MA( C/Ref(C,-2), 5 ) * MA( C/Ref(C,-2), 40 )
• Rank2 = MA( C/Ref(C,-2), 5 ) * Ref( MA( C/Ref(C,-2), 10 ), -5 )

Following code implements this strategy using the backtesting library in the Systematic Investor Toolbox:

# Load Systematic Investor Toolbox (SIT)
setInternet2(TRUE)
con = gzcon(url('https://github.com/systematicinvestor/SIT/raw/master/sit.gz', 'rb'))
source(con)
close(con)

#*****************************************************************
#******************************************************************
tickers = spl('DIA,EEM,EFA,EWH,EWJ,EWT,EWZ,FXI,GLD,GSG,IEF,ILF,IWM,IYR,QQQ,SPY,VNQ,XLB,XLE,XLF,XLI,XLP,XLU,XLV,XLY,XLK')

data <- new.env()
getSymbols(tickers, src = 'yahoo', from = '1995-01-01', env = data, auto.assign = T)
bt.prep(data, align='keep.all', dates='1995::2011')

#*****************************************************************
# Code Strategies
#******************************************************************
prices = data$prices n = ncol(prices) nperiods = nrow(prices) # Equal Weight data$weight[] = ntop(prices, n)
equal.weight = bt.run(data)

# find month ends
month.ends = endpoints(prices, 'months')
month.ends = month.ends[month.ends > 0]
month.ends2 = iif(month.ends + 2 > nperiods, nperiods, month.ends + 2)

# Strategy MEOM - Equal Weight
data$weight[] = NA data$weight[month.ends,] = ntop(prices, n)[month.ends,]
data$weight[month.ends2,] = 0 capital = 100000 data$weight[] = (capital / prices) * data$weight meom.equal.weight = bt.run(data, type='share') #***************************************************************** # Rank1 = MA( C/Ref(C,-2), 5 ) * MA( C/Ref(C,-2), 40 ) #****************************************************************** # BuyRule = C > WMA(C, 89) buy.rule = prices > bt.apply.matrix(prices, function(x) { WMA(x, 89) } ) buy.rule = ifna(buy.rule, F) # 2-day returns ret2 = ifna(prices / mlag(prices, 2), 0) # Rank1 = MA( C/Ref(C,-2), 5 ) * MA( C/Ref(C,-2), 40 ) position.score = bt.apply.matrix(ret2, SMA, 5) * bt.apply.matrix(ret2, SMA, 40) position.score[!buy.rule] = NA # Strategy MEOM - top 2 data$weight[] = NA;
data$weight[month.ends,] = ntop(position.score[month.ends,], 2) data$weight[month.ends2,] = 0

capital = 100000
data$weight[] = (capital / prices) * data$weight

#*****************************************************************
# Rank2 = MA( C/Ref(C,-2), 5 ) * Ref( MA( C/Ref(C,-2), 10 ), -5 )
#******************************************************************
position.score = bt.apply.matrix(ret2, SMA, 5) * mlag( bt.apply.matrix(ret2, SMA, 10), 5)

# Strategy MEOM - top 2
data$weight[] = NA; data$weight[month.ends,] = ntop(position.score[month.ends,], 2)
data$weight[month.ends2,] = 0 capital = 100000 data$weight[] = (capital / prices) * data\$weight

#*****************************************************************
# Create Report
#******************************************************************


This a great little strategy that is only invested 10% of time. You can improve returns by investing in a fixed income for the rest of the time. Quanting Dutchman tested this idea in My thoughts on “Go-In-Cash” post.

I also found promising results by using current Dow Jones Components instead of ETFs. To run the End of the Month strategy on current Dow Jones Components substitute:

tickers = spl('DIA,EEM,EFA,EWH,EWJ,EWT,EWZ,FXI,GLD,GSG,IEF,ILF,IWM,IYR,QQQ,SPY,VNQ,XLB,XLE,XLF,XLI,XLP,XLU,XLV,XLY,XLK')


with

tickers = dow.jones.components()


in the above code. Here are the summary stats for the End of the Month strategy using current Dow Jones Components.

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