# Exploring Optimal f

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