Created
November 29, 2014 01:36
-
-
Save mds2/621144c6428d6ec031a0 to your computer and use it in GitHub Desktop.
adventures in information theory and optimal gambling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; Every time I read about information theory, gambling, and the optimal | |
;;; way to bet on horse races, I am sufficiently surprised by what the math is | |
;;; telling me that I develop a desire to run experiments to double-check it | |
;;; for myself. | |
;;; | |
;;; See : http://en.wikipedia.org/wiki/Gambling_and_information_theory | |
;;; See : http://en.wikipedia.org/wiki/Kelly_criterion | |
;;; | |
;;; Note that my notion of "odds" might not exactly match up with the | |
;;; conventional notion. Mine are easier to compute with. | |
(defn unitize [vector-in] | |
(let [sum-vector (* 1.0 (reduce + vector-in))] | |
(apply vector (map (fn [el] (/ el sum-vector)) vector-in)))) | |
(defn cdf-from-pdf [probs] | |
(apply vector (reverse (reduce | |
(fn [accum next] | |
(cons (+ next (first accum)) accum)) | |
'(0) (unitize probs))))) | |
(defn select-from-cdf | |
([cdf] | |
(select-from-cdf cdf (rand 1.0))) | |
([cdf prob] | |
(first (filter (fn [i] (and (<= (nth cdf i) prob) | |
(> (nth cdf (+ i 1)) prob))) | |
(range (- (count cdf) 1)))))) | |
(defn make-sane-odds | |
{:doc "Makes horse-racing style odds given a quantity bet on each outcome" | |
:todo "May not correspond to everone else's notion of what \"odds\" means"} | |
[bet-amounts-vector] | |
(let [total (* 1.0 (reduce + bet-amounts-vector))] | |
(apply vector (map (fn [x] (/ total x)) bet-amounts-vector)))) | |
(defn make-experiment | |
{:doc "Makes a horse-racing experiment"} | |
[odds probs] | |
(let [unit-probs (unitize probs) | |
cdf-probs (cdf-from-pdf probs) | |
run-once (fn [bet-vector] | |
(let [bets (unitize bet-vector)] | |
(let [winner (select-from-cdf cdf-probs)] | |
(* (nth bets winner) (nth odds winner))))) | |
run-n-times (fn [bet-vector n] | |
(reduce * (map (fn [i] (run-once bet-vector)) (range n))))] | |
{:odds odds, | |
:probs unit-probs, | |
:run-once run-once, | |
:run-n-times run-n-times, | |
:sample-trials (fn [bet-vector rounds-per-trial num-trials] | |
(map (fn [i] (Math/log (run-n-times bet-vector | |
rounds-per-trial))) | |
(range num-trials))) | |
} | |
)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use it
Start the repl and load the file
make-experiment
will let you build a horse-racing experiment given a set of odds and a vector containing the probabilities that each horse will win.Here we make one with skewed odds and one with odds that match the probability of winning.
You can run individual experiments with this. Here we bet in each race (repeatedly) with a clearly flawed vector of bets (
0.75
of our money on one horse and0.25
of our money on the other)Or you can run a bunch of races back to back, each time re-investing your total cash according to the same bet vector (here we use a uniform betting vector -- which the code will even out for us)
Note that the
even-odds-experiment
always gives us exactly our money back if we split it 50/50 among both horses.We can also run a bunch of repeated series of races and print out the log of our final money at the end of each run. Recall that
(Math/log 1.0)
gives you0.0
.Playing with this lets one experience that the optimal bet is to bet to the probability of winning, while the odds only affect how much you win (or whether you should even place a bet in the first place).