OK so I played round with this some more and it seems the best strategy is just to bet 100% of your bankroll whenever you have an advantage bet:
Code:
#include <iostream>
#include <random>
#include <cmath>
#include <ctime>
#include <algorithm>
// The number of simulations to run.
//const int NUM_SIMS = 100000000;
const int NUM_SIMS = 5000000; // The largest value that will run using http://cpp.sh/.
// The "Greedy" strategy (ie: always bet full bankroll when advantage bet presents itself).
const std::vector<std::vector<double>> GREEDY_STRATEGY {
{0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0},
{0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}
};
// The "Kelly" strategy.
const std::vector<std::vector<double>> KELLY_STRATEGY {
{0.0, 1.0/3.0, 1.0/2.0, 3.0/5.0, 2.0/3.0, 5.0/7.0, 3.0/4.0, 7.0/9.0, 4.0/5.0, 1.0},
{0.0, 0.0, 1.0/5.0, 1.0/3.0, 3.0/7.0, 1.0/2.0, 5.0/9.0, 3.0/5.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0/7.0, 1.0/4.0, 1.0/3.0, 2.0/5.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 1.0/9.0, 1.0/5.0, 1.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}
};
double score(const std::vector<std::vector<double>>& strategy)
{
// Random number generator to use.
std::mt19937 generator(time(nullptr));
// Distribution for the coin bias.
std::uniform_real_distribution<double> biasDistribution(0.0,1.0);
// Sum of bankroll over all sims,
double sumBankroll=0.0;
// Run lots of times with different bias values.
for (int i=0;i<NUM_SIMS;i++) {
// Generate a random bias for the coin.
double bias=biasDistribution(generator);
// Distribution for the coin-flips.
std::bernoulli_distribution coinDistribution(bias);
// Start off with $20.
double currentBankroll=20.0;
// Run a single game.
int numHeads=0;
int numTails=0;
for (int i=0;i<10;i++) {
// Work out the bet fraction the strategy says we should do.
double betFraction=0.0;
if (numHeads>numTails)
betFraction=strategy[numTails][numHeads];
else if (numHeads<numTails)
betFraction=(-strategy[numHeads][numTails]);
// Generate a random coin toss and update the counts/bankroll.
if(coinDistribution(generator)) {
numHeads++;
currentBankroll*=(1.0+betFraction);
}
else {
numTails++;
currentBankroll*=(1.0-betFraction);
}
}
// Add to the sum of bankroll.
sumBankroll+=currentBankroll;
}
// Return the average EV per game.
return (sumBankroll/static_cast<double>(NUM_SIMS)-20.0);
}
int main() {
std::cout << "Greedy strategy = $" << score(GREEDY_STRATEGY) << " EV per game" << std::endl;
std::cout << "Kelly strategy = $" << score(KELLY_STRATEGY) << " EV per game" << std::endl;
}
and hit run (and reduce the NUM_SIMS if you get no output).
I guess it's possible that there is a bug in the sim or the mathematica code, but I've looked over them both a few times and can't see anything wrong.