Recently I’ve been reading Ralph Vince’s Risk Opportunity Analysis. His exploration in Optimal f and Leverage Space Model is quite fascinating and coincidently, his theory generalized the findings we’ve seen in my previous posts Monty Hall Paradox Test and Is Your Faith Fat-tailed?

In a nutshell, Ralph’s theory incorporates the factor of time into a decision-making & bet-sizing process through implementing probability-weighted median and Optimal f, as oppose to using probability-weighted mean and Kelly Criterion.

It’s a very powerful combination. In a hypothetical game with negative expected return, as well as a high chance to win small amounts and a very little chance to lose a lot (such as 90% of win 1 and 10% of loss -10), using probability-weighted median could prevent the player rejecting **highly probable and small** profits while Optimal f could protect the player from **remotely possible disasters.**

Here I’d like to mirror what he did in his book using a 2:1 fair coin tossing game to illustrate these ideas. Since the expected return is 2 * 0.5 + (-1) * 0.5 = 0.5, we are going to play this game anyway. But the expected return, which has a linear relationship with the amount you bet f, only tells half of the story. As shown below in R. With your time horizon expands, the relationship bends. (well…)

# sets up the function HPR <- function(win = 2, loss = -1, hor = 2, lev = 1, try = 101) { # hor = time horizon # lev = max leverage f <- seq(0, lev, length.out = try) ghpr <- rep(0, length(f)) for (i in 1:length(ghpr)) { win_ret <- 1 + f[i] * win loss_ret <- 1 + f[i] * loss mat <- matrix(c(win_ret, loss_ret)) mat <- mat %*% t(mat) if (hor > 2) { for (j in 2:(hor - 1)) { mat <- cbind(mat * win_ret, mat * loss_ret) } } ghpr[i] <- sum((mat ^ (1 / hor) - 1)) / (2 ^ hor) } ghpr[ghpr<0] <- 0 data.frame(f = f, GHPR = 1 + ghpr, HPR = (ghpr + 1) ^ hor) } # play 2 times plot(HPR(hor=2)$f, HPR(hor=2)$HPR, type='l', ylim = c(1, 1.8), main = 'Time Horizon Illustration', xlab = 'f', ylab = 'HPR') # play 1 time lines(c(0, 1), c(1, 1.5)) # and more lines(HPR(hor=3)$f, HPR(hor=3)$HPR) lines(HPR(hor=4)$f, HPR(hor=4)$HPR) lines(HPR(hor=5)$f, HPR(hor=5)$HPR) lines(HPR(hor=6)$f, HPR(hor=6)$HPR) lines(HPR(hor=7)$f, HPR(hor=7)$HPR) lines(HPR(hor=8)$f, HPR(hor=8)$HPR) text(0.8, 1.2, '2') text(0.65, 1.18, '3') text(0.5, 1.1, '8') text(1, 1.55, '1') grid()

As we continue to play (despite the time horizon), the optimal bet size f keeps approaching to 0.25, which could also be derived out from the objective function of Optimal f: .

Now we can examine the compounding effect with using Optimal f.

# this function simply implements Optimal f with 100 observations Opt.f <- function(win = 2, loss = -1, p = .5, lev = 1, obs = 100, plays = 1) { f <- seq(0, lev, 1/obs) rets <- rep(0, length(f)) for (i in 1:length(rets)) { rets[i] <- (((1 + f[i] * win / -loss) ^ p) * ((1 + f[i] * loss / -loss) ^ (1 - p))) ^ plays } data.frame(f = f, rets = rets) } # the results of 40 plays plot(Opt.f(plays=40)$f, Opt.f(plays=40)$rets, type='l', main = 'Optimal f Effect', xlab = 'f', ylab = 'returns') # 20 and 5 plays lines(Opt.f(plays=20)$f, Opt.f(plays=20)$rets) lines(Opt.f(plays=5)$f, Opt.f(plays=5)$rets) text(.25, 9, '40') text(.25, 3.5, '20') text(.25, 1, '5') grid()

Finally, instead of tossing one coin, now we have two coins for the same game and here’s the combined effect of 5 plays.

# Two components function TCOpt.f <- function(win = 2, loss = -1, outcome = 4, lev = 1, obs = 100, plays = 1) { f1 <- seq(0, lev, 1/obs) f2 <- seq(0, lev, 1/obs) rets <- matrix(0, length(f1), length(f2)) for (i in 1:length(f1)) { for (j in 1:length(f2)) { s1 <- (1 + (f1[i] * win + f2[j] * loss) / -loss) ^ (1 / outcome) s2 <- (1 + (f1[i] * win + f2[j] * win) / -loss ) ^ (1 / outcome) s3 <- (1 + (f1[i] * loss + f2[j] * win) / -loss ) ^ (1 / outcome) s4 <- (1 + (f1[i] * loss + f2[j] * loss) / -loss ) ^ (1 / outcome) rets[i, j] <- (s1 * s2 * s3 * s4) ^ plays } } rets[is.na(rets)] <- 0 mat <- matrix(f1, nrow = length(f1), ncol=length(f1)) list(xmat = mat, ymat = t(mat), 'rets' = rets) } require(rgl) plays5 <- TCOpt.f(plays=5) x <- plays5$xmat y <- plays5$ymat z <- plays5$rets col <- c('white','blue')[ z+1 ] persp3d(x, y, z, color=col, alpha=.6, xlab = 'coin 1', ylab = 'coin 2', zlab = 'returns') grid3d(c('x', 'y', 'z')) title3d("Two Components Coin Tossing", line=5)

There are a lot of other interesting properties of this system but I believe I’ve covered the gist of it. And apparently more works need to be done until we can fully utilize it in trading or investment.

roy