使用Scipy最大化目标(通过Kelly标准)

dm7nw8vv  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(152)

我有以下两个Pandas Dataframe :新闻和结果

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

和 Dataframe '结果'

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的值?结果似乎有很大的不同,通过分配不同的方法和初始值的赌注。
如有任何帮助,我们将不胜感激!
(This是一个例子张贴在顶峰网站:(第10页)

9w11ddsr

9w11ddsr1#

如果打印出函数中的“bet”值,就可以看到哪里出错了。

[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-minimize-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)

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

相关问题