RigelのR言語メモであーる(R言語だけとは言っていない)

RigelのR言語メモであーる(主にpython)

興味あることや趣味、やったことについて書くよ

競艇や競馬の買い目最適化(ケリー基準の一般化)

はじめに

ケリー基準を競艇や競馬へ適用できる形に一般化して、

買い目を最適化することを目指します。

ケリー基準の説明は以下のサイトをご参照ください。

http://www.geocities.jp/y_infty/management/index.html

問題設定

特定のレースの特定の券種で、確定オッズ(以下オッズ)と的中確率は所与とします。

そのうち、期待値が{1}を超える券が{N}枚あるとします。

{N}枚の券のうち、{i\ (1 \leq i \leq N)}番目の券の、オッズを{o_i}、的中確率を{p_i}とします。

それぞれの券の期待値が{1}を超えるので、{o_ip_i\geq 1}です。

さて、このときそれぞれの券にいくらずつかけるのが最適ですか?という問題です。

ただし、何レースでも購入でき、オッズは低下せず、少数金額も購入できるとします。

(他にも条件あるかもしれませんが、このくらいで。)

最適化

{i}番目の券を所持金の{f_i}倍購入するとします。

いま、{N}枚の券はすべて同じ券種であるため、互いに排反な事象となります。なので、的中してもどれか1枚です。

(※券種は複勝や拡連複ではないとして、さらに同着や返還等も考えません。)

なので、レースが終わったときの結果の事象としては、

{N}枚の券のうちどれか1枚が的中するか、全部外れるかです。

したがって、ケリー基準を導出する際と同様に考えて、

{\begin{eqnarray}
g(f)=(1-f_0)^{p_0} \prod_{i=1}^N (1+f_i o_i - f_0)^{p_i}
\end{eqnarray}}

この関数を最大化します。

ただし、{f_0=\sum_{i=1}^N f_i, p_0=1-\sum_{i=1}^N p_i}です。

また、{g(f)}{f}は、あらゆる{f_i}の組み合わせ的な感じです。

なぜこの関数を最大化するのかは、上記参考サイトに任せますが、

イメージとしては、

  • {N}枚全部外れる確率は{p_0}で、そのとき所持金は{1-f_0}倍になる。
  • {i}番目の券が的中する確率は{p_i}で、そのとき所持金は{1+f_i o_i - f_0}倍になる。

それらの期待値のような感じです。

掛け算や指数があれなので、最適化の常套手段である対数変換をします。

{\begin{eqnarray}
\log(g(f))=p_0\log(1-f_0) + \sum_{i=1}^N p_i\log(1+f_i o_i-f_0))
\end{eqnarray}}

ベクトルで偏微分とか苦手なので、地道にいきます。

上式を、{n\ (1 \leq n \leq N)}番目の券の購入割合{f_n}偏微分してイコール{0}とおくことで、

{\begin{eqnarray}
\frac{\partial \log(g(f))}{\partial f_n}=-\frac{p_0}{1-f_0} - \sum_{i=1}^N \frac{p_i}{1+f_i o_i-f_0} + \frac{o_n p_n}{1+f_n o_n-f_0}=0
\end{eqnarray}}

となります。

ここで、第1項と第2項は{n}によらず一定です。

なので、別の{m\ (1 \leq m \leq N)}番目の券の購入割合{f_m}偏微分した場合は、

第3項だけが変わるので、

{\begin{eqnarray}
\frac{o_n p_n}{1+f_n o_n-f_0}=\frac{o_m p_m}{1+f_m o_m-f_0}
\end{eqnarray}}

が成り立ちます。

変形して、

{\begin{eqnarray}
\frac{p_n}{1+f_n o_n-f_0}=\frac{o_m}{o_n}\frac{p_m}{1+f_m o_m-f_0}
\end{eqnarray}}


となります。

この式により、偏微分した式の第2項の総和の中身のインデックスを

オッズの比をかけることで、変換できるようになります。

第2項の総和の中身のインデックス{i}{n}に変換します。

{\begin{eqnarray}
\frac{\partial \log(g(f))}{\partial f_n}=&&-\frac{p_0}{1-f_0} - \sum_{i=1}^N \frac{p_i}{1+f_i o_i-f_0} + \frac{o_n p_n}{1+f_n o_n-f_0}\\
=&&-\frac{p_0}{1-f_0} - \sum_{i=1}^N \frac{o_n}{o_i}\frac{p_n}{1+f_n o_n-f_0} + \frac{o_n p_n}{1+f_n o_n-f_0}\\
=&&-\frac{p_0}{1-f_0} + \frac{o_n p_n}{1+f_n o_n-f_0} (1-\sum_{i=1}^N \frac{1}{o_i})=0\\
\end{eqnarray}}

{(1-\sum_{i=1}^N \frac{1}{o_i}) = o_0}とおいて、さらに変形をつづけます。

{\begin{eqnarray}
 - \frac{p_0}{1-f_0} + \frac{o_n p_n}{1+f_n o_n-f_0} o_0 = 0\\
 - p_0(1+f_n o_n-f_0)+(1-f_0)o_n o_0 p_n = 0\\
f_0(p_0-o_n o_0 p_n) - f_n o_n p_0 = p_0 - o_n o_0 p_n
\end{eqnarray}}

上式はすべての{n\ (1 \leq n \leq N)}について成り立ちます。

ここまでくるともう少しですね。

いま求めたいのは、{f_n\ (1 \leq n \leq N)}ですけど、

線形になっているので、解けますね。

具体的には、

{N}次元縦ベクトル
{\displaystyle
\boldsymbol{f} = \ ^t(f_1,\ f_2,\ \ldots,\ f_N)
}
{N \times N}の行列
{\displaystyle
\boldsymbol{A} = 
\begin{pmatrix}
p_0 - o_1 o_0 p_1 - o_1 p_0 & p_0 - o_1 o_0 p_1 & \cdots & p_0 - o_1 o_0 p_1\\
p_0 - o_2 o_0 p_2 & p_0 - o_2 o_0 p_2 - o_2 p_0 & \cdots & p_0 - o_2 o_0 p_2\\
\vdots & \vdots & \ddots & \vdots\\
p_0 - o_N o_0 p_N & p_0 - o_N o_0 p_N & \cdots & p_0 - o_N o_0 p_N - o_N p_0\\
\end{pmatrix}
}
{N}次元縦ベクトル
{\displaystyle
\boldsymbol{b} = \ ^t(p_0 - o_1 o_0 p_1,\ p_0 - o_2 o_0 p_2,\ \ldots,\ p_0 - o_N o_0 p_N)
}
とすると、
{\begin{eqnarray}
\boldsymbol{A}\boldsymbol{f}=\boldsymbol{b}
\end{eqnarray}}
が成り立ちますので、最適な{\boldsymbol{f}}は、
{\begin{eqnarray}
\boldsymbol{f}=\boldsymbol{A}^{-1} \boldsymbol{b}
\end{eqnarray}}
と求まりました。

{N=1}の場合について考えて、ケリー基準と一致するか確認してみます。

{N=1}のとき、

{\displaystyle
\boldsymbol{A}=(p_0 - o_1 o_0 p_1 - o_1 p_0), \ \boldsymbol{b}=(p_0 - o_1 o_0 p_1)
}

なので、
{\begin{eqnarray}
(f_1) = \boldsymbol{f}=&&\boldsymbol{A}^{-1} \boldsymbol{b}\\
=&&\left( \frac{p_0 - o_1 o_0 p_1}{p_0 - o_1 o_0 p_1 - o_1 p_0} \right)
\end{eqnarray}}
となります。

ここで、
{\displaystyle
p_0=1-p_1, \ o_0=1-\frac{1}{o_1}
}
なので、
{\begin{eqnarray}
(f_1)=&&\left( \frac{p_0 - o_1 o_0 p_1}{p_0 - o_1 o_0 p_1 - o_1 p_0} \right)\\
=&&\left( \frac{(1-p_1) - o_1 \left(1-\frac{1}{o_1}\right) p_1}{(1-p_1) - o_1 \left(1-\frac{1}{o_1}\right) p_1 - o_1(1-p_1)} \right)\\
=&&\left( \frac{o_1 p_1 - 1}{o_1 -1} \right)
\end{eqnarray}}
となり、普通のケリー基準の式と一致します。

(参考サイトや一般的に紹介されているケリー基準と違うのはオッズの置き方によるもの。本質的には全く同じ。)

数値シミュレーション

求めた解が正しいか、数値シミュレーションで確認します。

現実ではありえないかもしれませんが{N=3}で、

{p_1=0.1,\ o_1=15,\ p_2=0.2,\ o_2=6,\ p_3=0.3,\ o_3=4}

という状況を考えます。

期待値はそれぞれ順に{1.5, 1.2, 1.2}となります。

{1}番目の券が一番期待値高いです。{2}番目と{3}番目の券は期待値同じです。

最適な{\boldsymbol{f}}を求めると、{f_1=0.048,\ f_2=0.071,\ f_3=0.106}となりました。

{2}番目と{3}番目の券を比較すると期待値は同じですが、

確率は{3}番目の券の方が高いため、購入金額の割合は大きいです。

{1}番目の券が一番期待値高いですが、一番購入金額は低くなりました。

的中確率が小さいためですね。

では、この設定で5000レースシミュレーションしてみます。

また、最適な{\boldsymbol{f}}に、

定数{0.2,\ 0.4,\ 0.6,\ 0.8,\ 1.2,\ 1.4,\ 1.6,\ 1.8}を掛けた場合も同時に示します。

f:id:strawberry_kyon:20190326220623p:plain

f:id:strawberry_kyon:20190326220630p:plain

横軸はレース数、縦軸は所持金で対数グラフです。初期所持金は{1}としました。

どうやら、求めたものは正しかったようですね。

最適な{\boldsymbol{f}}より小さいと、資産の増え方は下がりばらつきが抑えられます。

一方最適な{\boldsymbol{f}}より大きいと、資産の増え方は下がりばらつきが増えます。

レース数が少ないとき、一時的に資産が最適な{\boldsymbol{f}}のときの資産を上回る可能性はありますが、長期的にみるといいことないですね。

なので、ハーフケリーとかの方法があるんですかね。

おわりに

今回は、的中確率とオッズが所与のときの買い目を最適化しました。

今後の課題としては、

  • 複数種類の券種がある場合どうなるか
  • 的中確率やオッズが確立変数として与えられたときどうなるか

です。気になります。

のちのち考えていきます。

Rコード

library(ggplot2)
p=c(0.1,0.2,0.3)
o=c(15,6,4)
N=length(p)
p0=1-sum(p)
o0=1-sum(1/o)
f=solve(matrix(p0-p*o*o0,ncol=N,nrow=N)-diag(N)*p0*o)%*%(p0-p*o*o0)

p*o
f

R=5000
flg=sample(1:(N+1),R,prob=c(p,p0),replace=TRUE)

ff=f
data=data.frame(R=1:R,w=cumprod(c(1+ff*o-sum(ff),1-sum(ff))[flg]))
g=ggplot()+geom_line(data=data,aes(x=R,y=w),color=2)+scale_y_log10()
for(i in seq(0.2,0.8,by=0.2)){
  ff=f*i
  data=data.frame(R=1:R,w=cumprod(c(1+ff*o-sum(ff),1-sum(ff))[flg]))
  g=g+geom_line(data=data,aes(x=R,y=w))
}
g

ff=f
data=data.frame(R=1:R,w=cumprod(c(1+ff*o-sum(ff),1-sum(ff))[flg]))
g=ggplot()+geom_line(data=data,aes(x=R,y=w),color=2)+scale_y_log10()
for(i in seq(1.2,1.8,by=0.2)){
  ff=f*i
  data=data.frame(R=1:R,w=cumprod(c(1+ff*o-sum(ff),1-sum(ff))[flg]))
  g=g+geom_line(data=data,aes(x=R,y=w))
}
g