Kelly Criterion (Part 2)

Kelly Criterion (Part 2)

Imagine if a hustler tries to sell you an investment oppoturnity. An event/venture was successful 4 times and unsuccessful 1 time. The hustler tells you that probability of a successful venture is thus 0.8 (aka 80%) and the payoff is double your investment money. Aka a lottery ticket with a profit of $1 for each $1 ticket cost.

So according to the Kelly Criterion, you should invest 0.6 (60%) of your bankroll every time for say 100 consequtive investments.

Like a naive fool, you invest 60% of your bankroll and you end up making a loss.

But how can that be, when your chances of having a loss is

probabilityofloss(1.0,100, 0.8, 0.6)
The probability of loss for exact g=1.0 p=0.8 f=0.6 n=100 is 0.000737

or 0.0737% (and that is a lot less than 1% chance)

The secret is that the probability of unsuccessful venture is NOT 0.8 (80%).

If you read Checking whether a coin is fair - Wikipedia you will see that the probability of heads is

basically a beta distribution.

![kelly_betadist_calc|491x500](upload://5c0bstrV5jvJMxuFlinI7NyvfWF.png)

So to calculate the probability of making a loss, we need to calculate every value of p from 0.000…1 to 0.9999… which has infinite values. But we can estimate it if we assume the value of p can only take 99 values from 0.01, 0.02, … , 0.99 and weight each value of the relative probability that it occurs. That is what our source code do.

Now we see the actual probability of loss is

The probability of beta loss for g=1.0 alpha=4 beta=1 f=0.6 n=100 is 0.203455

or 20.3455%

And 20.3455% chance of making a loss is A LOT higher than Kelly Criterion naive prediction of 0.0737% chance of making a loss.

And the rest of the source code just draw graphs showing that the chances of making a loss is much higher than what naive Kelly Criterion predicts.

import Distributions

function calc_f_simplistic(p,cost_of_ticket,profit_per_ticket)
    gain = profit_per_ticket/cost_of_ticket
    f = p - (1-p)/gain
    if f < 0.0
        f = 0.0
    end
    return f
end

function gain_func(gain::Float64,n::Int64,w::Int64,f::Float64)
    #=
    number of losses equal to number of games - number of wins
    return the log of (1+f) * w/n + l/n * log of (1-f)
    =#
    local l = n - w
    return (w/n)*log(2,1+gain*f) + (l/n)*log(2,1-f)
end

isloss(x) = x < 0 ? true : false
isgain(x) =  x > 0 ? true : false
isstalemate(x) = x == 0 ? true : false

function probabilityofloss(gain::Float64,n::Int64,p::Float64,f::Float64)
    local k,q,acc
    q = 1.0 - p
    acc = 0.0
    for k = 0:n  # when we have k number of wins
         if isloss(gain_func(gain,n,k,f))
            acc += convert( Float64,binomial( big(n),big(k) ) ) * p^k * q^(n-k)
         end
    end
    return acc # Return the result in Float Type
end

myround6(x) = round(Float64(x),digits=6)


function probabilityofbetaloss(gain::Float64,alpha::Int64,beta::Int64,n::Int64,f::Float64)
    local betadist,arr,k,acc,loss
    betadist = Distributions.Beta(alpha,beta)
    arr = zeros(99)
    acc = 0.0
    for k=1:99
        arr[k]=Distributions.pdf(betadist,Float64(k)/100.0)
        acc += arr[k]
    end
    # Normalise the array for actual probability
    for k=1:99
        arr[k] = arr[k]/acc
    end
    # Now calculate the actual loss
    loss = 0.0
    for k=1:99
        loss += arr[k] * probabilityofloss(gain,n,Float64(k)/100.0, f)
    end
    return loss
end

println("start of program")

a = myround6(probabilityofloss(1.0,100, 0.8, 0.6))
println("The probability of loss for exact g=1.0 p=0.8 f=0.6 n=100 is ",a)

b = myround6(probabilityofbetaloss(1.0,4,1,100,0.6))
println("The probability of beta loss for g=1.0 alpha=4 beta=1 f=0.6 n=100 is ",b)

print("\n\n")

a2 = myround6(probabilityofloss(1.0,100, 0.8, 0.3))
println("The probability of loss for exact g=1.0 p=0.8 f=0.3 n=100 is ",a2)

b2 = myround6(probabilityofbetaloss(1.0,4,1,100,0.3))
println("The probability of beta loss for g=1.0 alpha=8 beta=2 f=0.3 n=100 is ",b2)

print("\n\n")

b3 = myround6(probabilityofbetaloss(1.0,16,4,100,0.6))
println("The probability of beta loss for g=1.0 alpha=16 beta=4 f=0.6 n=100 is ",b3)
b4 = myround6(probabilityofbetaloss(1.0,32,8,100,0.6))
println("The probability of beta loss for g=1.0 alpha=32 beta=8 f=0.6 n=100 is ",b4)
b5 = myround6(probabilityofbetaloss(1.0,64,16,100,0.6))
println("The probability of beta loss for g=1.0 alpha=64 beta=16 f=0.6 n=100 is ",b5)

using Plots

default(size=(900,730),linewidth=3.0)
const numberofgames=100

plot([x for x in 0.01:0.01:0.99],
[probabilityofbetaloss(1.0,4,1,numberofgames,x) for x in 0.01:0.01:0.99],
xticks=0.0:0.1:1.0,yticks=0.0:0.1:1.0,
title="Probability of Beta Loss with $(numberofgames) games",
grid=:true,gridalpha=1,
label="beta(4,1)",xlabel = "f", ylabel = "probability")
plot!([x for x in 0.01:0.01:0.99],
[probabilityofloss(1.0,numberofgames,0.8,x) for x in 0.01:0.01:0.99],
label="exact prob(0.8)",color=:black) |> display

plot([x for x in 0.01:0.01:0.99],
[probabilityofbetaloss(1.0,8,2,numberofgames,x) for x in 0.01:0.01:0.99],
xticks=0.0:0.1:1.0,yticks=0.0:0.1:1.0,
title="Probability of Beta Loss with $(numberofgames) games",
grid=:true,gridalpha=1,
label="beta(8,2)",xlabel = "f", ylabel = "probability")
plot!([x for x in 0.01:0.01:0.99],
[probabilityofloss(1.0,numberofgames,0.8,x) for x in 0.01:0.01:0.99],
label="exact prob(0.8)",color=:black)
plot!([x for x in 0.01:0.01:0.99],
[probabilityofbetaloss(1.0,8*2,2*2,numberofgames,x) for x in 0.01:0.01:0.99],
label="beta(16,4)")
plot!([x for x in 0.01:0.01:0.99],
[probabilityofbetaloss(1.0,4,1,numberofgames,x) for x in 0.01:0.01:0.99],
label="beta(4,1)",color=:red) |> display

plot([x for x in 0.71:0.01:0.99],
[probabilityofbetaloss(1.0,8,2,numberofgames,x)/probabilityofloss(1.0,numberofgames,0.8,x) for x in 0.71:0.01:0.99],
xrange=(0.0,1.0),xticks=0.0:0.1:1.0,
title="Ratio of Beta Loss/Actual Loss with $(numberofgames) games",
grid=:true,gridalpha=1,
label="beta(8,2)",xlabel = "f", ylabel = "ratio") |> display

plot([x for x in 0.01:0.01:0.99],
[log(10,probabilityofbetaloss(1.0,8,2,numberofgames,x)/probabilityofloss(1.0,numberofgames,0.8,x)) for x in 0.01:0.01:0.99],
xrange=(0.0,1.0),xticks=0.0:0.1:1.0,yticks=0:1:9,
title="Ratio of Log10(Beta Loss/Actual Loss) with $(numberofgames) games",
grid=:true,gridalpha=1,
label="log10(beta(8,2)/exact(0.8))",xlabel = "f", ylabel = "log ratio") |> display

Kelly Criterion (House of the Rising Sum)

There is a criterion in Mathematics
They call the Rising Sum
And it's been the ruin of many a poor investors
Dear God, I know I was one

My mother was a Mathematician
She bought me new shiny HP48SX
And my father was a gamblin' man
Way down in New Orleans

And the only thing a investor needs
Is a suitcase or a trunk of cash
And the only time he's satisfied
Is when he's a drunk

Oh, mother, tell your children
Not to do what I have done
To spend your lives in sums and misery
In the house of the rising sum
3 Likes