By Ilya Kipnis
This post will outline an easy-to-make mistake in writing vectorized backtests–namely in using a signal obtained at the end of a period to enter (or exit) a position in that same period. The difference in results one obtains is massive.
Today, I saw two separate posts from Alpha Architect and Mike Harris both referencing a paper by Valeriy Zakamulin on the fact that some previous trend-following research by Glabadanidis was done with shoddy results, and that Glabadanidis’s results were only reproducible through instituting lookahead bias.
The following code shows how to reproduce this lookahead bias.
First, the setup of a basic moving average strategy on the S&P 500 index from as far back as Yahoo data will provide.
require(quantmod) require(xts) require(TTR) require(PerformanceAnalytics) getSymbols('^GSPC', src='yahoo', from = '1900-01-01') monthlyGSPC movAvg gspcRetsAnd here is how to institute the lookahead bias.
lookaheadThese are the “results”:
compareOf course, this equity curve is of no use, so here's one in log scale.
As can be seen, lookahead bias makes a massive difference.
Here are the numerical results:
S&P 500 Lookahead Correct Annualized Return 0.0740000 0.15550000 0.0695000 Annualized Std Dev 0.1441000 0.09800000 0.1050000 Annualized Sharpe (Rf=0%) 0.5133000 1.58670000 0.6623000 Worst Drawdown 0.5255586 0.08729914 0.2699789 Calmar Ratio 0.1407286 1.78119192 0.2575219Again, absolutely ridiculous.
Note that when using Return.Portfolio (the function in PerformanceAnalytics), that package will automatically give you the next period's return, instead of the current one, for your weights. However, for those writing “simple” backtests that can be quickly done using vectorized ...read more
Source:: r-bloggers.com