博彩的赔率

最近刚看完塞勒的《“错误”的行为》,里面有一段,大意是如下,于是有了这篇文章的思考。

赛马中人们倾向于投注给历史成绩较差的,因为赔率更高,但是考虑到赔率形成的机制,相对更多的人投注导致了赔率(收益)与概率不匹配。

赔率的形成

本文的核心在于赔率的形成,但是首先考虑的一点是,给定投注情况,赔率如何生成。
假设仅存在两种选择,胜利W和失败F,W的投注数量是M,F的投注数量是N,W的赔率是Z1(即每1元赌注可获得Z1元),F的赔率是Z2,赌场的抽成是t,则满足以下关系:
$$N+M-Z1M=t(N+M)$$
$$M+N-Z2N=t(N+M)$$
给定任何一组投注情况,N和M都可以表示成M=kN,于是
$$Z1=\frac{(1-t)(k+1)}{k}$$
$$Z2=(1-t)(k+1)$$
所以Z1和Z2有恒定的比值Z1/Z2=1/k,结果如下图所示。

博彩的赔率-图1
博彩的赔率-图2

随着W投注的提高,Z1逐渐下降直到趋于1,如果小于1,将不再有投注;Z2额逐步提高。假设胜利的概率为p,相应地失败的概率为1-p,如果投注结果是“理性的”,则
$$Z1p=Z2(1-p)$$
由于p是固定值,Z2/Z1也应当是常数并且等于p/(1-p),但现实中Z2/Z1将是多变的。按照前述赔率的生成模式,无论比值如何变化,赌场将获取收益t(N+M),如果假定总投注规模一定,赌场的期望收益都将不变。那么赌徒的期望总收益也不变,但是,如果F投注过度,k取值较小,从而Z2小于“理性”情况,选择F赌徒将是“错误”的,因为其期望收益不如W。

博彩的赔率-图3

如何选择?赔率设置模型的改变

如果这种投注的倾向是常态,赌场的赔率设置是否有改进的空间?假设投注倾向——非理性的部分与Z2和Z1之间的差距有关,用M/N(即k)和p/(1-p)的差异衡量非理性部分。
$$k-p/(1-p)=d(Z2/Z1-1)$$
此时,赌场的期望收益是
$$p(N+M-Z1M)+(1-p)(N+M-Z2N)$$
令Z2/Z1=b,S=N+M于是问题转变为
$$min G(Z1,bZ1)=\fran{Z1(kp+b(1-p))}{1+k}$$
其中,$k=p/(1-p)+d(b-1)$

博彩的赔率-图4
博彩的赔率-图5

初步计算的结果很有趣,Z1越接近1,即取值越小,则G取值越小,b取值越小,即两者收益差越小,则G取值越小,也许说明一个问题,Z1和b的取值必须考虑对总投注S的影响,令$S=s\sqrt(Z1+DZ2)$,其中s,D取大于1,则
$$max H=S(1-G)$$
修改后的结果如下图所示,果然,尽管Z1仍是取1时H取值最大,但H的最大值出现在b取接近4的位置,意味着主要通过Z2的扩大来吸引更多的投注,b的取值实际上还与p有关,当p的取值从0.8扩大到0.9时,极值点上b的取值更大,W的胜率越高,留给Z2提升的空间越大。

博彩的赔率-图6
博彩的赔率-图7
博彩的赔率-图8

附录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# coding: utf-8

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

def gzdf(t=0.15):
kx=list(np.arange(0,100,0.5))
z1list=[]
z2list=[]
zplist=[]
zxlist=[]
for i in kx:
ki=i+1
z1=(1-t)*(ki+1)/ki
z2=(1-t)*(ki+1)
if z1<=1:
break
z1list.append(z1)
z2list.append(z2)
zplist.append(z2/z1)
zxlist.append(ki)
zdic={'Z1':z1list,'Z2':z2list,'Z2/Z1':zplist}
zdf=pd.DataFrame(zdic,index=zxlist)
return zdf

zdf0=gzdf()
plt.figure(); zdf0.plot().set_title("t=0.15");
zdf1=gzdf(0.1)
plt.figure(); zdf1.plot().set_title("t=0.1");

zdfe1=zdf0['Z1']*0.8
zdfe2=zdf0['Z2']*0.2
zdfe=pd.DataFrame({'Z1*p':zdfe1,'Z2*(1-p)':zdfe2})
plt.figure(); zdfe.plot().set_title("t=0.15,p=0.8");

def genp(ex=0.8,v=0.2):
nmlist0=list(np.random.normal(ex,v,100))
nmlist=[]
for i in nmlist0:
k=i
if i>1:
k=1
elif i<0:
k=0
nmlist.append(k)
return nmlist


Z1=pd.Series(list(np.arange(1.001,2,0.02)))
b=pd.Series(list(np.arange(1,20,0.2)))
p=0.8
d=1
k=p/(1-p)+d*(b-1)

Gdlist=[]
for i in range(len(k)):
for j in Z1:
gij=j*(k[i]*p+b[i]*(1-p))/(1+k[i])
gdic={'G':gij,'Z1':j,'b':b[i]}
Gdlist.append(gdic)

Gdf=pd.DataFrame(Gdlist)
G=Gdf['G']
plt.figure();Gdf.plot(x='Z1', y='G').set_title("Z1-G,p=0.8");
plt.figure();Gdf[Gdf['Z1']==1.001].plot(x='b', y='G').set_title("b-G,p=0.8");

Hdlist=[]
for i in range(len(k)):
for j in Z1:
gij=j*(k[i]*p+b[i]*(1-p))/(1+k[i])
hij=500*np.sqrt(j+5*b[i]*j)*(1-gij)
hdic={'H':hij,'Z1':j,'b':b[i]}
Hdlist.append(hdic)

Hdf=pd.DataFrame(Hdlist)
plt.figure();Hdf.plot(x='Z1', y='H').set_title("Z1-H,p=0.8,D=4");
plt.figure();Hdf[Hdf['Z1']==1.001].plot(x='b', y='H').set_title("b-H,p=0.8,D=4");

p=0.9
d=1
k=p/(1-p)+d*(b-1)

Hdlist=[]
for i in range(len(k)):
for j in Z1:
gij=j*(k[i]*p+b[i]*(1-p))/(1+k[i])
hij=500*np.sqrt(j+5*b[i]*j)*(1-gij)
hdic={'H':hij,'Z1':j,'b':b[i]}
Hdlist.append(hdic)

Hdf=pd.DataFrame(Hdlist)
plt.figure();Hdf[Hdf['Z1']==1.001].plot(x='b', y='H').set_title("b-H,p=0.9,D=4");