The Paradox

The St. Petersburg paradox describes a game of chance for a single player in which a fair coin is tossed at each stage. The initial stake starts at 2 dollars and is doubled every time heads appears. The first time tails appears, the game ends and the player wins whatever is in the pot.

Let denote the final winning amount after the th toss. We know that and and . We can see that is a sub-martingale as .

Let denote the minimum number of toss that shows a tail toss . is a stopping time.

The variance:

Considering nothing but the expected value of the net change in one’s monetary wealth, one should therefore play the game at any price if offered the opportunity. Yet the paradox exists between what people seem willing to pay to enter the game and the infinite expected value.

The Martingale

With slight modifications from above, the St. Petersburg martingale is the sequence of random variable , where and and . It is now a martingale because .

Note that now the expected payoff at inception is equal to initial stake based on Doob’s Idenfity, given stopping time T defined above:

Expected Utility Theory

The classic way to resolve the paradox involves the introduction of utility function and the presumption of diminishing marginal utility.

Let x denote a person’s total wealth, then the logrithmic utility function states that:

Where the marginal utility is a decreasing function of x:

Now we calculate the maximum cost c that a person with logrithmic utility function and wealth w would pay to enter the game. The maximum cost will make the expected utility change from playing the game be 0.

Simulation

Given w, c can be calculated numerically. In python, we first check the maximum power of two allowed in our simulation. It turns out to be 63:

1
2
3
4
5
6
7
import sys
import numpy as np

x = sys.maxsize
print('maximum integer: ', x)
max_power = np.log(x)/np.log(2)
print('maximum power of 2: ', max_power)

Returns:

1
2
maximum integer:  9223372036854775807
maximum power of 2: 63.0

Logrithmic Utility Function

Now we use fsolve to calculate the maximum c to break even:

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
from scipy.optimize import fsolve

def func(c):
w = 1000
p = 0.5`np.arange(1, 63)
u = np.log(w + 2`np.arange(1, 63) - c) - np.log(w)
return sum(p*u)


maximum_cost = fsolve(func, 0)
print("maximum cost to enter: ", round(maximum_cost[0], 2))

When w = 1000:

1
maximum cost to enter:  10.95

When w = 1000000:

1
maximum cost to enter:  20.87

Square-Root Utility Function

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
from scipy.optimize import fsolve

def func(c):
w = 1000
p = 0.5`np.arange(1, 63)
u = np.sqrt(w + 2`np.arange(1, 63) - c) - np.sqrt(w)
return sum(p*u)


maximum_cost = fsolve(func, 0)
print("maximum cost to enter: ", round(maximum_cost[0], 2))

When w = 1000:

1
maximum cost to enter:  12.93

When w = 1000000:

1
maximum cost to enter:  22.87

Note that under the square-root utility function, the maximum cost to enter is higher, as utility diminished slower.




Reference: