Direct Method once more

From Stanford Wong's BJ21


Posted by Pete Moss on 21 Nov 1997, at 7:17 p.m.

This subject is pretty much worn out I think. I believe we are making a mountain out of an interesting but rather short mole hill. However, I want to make one point which I've tried to make before, but apparently it didn't get through: There is no need to use a derivative-based score function like N0, or the difference between composite ev/var and your betting unit. You can use the "raw" logrithmic score function directly. Just search for its maximum. I use a general purpose implementation of Brent's method [sic] that I wrote years ago for finding the maximum.

Using the data Brett posted here, and a constraint of a 1-10 spread, I calculated the optimal unit size by all three methods. They all agreed with each other to 8 significant figures. That might have been more if I set the function maximizer to a more precise tolerance. There are practical reasons to prefer the raw score function. 1) The derivative-based score functions can have very flat areas that can make the search fail if the initial search range is not set close enough around the optimum value. 2) There are fewer arithmetic operations in the direct method.

Here is the C++ source code I used. "Hyst" stands for "hystogram". It contains the statistics for all the count bins (not necessarily in any paricular order). The 1-10 spread is imposed in the virtual function "units". It returns the unconstrained Kelly-optimal number of units to bet if that number falls in the range 1-10, or 1 or 10 as appropriate otherwise. It could instead impose some other betting strategy, like betting 1 unit at tc = +2, two units at +3, etc up to some maximum -- or whatever.


double BetStrategy::score(double bank) const
{
switch (method) {
case Brett: // maximize EV^2/Var
{
double EV = 0;
double VAR = 0;
for(int i=0; i< hyst.size();i++) {
double B = units(i, bank)/bank;
EV += hyst.C(i) * B * hyst.E(i);
VAR += hyst.C(i) * B*B * hyst.ER2(i);
}
return (EV*EV)/VAR;
}
case Winston: // find f = EV/Var
{
double EV = 0;
double VAR = 0;
for(int i=0; i< hyst.size();i++) {
double B = units(i, bank)/bank;
EV += hyst.C(i) * B * hyst.E(i);
VAR += hyst.C(i) * B*B * hyst.ER2(i);
}
// Need to find the zero of 1-EV/VAR
double diff = (1-EV/VAR);
return -fabs(diff); // Make bigger scores better for maximum-finder
}
default: // Maximize expected log(bank) approximation directly
// Pete's way
double retval = 0;
for(int i=0; i< hyst.size();i++) {
double B = units(i, bank)/bank;
retval += hyst.C(i)*B*(hyst.E(i)-.5*B*hyst.ER2(i));
}
return retval;
};
}