Skip to content

Instantly share code, notes, and snippets.

@chrismilson
Last active February 27, 2024 06:22
Show Gist options
  • Save chrismilson/bb1f19f833e7485bd44dc5e600d2eb49 to your computer and use it in GitHub Desktop.
Save chrismilson/bb1f19f833e7485bd44dc5e600d2eb49 to your computer and use it in GitHub Desktop.
The Generous Bookie
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "ultimate-hamilton",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "loving-jenny",
"metadata": {},
"source": [
"# The Generous Bookie\n",
"\n",
"I came across the following interview question recently:\n",
"\n",
"> A bookie gives you certain odds for Team A (say 3:1) to win again Team B, and vice versa (say 4:1). The bookie also gives you odds for a draw (say 11:1). Would you bet? How would you bet?\n",
"\n",
"## Solution\n",
"\n",
"Lets say we know nothing about the teams, so we will not attempt to guess the probabilities associated with the three outcomes of the game. We still may want to bet, if there is some way that we can allocate our bets so that we are guaranteed to win money.\n",
"\n",
"Let the amounts $a$, $b$, and $d$ be the amounts that we will bet on team A winning, team B winnning and a draw respectively. In the event that team A wins, we will gain $3a$ dollars and lose $b + d$ dollars. If team B wins we will gain $4b$ dollars and lose $a + d$ dollars. If the game ends in a draw, we will gain $11d$ dollars and lose $a + b$ dollars.\n",
"\n",
"We can represent our winnings by the following matrix multiplication:\n",
"\n",
"$$\n",
"\\begin{bmatrix}\n",
"3 &-1 &-1 \\\\\n",
"-1 &4 &-1 \\\\\n",
"-1 &-1 &11\n",
"\\end{bmatrix}\n",
"\\begin{bmatrix}\n",
"a \\\\ \n",
"b \\\\\n",
"d\n",
"\\end{bmatrix}\n",
"=\n",
"\\begin{bmatrix}\n",
"w_A \\\\ \n",
"w_B \\\\\n",
"w_D\n",
"\\end{bmatrix}\n",
"$$\n",
"\n",
"Where $w_A$, $w_B$, and $w_D$ are the winnings we get when A or B wins or we have a draw, respectively.\n",
"\n",
"Before we worry about solving this, let's try some different values."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "stuck-contributor",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"(array([1, 2, 9]), array([-2, 4, 30]), array([6, 4, 6]))"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"M = np.array([[ 3, -1, -1],\n",
" [-1, 4, -1],\n",
" [-1, -1, 11]])\n",
"\n",
"M @ [1, 1, 1], M @ [1, 2, 3], M @ [3, 2, 1]"
]
},
{
"cell_type": "markdown",
"id": "living-renewal",
"metadata": {},
"source": [
"Ok, now we know that there are strategies that we can use so that we can win every time. Great! However, for $(1, 1, 1)$ we win a lot more if there is a draw as opposed to A or B winning, and for $(3, 2, 1)$ we win more if A wins or there is a draw as opposed to B winning. This is not great, since we want to be unbiased by the probabilities that any given outcome may occur.\n",
"\n",
"More formally, we want to find an unbiased betting strategy such that no matter the outcome, we will win the same amount of money.\n",
"\n",
"This corresponds to solving the following linear system:\n",
"\n",
"$$\n",
"\\begin{bmatrix}\n",
"3 &-1 &-1 \\\\\n",
"-1 &4 &-1 \\\\\n",
"-1 &-1 &11\n",
"\\end{bmatrix}\n",
"\\begin{bmatrix}\n",
"a \\\\ \n",
"b \\\\\n",
"d\n",
"\\end{bmatrix}\n",
"=\n",
"\\begin{bmatrix}\n",
"w \\\\ \n",
"w \\\\\n",
"w\n",
"\\end{bmatrix}\n",
"$$\n",
"\n",
"Note that multiplying our bets by a constant will just multiply the winnings by the same constant, so we can try to solve for $a$, $b$, $c$ where $w = 1$, and then scale.\n",
"\n",
"To solve the system, we need to find an inverse for $\\begin{bmatrix}3&-1&-1\\\\-1&4&-1\\\\-1&-1&11\\end{bmatrix}$. We could do this by hand, but the `numpy` package is our friend here:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "worst-emperor",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(112.00000000000006,\n",
" array([[43., 12., 5.],\n",
" [12., 32., 4.],\n",
" [ 5., 4., 11.]]))"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.linalg.det(M), np.linalg.det(M) * np.linalg.inv(M)"
]
},
{
"cell_type": "markdown",
"id": "qualified-christopher",
"metadata": {},
"source": [
"If we guess that the `...0006` is due to floating point error and check:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "contained-forest",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1., 0., 0.],\n",
" [0., 1., 0.],\n",
" [0., 0., 1.]])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"M @ np.array([[43, 12, 5],\n",
" [12, 32, 4],\n",
" [ 5, 4, 11]]) / 112"
]
},
{
"cell_type": "markdown",
"id": "desirable-receptor",
"metadata": {},
"source": [
"We realise the fact:\n",
"\n",
"$$\n",
"\\begin{bmatrix}\n",
"3 &-1 &-1 \\\\\n",
"-1 &4 &-1 \\\\\n",
"-1 &-1 &11\n",
"\\end{bmatrix}^{-1}\n",
"=\n",
"\\frac{1}{112}\n",
"\\begin{bmatrix}\n",
"43 &12 &5 \\\\\n",
"12 &32 &4 \\\\\n",
"5 &4 &11\n",
"\\end{bmatrix}\n",
"$$\n",
"\n",
"We can then (left) multiply the original system by this inverse to get:\n",
"\n",
"\\begin{align*}\n",
"\\begin{bmatrix}\n",
"a \\\\ \n",
"b \\\\\n",
"d\n",
"\\end{bmatrix}\n",
"&=\n",
"\\frac{1}{112}\n",
"\\begin{bmatrix}\n",
"43 &12 &5 \\\\\n",
"12 &32 &4 \\\\\n",
"5 &4 &11\n",
"\\end{bmatrix}\n",
"\\begin{bmatrix}\n",
"1 \\\\ \n",
"1 \\\\\n",
"1\n",
"\\end{bmatrix}\\\\\n",
"&=\n",
"\\frac{1}{112}\n",
"\\begin{bmatrix}\n",
"60 \\\\\n",
"48 \\\\\n",
"20\n",
"\\end{bmatrix}=\n",
"\\frac{1}{28}\n",
"\\begin{bmatrix}\n",
"15 \\\\\n",
"12 \\\\\n",
"5\n",
"\\end{bmatrix}\n",
"\\end{align*}\n",
"\n",
"That is, for every bet of 15 on A winning, 12 on B winning, and 5 on a draw, we will win 28 **no matter the outcome**."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "adjacent-shareware",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([28, 28, 28])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"M @ [15, 12, 5]"
]
},
{
"cell_type": "markdown",
"id": "massive-delhi",
"metadata": {},
"source": [
"So the answer is:\n",
"\n",
"- YES! we should bet, because there are betting strategies that allow us to have a **guarunteed return**.\n",
"- We should bet proportinal to 15 on team A winning, 12 on team B winning, and 5 on there being a draw, because we (in general) know nothing of the likelihood that any given event will occur.\n",
"\n",
"That is a very generous bookie!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment