使用scipy最大化目标(根据kellycriterium)



我有以下两个panda数据帧:new&结果

new = pd.DataFrame([[5,5,1.6],[0.22,0.22,0.56]]).T
new.index = ['Visitor','Draw','Home']
new.columns = ['Decimal odds', 'Win prob'] 
new['Bet amount'] = np.zeros((len(new),1))

带输出:

Decimal odds  Win prob  Bet amount
Visitor           5.0      0.22         0.0
Draw              5.0      0.22         0.0
Home              1.6      0.56         0.0

数据帧"结果">

outcome = pd.DataFrame([[0.22,0.22,0.56],[100,100,100]]).T
outcome.index = ['Visitor win','Draw','Home win']
outcome.columns = ['Prob.','Starting bankroll']
outcome['Wins'] = ((new['Decimal odds'] - 1) * new['Bet amount']).values
outcome['Losses'] = [sum(new['Bet amount'][[1,2]]) , sum(new['Bet amount'][[0,2]]), sum(new['Bet amount'][[0,1]])]
outcome['Ending bankroll'] = outcome['Starting bankroll'] + outcome['Wins'] - outcome['Losses']
outcome['Logarithm'] = np.log(outcome['Ending bankroll'])

带输出:

Prob.  Starting bankroll  Wins  Losses  Ending bankroll  Logarithm
Visitor win   0.22              100.0   0.0     0.0            100.0    4.60517
Draw          0.22              100.0   0.0     0.0            100.0    4.60517
Home win      0.56              100.0   0.0     0.0            100.0    4.60517

因此,objective通过以下公式计算:

objective = sum(outcome['Prob.'] * outcome['Logarithm'])

现在,我想通过列"new"["Bet amount"]中包含的值来最大化objective。约束条件是a、b和c的边界在0和100之间。此外,a、b和c的总和必须低于100。原因是a,b,c类似于你用来进行体育博彩的资金比例。

希望使用scipy库实现这一点。到目前为止,我的代码看起来像:

from scipy.optimize import minimize
prob = new['Win prob']
decimal = new['Decimal odds']
bank = outcome['Starting bankroll'][0]
def constraint1(bet):
a,b,c = bet

return 100 - a + b + c
con1 = {'type': 'ineq', 'fun': constraint1}
cons = [con1]

b0, b1, b2 = (0,100), (0,100), (0,100)     
bnds = (b0, b1, b2)
def f(bet, sign = -1):
global prob, decimal, bank
p0,p1,p2 = prob
d0,d1,d2 = decimal
a,b,c = bet

wins0 = a * (d0-1)
wins1 = b * (d1-1)
wins2 = c * (d2-1)

loss0 = b + c
loss1 = a + c
loss2 = a + b
log0 = np.log(bank + wins0 - loss0)
log1 = np.log(bank + wins1 - loss1)
log2 = np.log(bank + wins2 - loss2)

objective = (log0 * p0 + log1 * p1 + log2 * p2)

return sign * objective

bet = [5,8,7]
result = minimize(f, bet, method = 'SLSQP', bounds = bnds, constraints = cons)

然而,这并没有产生期望的结果。期望的结果是:

a = 3.33
b = 3.33
c = 0

我的问题也是如何设置methodinitial的值?通过为赌注分配不同的方法和初始值,结果似乎差异很大。

如有任何帮助,我们将不胜感激!

(这是发布在顶峰网站上的一个例子:https://www.pinnacle.com/en/betting-articles/Betting-Strategy/the-real-kelly-criterion/HZKJTFCB3KNYN9CJ)

如果您打印出;"下注";在函数中的值,您可以看到哪里出了问题。

[5. 8. 7.]
[5.00000001 8.         7.        ]
[5.         8.00000001 7.        ]
[5.         8.         7.00000001]
[5.00040728 7.9990977  6.99975556]
[5.00040729 7.9990977  6.99975556]
[5.00040728 7.99909772 6.99975556]
[5.00040728 7.9990977  6.99975558]
[5.00244218 7.99458802 6.99853367]
[5.0024422  7.99458802 6.99853367]

该算法试图通过相对于初始值的微小调整来优化公式,但它的调整永远不会达到你想要的值。

如果你查看scipy网页,你会发现https://docs.scipy.org/doc/scipy/reference/optimize.minimize-slsqp.html#optimize-最小化slsqp

eps float
Step size used for numerical approximation of the Jacobian.
result = minimize(f, bet, method='SLSQP', bounds=bnds, constraints=cons,
options={'maxiter': 100, 'ftol': 1e-06, 'iprint': 1, 'disp': True,
'eps': 1.4901161193847656e-08, 'finite_diff_rel_step': None})

所以你从1.0e-08的步长开始,所以你的初始估计偏离了算法要寻找的范围很多数量级。

我建议您将赌注标准化为0到1之间的值。所以,与其说我在0到100之间下注,不如说你在0到1之间下注了你净财富的一小部分。许多算法被设计用于处理标准化输入(在0和1之间(或标准化输出(与平均值的标准偏差(。

此外,它看起来像:

def constraint1(bet):
a,b,c = bet

return 100 - a + b + c

应该是:

def constraint1(bet):
a,b,c = bet

return 100 - (a + b + c)

但我不认为这会影响你的结果

最新更新