Kelly Criterion
- Bet or invest so as to maximize (after each bet) the expected growth rate if capital, which is equivalent to maximizing the expected value of the logarithm of wealth.
or equivalently
- maximizing
is the same as maximizing
binary case
where
An optimal fraction is the one that makes the derivative null.
from sympy import *
# For a symbolic verification with Python and SymPy one would set the derivative y'(x)
# of the expected value of the logarithmic bankroll y(x) to 0 and solve for x
x, b, p = symbols('x b p')
y = p * log(1 + b * x) + (1 - p) * log(1 - x)
s = solve(diff(y, x), x)
print(str(s))
# [(b*p + p - 1)/b]
example:
example:
2 independent binary cases
2 dependent binary cases
more than 2 outcomes
Example from “mathexchange/Kelly criterion with more than two outcomes”
“In other words, if you bet a little under a quarter of your bankroll, you should expect your bankroll to grow on average by
from sympy import *
# For a symbolic verification with Python and SymPy one would set the derivative y'(x)
# of the expected value of the logarithmic bankroll y(x) to 0 and solve for x
x, p = symbols('x p')
y = 0.1 * log(1 + 30 * x) + 0.2 * log(1 + 10 * x) + 0.7 * log(1 - x)
s = solve(diff(y, x), x)
print(str(s))
# [-0.0578343329665600, 0.247834332966560]
d = s[1]
fx = 0.1 * log(1 + 30 * d) + 0.2 * log(1 + 10 * d) + 0.7 * log(1 - d)
print(str(fx)) # 0.263191478105847
continuous case
Again, an optimal fraction is the one that makes the derivative null.
Two options for solving here with Python:
- compute the integral in the 1st equation and maximize the
- compute the derivative of the integral in the 2nd equation and use numeric solver to find zero
Example from E. Thorp’s article with Source code from (Leiva, 2018).
Thorp focuses on annual returns and suggests modeling
from scipy.optimize import minimize_scalar, newton, minimize
from scipy.integrate import quad
from scipy.stats import norm
def norm_integral(f,m,st):
val,er = quad(lambda l: np.log(1+f*l)*norm.pdf(l,m,st),m-3*st,m+3*st)
return -val
def norm_dev_integral(f,m,st):
val,er = quad(lambda l: (l/(1+f*l))*norm.pdf(l,m,st),m-3*st,m+3*st)
return val
# Reference values from Eduard Thorp's article
m = .058
s = .216
# Option 1: minimize the expectation integral
sol = minimize_scalar(norm_integral,args=(m,s),bounds=[0.,2.],method='bounded')
print('Optimal Kelly fraction: {:.4f}'.format(sol.x))
# Option 2: take the derivative of the expectation and make it null
x0 = newton(norm_dev_integral,.1,args=(m,s))
print('Optimal Kelly fraction: {:.4f}'.format(x0))
Portfolio construction
Example from wduwant, with known expected return at each step.
- Good for educational processes, but miss the point of having distributions of expected return.
- Example is with
instead of
We have 2 assets
assuming asset returns are:
def objective(x, sign=-1.0):
w1=x[0]
w2=x[1]
w3=x[2]
a=np.array([0.3,-.15])
b=np.array([-0.05,0.2])
c=np.array([0.05,0.1])
fx=np.log(np.prod(1+w1*a+w2*b+w3*c))
return sign*(fx)
def weight_sum(x):
return x[0]+x[1]+x[2]-1.0
b=(-1,1) # bounds for weights
bounds=(b,b,b)
cons={'type': 'eq', 'fun': weight_sum}
x_default=np.zeros(3)
sol = minimize(objective, x_default,method='SLSQP', bounds=bounds, constraints=[cons])
#print(str(sol))
print('Kelly portfolio weights are as follows ' + str(sol.x*100))
Examples
- https://github.com/DinodC/investing-etf-kelly.git
single and multiple securities with ETFs based on “The Kelly Criterion in Blackjack Sports Betting and the Stock Market” using normal distributions. Uses matrix multiplication and python pandas. - https://github.com/jeromeku/Python-Financial-Tools.git
see portfolio.pyoptimize_kelly_criterion()
and the references “Kelly Criterion for Multivariate Portfolios: A Model-Free Approach”. It still uses covariance, but has other useful stuff, calculations and explanations.
References
- Leiva, J. (2018). The Kelly Criterion. https://quantdare.com/kelly-criterion/