﻿ Backtest Overfitting | Translated in R

# Backtest Overfitting | Translated in R

TimelyPortfolio

### Original Paper

Pseudo-Mathematics and Financial Charlatanism:

The Effects of Backtest Overfitting on Out-of-Sample Performance

Bailey, David H. and Borwein, Jonathan M. and Lopez de Prado, Marcos and Zhu, Qiji Jim
October 7, 2013
Available at SSRN: http://ssrn.com/abstract=2308659

### Constants - R Equivalents

# these are the constants referenced
# Euler–Mascheroni's constant
-digamma(1)

##  0.5772

# euler constant
exp(1)

##  2.718


### Expected Maximum Sharpe $E[max_N]$

\begin{aligned} (1-\gamma)Z^{-1}\left[1-\frac{1}{N}\right]+\gamma Z^{-1}\left[1-\frac{1}{N}e^{-1}\right] \end{aligned}

#### R Translation

### Eq. 4
emax <- function(N) {
( ( 1 + digamma(1) ) * qnorm( 1 - 1/N ) ) +
(-digamma(1) * qnorm( 1 - (1/N) * exp(-1)))
}

emax( N = 10 )  # should be about = 1.57 to match paper

##  1.575


### Plot $E[max_N]$

#implement upper bound
upbound <- function(N) {sqrt(2*log(N))}
#make a ugly plot for reasonableness check
curve(upbound, from = 1, to = 1000, col = "red", lty = 2)
curve(emax, from = 1, to = 1000, add=TRUE)
grid() ### rChart $E[max_N]$

require(rCharts)
df <- data.frame(
list(x=c(1,2:1000), y=c(0,emax(2:1000))))
d1 <- dPlot( y ~ x, groups = "x", data = df, type = "line", height = 270, width = 800)
d1$xAxis(type = "addMeasureAxis",orderBy = "x",outputFormat = ",0.0f") d1$yAxis( outputFormat = ".2f")
d1


### Check My Math with Eq. 6

### Try next example for Eq. 6
# if y = 5
# so solve for annualized Sharpe of 1
# says no more than 45 N should be tried

# first just do this to make sure I understand
N = 45
y = 5
emax( N ) * y^-0.5  #seems like on the right path

##  0.9998


### Minimum Backtest Length $MinBTL$

\begin{aligned} \left(\frac{(1-\gamma)Z^{-1}\left[1-\frac{1}{N}\right]+\gamma Z^{-1}\left[1-\frac{1}{N}e^{-1}\right]}{\overline{E[max_N]}}\right)^2 \end{aligned}

#### R Translation

#use emax from earlier for numerator
minBTL <- function( N, eMaxSharpe = 1 ) {
(emax(N) / eMaxSharpe) ^ 2
}
#then this should equal 5 if correct
minBTL( N = 45, eMaxSharpe = 1 )

##  4.998


### Plot $MinBTL$

#make ugly plot for a reasonableness check
curve( minBTL, from = 1, to = 1000) ### rChart $MinBTL$

df <- data.frame(
list(x=c(1,2:1000), minBTL=c(0,minBTL(2:1000))))
n1 <- nPlot( minBTL ~ x, data = df, type = "lineChart", height = 270, width = 800)
n1$yAxis( tickFormat = "#!d3.format(',.2f')!#") n1$chart( useInteractiveGuideline = TRUE )
n1


### Thanks

• Ramnath Vaidyanathan
• Bailey, David H. and Borwein, Jonathan M. and Lopez de Prado, Marcos and Zhu, Qiji Jim