[PYTHON] Horse racing winning method by combinatorial optimization

what is this

I tried to solve it by combinatorial optimization by combining "Programming the horse racing winning method".

--The way of thinking is based on "Umameshi.com Horse Racing Winning Method". --For the program, see "[Optimization of crude oil refining --Points of modeling](https://qiita.com/SaitoTsutomu/items/e3ef218b78fd859b4aeb#%E3%83%A2%E3%83%87%E3%83] % AB% E5% 8C% 96% E3% 81% AE% E3% 83% 9D% E3% 82% A4% E3% 83% B3% E3% 83% 88) ".

raw data

September 20, 2013 It is a table of wins and horses in one race of Nagoya horse racing. Ask for how many betting tickets to buy for each row in this table.

from ortoolpy import addbinvars, lpSum, model_min, pd


def sample_data_frame() -> pd.DataFrame:
    """September 20, 2013 Nagoya Horse Racing 1 Race Table

    :return: 「First=1st arrival number, Second=2 arrival number (-1 wins), Odds=Odds table
    """
    ls = list(range(1, 8))
    df1 = pd.DataFrame({  #Win
        "First": ls,
        "Second": [-1] * 7,
        "Odds": [14.7, 72.6, 1.4, 2.3, 151.8, 18.0, 66.8],
    })
    df2 = pd.DataFrame({  #Horse single
        'First': [i for i in ls for _ in ls[1:]],
        'Second': [j for i in ls for j in ls if i != j],
        'Odds': [
            347.2, 37.4, 54.0, 662.7, 169.6, 607.5, 455.6, 177.8, 197.1,
            1457.9, 331.4, 2429.8, 23.0, 86.8, 5.4, 50.7, 13.0, 177.8, 10.3,
            49.3, 1.9, 90.0, 5.9, 123.6, 1214.9, 1457.9, 74.4, 455.6, 560.8,
            3644.7, 119.5, 347.2, 27.6, 43.2, 486.0, 455.6, 1041.4, 2429.8,
            1214.9, 911.2, 3644.7, 911.2
        ]
    })
    return pd.concat([df1, df2]).reset_index(drop=True)


df = sample_data_frame()
# First=1st arrival number, Second=2 arrival number (-1 wins), Odds=Odds
df[:3]  #First 3 lines
First Second Odds
0 1 -1 14.7
1 2 -1 72.6
2 3 -1 1.4

optimisation

def solve(df: pd.DataFrame, num: int, alpha: float) -> pd.DataFrame:
    """Find the number of purchases

    :param df:Variable table
    :param num:Maximum number of purchases
    :param alpha:Return ratio
    :return:Variable table (Val column is the number of purchases)
    """
    n = len(df[df.Second == -1])  #Number of lines to win
    m = model_min(dfi=df)  #Mathematical model
    df["Mono"] = None  #Whether to buy a win
    df.loc[: n - 1, "Mono"] = addbinvars(n)
    m += lpSum(df.Var)  #Objective function (total number of purchases)
    m += lpSum(df.Var) <= num  #Maximum number of purchases
    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()
    df["Prize"] = df.Odds * df.Val * 100
    return df[df.Val > 0] if m.status == 1 else None


res = solve(df, num=1000, alpha=1.08)
res
First Second Odds Var Mono Val Prize
1 2 -1 72.6 v000002 v000051 15 108900
3 4 -1 2.3 v000004 v000053 470 108100
4 5 -1 151.8 v000005 v000054 8 121440
5 6 -1 18 v000006 v000055 60 108000
7 1 2 347.2 v000008 v000050 4 138880
8 1 3 37.4 v000009 v000050 29 108460
9 1 4 54 v000010 v000050 20 108000
10 1 5 662.7 v000011 v000050 2 132540
11 1 6 169.6 v000012 v000050 7 118720
12 1 7 607.5 v000013 v000050 2 121500
19 3 1 23 v000020 v000052 47 108100
20 3 2 86.8 v000021 v000052 13 112840
21 3 4 5.4 v000022 v000052 200 108000
22 3 5 50.7 v000023 v000052 22 111540
23 3 6 13 v000024 v000052 84 109200
24 3 7 177.8 v000025 v000052 7 124460
43 7 1 1041.4 v000044 v000056 2 208280
44 7 2 2429.8 v000045 v000056 1 242980
45 7 3 1214.9 v000046 v000056 1 121490
46 7 4 911.2 v000047 v000056 2 182240
47 7 5 3644.7 v000048 v000056 1 364470
48 7 6 911.2 v000049 v000056 2 182240

--The maximum number of purchases is 1000 (num). Since each sheet is 100 yen, the military fund is 100,000 yen. ――We will set a constraint so that no matter which horse wins, the dividend will be at least 108,000 yen (military funds x ʻalpha). --As a result, I will buy 999 pieces (res.Val.sum ()). ――No matter which horse from 1 to 7, the Prize` row is over 108,000 yen.

ʻAlpha = 1.08` should be found by a 2-minute search. It's amazing that it's 100% profitable, not a desk theory.

that's all

Recommended Posts

Horse racing winning method by combinatorial optimization
Grouping by combinatorial optimization
Divide into teams by combinatorial optimization (simulated annealing method)
Solving "cubes in cubes" by combinatorial optimization
Determine recorded programs by combinatorial optimization
SVM optimization by active set method
Divide into teams by combinatorial optimization
Think about menus by combinatorial optimization
Minimize the number of polishings by combinatorial optimization
Judging the finish of mahjong by combinatorial optimization
Use combinatorial optimization
Divide into teams by combinatorial optimization (minimize average deviation)
A concrete method of predicting horse racing by machine learning and simulating the recovery rate
Gurobi-like optimization description method
Let's decide the lecture of PyCon JP 2016 by combinatorial optimization
Let's decide the position of the fire station by combinatorial optimization