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) ".
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 |
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