帝王賞を最適化問題で解いたらどうだったか?

結果から言うと

安易な考えすぎて、解が出ませんでした。

最適化問題とは・・・?
こちらより引用させていただきました。

変数目的関数制約条件といった要素を定義して、制約を満たしつつ目的の値を最大化/最小化する条件を求める問題です。

過程

2023年の帝王賞は12頭立て、内JRA勢が7頭
実力的にはJRA勢が揃いすぎた感じのメンバーで、
ほぼ間違いなく上位2頭にはJRAの馬が入りそう。
この7頭という頭数だったら、

絶対プラスになる買い方があるのではないか、

と思った次第です。
そこで最適化問題の登場です。

参考

こちらに丁度よいPythonのソースコードあったので参考にさせていただきました。

解いてみた

「JRA勢が上位1,2着に入る」という条件付きになりますが、必ずプラスになる買い方を見つけようという試みです。
単勝オッズと馬単オッズを使用します。

オッズや馬番などは公式から参考にしました。
コーディングはPythonで。取得したオッズデータ等をDataFrameに格納します(df)。
因みにオッズデータはこんな感じになってます。上の方に単勝オッズが並び、その後、馬単オッズが続いています。

  • First: 1位予想馬

  • Second: 2位予想馬(-1の場合は単勝)

  • Odds: オッズ

帝王賞2023 単勝と馬単オッズ(JRA勢のみ)

Pythonコード

最適解を出すメイン部分の関数になります。(上記参考サイトより)

from ortoolpy import addbinvars, lpSum, model_min, pd
def solve(df: pd.DataFrame, num: int, alpha: float) -> pd.DataFrame:
    """購買数を求める

    :param df: 変数表
    :param num: 購買数上限
    :param alpha: リターン比
    
    :return: 変数表(Val列が購買数)
    """
    n = len(df[df.Second == -1])  # 単勝の行数
    m = model_min(dfi=df)  # 数理モデル
    df["Mono"] = None  # 単勝を買うかどうか
    df.loc[:n-1, "Mono"] = addbinvars(n)
    m += lpSum(df.Var)  # 目的関数(総購買数)
    m += lpSum(df.Var) <= num  # 購買数上限

    # 単勝
    for row in df[:n].itertuples():
        m += row.Odds * row.Var >= num * alpha * row.Mono
        df.loc[df.First == row.First, "Mono"] = row.Mono

    # 馬単
    for row in df[n:].itertuples():
        m += row.Odds * row.Var >= num * alpha * (1 - row.Mono)

    # こんな感じで使うみたい
    # m.solve(objs=['-XXX', 'YYY'])
    m.solve()
    # df['Val'] に結果が入る

    try:
        df["Prize"] = df.Odds * df.Val * 100
        return df[df.Val > 0] if m.status==1 else None

    except Exception as e:
        print(f'[Warning] 解なし m.status = {m.status}, {e}')
        return pd.DataFrame()  # 解がなければ空を返す

res = solve(df, num=1000, alpha=1.05)  # num: 百円単位
res

条件:100,000円を賭ける
   回収率を105%に設定

計算結果

この条件でやってみましたが、解が出ませんでした。
ちょっと安易すぎたか。

条件変更

res = solve(df, num=500, alpha=0.88)  # num: 百円単位

条件:50,000円を賭ける
   回収率を88%に設定

この条件にしたら一応解は出ましたが、必ず12%は負ける賭け方なので、駄目ですね。Valがベット数で、Prizeが返ってきた額です。
50,000円賭けて、大体44,000〜 46,000円位のリターンになってますね。

表の見方
1行目:4番(メイショウハリオ)の単勝に11,300円賭けて44,070円の払い戻し
4行目:1番(テーオーケインズ)->4番(メイショウハリオ)の馬単に5,800円賭け   て44,160円の払い戻し

今回の帝王賞は「解なし」という結果になりましたが、少頭数のレースを見つけて、またいつか検証してみようと思います。
以上になります。またお会いしましょう


この記事が気に入ったらサポートをしてみませんか?