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