Loading [MathJax]/jax/output/CommonHTML/fonts/TeX/AMS-Regular.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >All in 凉凉!德州赔率怎么算?我用Python来搞定

All in 凉凉!德州赔率怎么算?我用Python来搞定

作者头像
量化投资与机器学习微信公众号
发布于 2020-05-14 09:55:35
发布于 2020-05-14 09:55:35
3.2K00
代码可运行
举报
运行总次数:0
代码可运行

编译:1+1=6

1

介绍

在今天的推文中,公众号将向大家展示如何在Python中表示基本的扑克元素,例如“手牌”和“组合牌”(Hands、Combos),以及如何计算扑克赔率,即在无限注德州扑克中获胜/平局/失败的可能性。我们将使用Poker包来表示手牌、组合和区间。

https://poker.readthedocs.io/en/latest/index.html

首先导入相关库文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from poker import Range
from poker.hand import Combo

import holdem_calc
import holdem_functions

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.core.display import display, HTML

hero_odds = []
hero_range_odds = []

2

翻牌(Flop)

K♠、J♣

我们将使用poker.hand来构造我们的手牌:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
hero_hand = Combo('KsJc')
print(hero_hand)

我们不清楚翻牌前发生的事情以及我们的位置。我们只知道翻牌前有加注,而翻牌后只剩下两名玩家:我们自己和另外一个人。

我们现在领先了。翻牌出现了:

Q♣、10♠、J♠

是的,顺子!

假设没我们有事先了解对方的牌型,让我们计算翻牌后的赔率:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
flop = ["Qc", "Th", "9s"] 
board = flop
villan_hand = None 
exact_calculation = True 
verbose = True 
num_sims = 1 
read_from_file = None 

odds = holdem_calc.calculate_odds_villan(board, exact_calculation, 
                            num_sims, read_from_file , 
                            hero_hand, villan_hand, 
                            verbose, print_elapsed_time = True)

Holdem_calc中的函数calculate_odds_villan计算出特定的德州扑克某手牌获胜的概率。通过运行蒙特卡罗方法可以估算出该概率,也可以通过模拟所有可能的手牌来精准计算。快速计算翻牌后的精准赔率,因此在这里我们不需要蒙特卡罗近似值。这是我们的赔率:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
hero_odds.append(odds[0]['win'])

odds[0]
{'tie': 0.04138424018164999,
 'win': 0.9308440557284221,
 'lose': 0.027771704089927955}

此时,我们感觉还不错。与随机牌相比,我们只有2.77%的机会输,获胜的机会超过93%,这很乐观。

考虑到翻牌前有加注,对反很可能会有一些东西。我们称这种可能的手牌为一个区间。这是我们根据几个因素(包括对反的举止、位置、赌注大小等)做出的推论。该推论导致我们假设对反可能拥有一组手牌:

  • 一对7或更好
  • A /10或更好
  • K/J或更好

我们可以使用Class Range来表示该区间,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
villan_range = Range('77+, AT+, KJ+')
display(HTML(villan_range.to_html()))
print("#combo combinations:" + str(len(villan_range.combos)))

144

这使我们对手的牌组合从 51*52–1=2651 减少到 144 种组合。现在假设对手的区间来计算我们的赔率。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
items = [holdem_calc.calculate_odds_villan(board, exact_calculation, 
                            num_sims, read_from_file , 
                            hero_hand, villan_hand, 
                            verbose, print_elapsed_time = False) for villan_hand in villan_range.combos]

odds = {}
[odds.update({odd_type: np.mean([res[0][odd_type] for res in items if res])}) for odd_type in ["tie", "win", "lose"]]
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
hero_range_odds.append(odds['win'])

odds
{'tie': 0.11423324150596878,
 'win': 0.8030711151923272,
 'lose': 0.08269564330170392}

在给定假定的区间内,我们的获胜几率从93%下降至80%。但是,损失8.2%的可能性仍然很低,但是我们应该打赌吗?我们绝对希望对手继续比赛并且不弃牌。但是他在翻牌后有一手好牌的可能性有多大?让我们看看如果我们继续玩到最后,他下一手牌的几率有多大。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for hand_ranking in holdem_functions.hand_rankings:
    print(hand_ranking +": " + str(np.mean([res[1][1][hand_ranking] for res in items if res])))
    
High Card: 0.06978879706152433
Pair: 0.3662891541679421
Two Pair: 0.23085399449035812
Three of a Kind: 0.09733700642791548
Straight: 0.18498112437506373
Flush: 0.0040608101214161816
Full House: 0.04205693296602388
Four of a Kind: 0.004560759106213652
Straight Flush: 2.0406081012141617e-05
Royal Flush: 5.101520253035404e-05

如果我们继续玩到河牌(第五张公共牌),对反就有很好的机会做出:

  • 一对(36%)
  • 两对(23%)

他极有可能命中:

  • 顺子(18%)
  • 一盘-暗三条(9.7%)
  • 满堂-三条+一对(4%)

由于对反很有可能拥有合理的手牌,因此我们决定下高注,大约底池的2/3。

3

转牌(Turn)

回合了来:

2♦

平局!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
turn= ["2d"]
board = flop + turn
villan_hand = None

odds = holdem_calc.calculate_odds_villan(board, exact_calculation, 
                            num_sims, read_from_file , 
                            hero_hand, villan_hand, 
                            verbose, print_elapsed_time = True)
hero_odds.append(odds[0]['win'])

print(odds[0])

Time elapsed:  0.5410661697387695
{'tie': 0.0233201581027668, 'win': 0.9677206851119895, 'lose': 0.008959156785243741}

假设对手的牌是随机的,那么我们现在有96%的获胜几率。

但是,考虑到我们假定的对手区间,我们的获胜几率现在从翻牌时的80%上升到86%。我们再次下注,对手跟注,河牌来了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
items = [holdem_calc.calculate_odds_villan(board, exact_calculation, 
                            num_sims, read_from_file , 
                            hero_hand, villan_hand, 
                            verbose, print_elapsed_time = False) for villan_hand in villan_range.combos]

odds = {}
[odds.update({odd_type: np.mean([res[0][odd_type] for res in items if res])}) for odd_type in ["tie", "win", "lose"]]

hero_range_odds.append(odds['win'])
odds
{'tie': 0.10123966942148759,
 'win': 0.8615702479338843,
 'lose': 0.0371900826446281}

4

河牌(River)

K♣

河牌的梅花K使顺子更容易被对手抓住。所以这对我们来说是个坏消息。

现在,我们对随机牌的胜算从96%降至约87%。但是我仍然只是以1.2% 的极低概率输掉了比赛。

好吧,还有另外一个因素。对手在翻牌和河牌都跟我们下了大赌注。他可能有比我们想像的更好的牌。那么,我们应该调整我们的假设区间。

现在,我们认为对手不再拥有77或88的组合,否则,鉴于我们的高赌注,他不会走那么远。我们认为他可能要搭配99或更好的一对,才能与99、10或QQ配对。他可能还会有JJ、KK或者AA。由于所谓的隐含赔率,我们决定保留Ace 10或更好和King Jack或更好的组合。隐含赔率是对如果你打出一笔钱可以从投注中赢取多少钱的估计。因此,对手可能希望打一场平局。因此,我们将对手的更新区间定义如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
villan_range = Range('99+, AT+, KJ+') 
display(HTML(villan_range.to_html()))
print("#combo combinations:" + str(len(villan_range.combos)))

现在,对手的组合数从144降低了132。让我们计算更新后的赔率。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
tems = [holdem_calc.calculate_odds_villan(board, exact_calculation, 
                            num_sims, read_from_file , 
                            hero_hand, villan_hand, 
                            verbose, print_elapsed_time = False) for villan_hand in villan_range.combos]

odds = {}
[odds.update({odd_type: np.mean([res[0][odd_type] for res in items if res])}) for odd_type in ["tie", "win", "lose"]]

hero_range_odds.append(odds['win'])
odds
{'tie': 0.12, 'win': 0.72, 'lose': 0.16}

现在,我们有72%的胜算(从86%下降),失利几率从3.7%增加到16%。我们决定检查一下,对手全押,下注大约底池的70%。

一个基本和标准的河牌策略:

1、用你最薄弱的资产作为河牌虚张声势。

2、用你最强的资产作为价值押注(Value Bet)

3、用中的摊牌价值(Show down value,简称SDV)检查牌局,以期达到摊牌。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for hand_ranking in holdem_functions.hand_rankings:
    print(hand_ranking +": " + str(np.mean([res[1][1][hand_ranking] for res in items if res])))
    
High Card: 0.0
Pair: 0.5066666666666667
Two Pair: 0.08
Three of a Kind: 0.13333333333333333
Straight: 0.28
Flush: 0.0
Full House: 0.0
Four of a Kind: 0.0
Straight Flush: 0.0
Royal Flush: 0.0

根据赔率直方图,我们可以将对手的可能手分为3种类型:

1、虚张声势:他持有(高牌,对子)的几率为60.66%。

2、SDV:他持有(两对)的几率为0.8%。

3、最强持牌:他持有(三张相同的牌-顺子)的几率为41.33%。

对手的全押是有道理的。所以在这里,所以我认为他要么是在虚张声势,比如因为错过了一场平局,要么就是在胡说八道,这是一个价值押注。虚张声势或价值押注的基本策略有时被称为两极化押注。 这就是对手在做的事。

回顾每种类型的概率(虚张声势、SDV、价值押注),我们基本上应该至少赢得60.66%,这是一个保守的衡量标准,因为对手可能会价值押注三倍。但是我们应该跟注吗?

这是另一个称为底池赔率(Pot Odds)的概念。你可能会经常听大家常说到。跟注的成败比是3:1,遭遇对手1.5:1的全下,Pot Odds 在德州扑克里都是以比例的形式出现。

池赔率是指相对于底池大小进行下注的价格,它是期望回报与面临风险的比例的数学表达式。数学公式就是:

风险 : 回报

举个例子:底池Pot 40,此时的Pot Odds就是40:(40+80)=3:1,意思是你要跟注40你才能赢得

总而言之,如果我们赢得底池的概率大于底池限注价格和底池大小之间的比率,我们应该跟注。

那么对于这把牌局:

1、胜算 ≥ 60.66%(保守)

2、跟注价格 = 0.7 * 底池大小

3、跟注后底池大小 =(1 + 0.7 + 0.7)* 底池大小

4、底池赔率 = 跟注价格 跟注后底池大小 = 29%

我们获胜的机会至少是底池赔率的两倍。因此,我们继续跟注。结果如何?对手是:

A、J

呵呵!

4

结语

下面,我们向读者展示了我们的获胜几率是如何从翻牌变成转牌,然后是河牌(假设对手玩家随机出牌)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
df_odds = pd.DataFrame(
{"board" : ["flop","turn", "river"],
"hero_odds" : hero_odds,
"hero_range_odds" : hero_range_odds,
}

index = [1, 2, 3])
In [22]:
ax = plt.gca()
df_odds.plot(kind='line',x='board',y='hero_odds', marker='o', ax=ax)
df_odds.plot(kind='line',x='board',y='hero_range_odds',color='red' ,marker='o', ax=ax)
plt.show()

我们观察到,即使最终结果不利于我们,我们还是最有可能赢得这一平手牌。这就是为什么扑克玩家说:

你应该专注于做出的决定,而不是所取得的结果!

当然,本文中的所有分析都假设了一些区间和基本的扑克策略,这些策略构成了我们在玩游戏时的思维模型,并用Python实现。这手牌有很多玩法。我们也犯了一些错误。例如,在翻牌前加注的情况下,低估了对反持有A、J的机会。

希望大家在牌桌上有更好的表现!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量化投资与机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python装饰器详解
该段代码的缺点 1.我们期望的是直接调用主要函数,同时执行辅助函数,而并不是把辅助函数写在前面。
Yuou
2022/09/26
2700
Python装饰器详解
我们现在想一下,把查找奇数和统计时间放在一个方法中(耦合),那么这两个功能任意一个出了问题,都要复查所有代码,修改起来会很麻烦。
孟船长
2022/02/23
2140
Python装饰器详解
统计学习导论 Chapter4--Classification
本文介绍了统计学习导论中的Chapter 4 - Classification,讲解了三种经典的分类方法:逻辑回归、线性判别分析、K-近邻。首先介绍了为什么不用线性回归方法来处理分类问题,然后详细阐述了逻辑回归方法、线性判别分析方法和K-近邻方法的具体实现步骤和原理。最后介绍了如何通过最大似然方法来估计模型参数,并给出了多类别分类的另一种常用方法:线性判别分析。
用户1148525
2018/01/03
5590
统计学习导论 Chapter4--Classification
logistic regression一点理解
关于logistic regression一些常见问题,整理出来,方便大家应对各种坑爹的面试官。
用户1332428
2018/10/08
5510
logistic regression一点理解
体育赛事即时比分 分析页面的开发技术架构与实现细节
本文基于“体育即时比分系统”的实际开发经验总结,仅供技术交流。该系统在实现过程中,主要解决了实时比分更新、赔率数据同步、赛事分析展示等关键问题,并采用了以下技术栈:
用户10027718
2025/03/26
700
体育赛事即时比分 分析页面的开发技术架构与实现细节
发家致富靠AI:使用keras预测NBA比赛赚钱,回报率136%
投注者和博彩者没有太多共同点——人们可以把他们的关系描述为一场竞争、决斗、战争。但在梦中,他们却为同样的幻想而垂涎三尺:一个完美的预测模型,使用它能够精确地预测出未来游戏的结果。通过深入学习,这或许是可能的——或者至少比以前的数据科学技术更容易。
deephub
2020/05/09
1.2K0
发家致富靠AI:使用keras预测NBA比赛赚钱,回报率136%
简单的统计学:如何用Python计算扑克概率
在本文中,我们展示了如何在Python中表示基本的扑克元素,例如“手”和“组合”,以及如何计算扑克赔率,即在无限额德州扑克中获胜/平局/失败的可能性。
deephub
2020/05/20
2.7K0
简单的统计学:如何用Python计算扑克概率
银行信用评分卡中的WOE在干什么?
woe全称叫Weight of Evidence,常用在风险评估、授信评分卡等领域。
流川疯
2021/12/08
1.5K0
银行信用评分卡中的WOE在干什么?
基于 mlr 包的逻辑回归算法介绍与实践(下)
上期 基于 mlr 包的逻辑回归算法介绍与实践(上)关于逻辑回归的介绍内容中主要包括了特征工程、特征选择和缺失值的处理等问题,都是小编之前没有系统学过的机器学习任务。本期逻辑回归内容基于上期进行了扩展,主要包括逻辑回归中的交叉验证、odds ratio 和预测等。
庄闪闪
2022/04/08
6930
基于 mlr 包的逻辑回归算法介绍与实践(下)
重磅 | 继 AlphaGo 又一突破:人工智能战胜德州扑克职业选手
AI 科技评论消息:当地时间 1 月 30 日,在宾夕法尼亚州匹兹堡的 Rivers 赌场,卡耐基梅隆大学(CMU)开发的人工智能系统 Libratus 战胜四位德州扑克顶级选手,获得最终胜利。 据官网介绍,此次由四名人类职业玩家 Jason Les、Dong Kim、Daniel McAulay 和 Jimmy Chou 对战人工智能程序 Libratus,赛程为 20 天,一共进行了 12 万手牌的比赛。 2015 年,CMU 曾组织了首场“大脑对抗人工智能”赛事。在当时的赛事中,代表 CMU 出战
AI科技评论
2018/03/09
6800
重磅 | 继 AlphaGo 又一突破:人工智能战胜德州扑克职业选手
Logistic regression 为什么用 sigmoid ?
假设我们有一个线性分类器: 我们要求得合适的 W ,使 0-1 loss 的期望值最小,即下面这个期望最小: 一对 x y 的 0-1 loss 为: 在数据集上的 0-1 loss 期望值为: 由
杨熹
2018/06/19
6310
logistic regression一点理解为什么用sigmoid函数?为什么要用交互熵做损失函数?
关于logistic regression一些常见问题,整理出来,方便大家应对各种坑爹的面试官。
sladesal
2018/08/27
1.1K0
logistic regression一点理解为什么用sigmoid函数?为什么要用交互熵做损失函数?
造出一艘logistic模型 | 【logistic从生产到使用】(上) | 数说 · 算法
前几天飞扬博士更新了一篇算法文章,关于softmax regression的,它是logistic模型的扩展,因此要是能有些logistic regression的底子就看起来非常容易,因此在发softmax regression之前,重新复习一下logistic模型。 一句话介绍: logistic regression,它用回归模型的形式来预测某种事物的可能性,并且使用优势(Odds)来考察“某事物发生的可能性大小”。 ---- 之前介绍过的几个算法,如KNN、决策树等(在微信公众号“数说工作室”中回
数说君
2018/03/28
1.3K0
造出一艘logistic模型 | 【logistic从生产到使用】(上) | 数说 · 算法
学界|德州扑克算法幕后研发者CMU博士Noam Brown专访:AI如何打败顶级人类牌手?
在上个月举行的单挑无限注德州扑克( heads-up no-limit hold’em)人机对战中,由卡耐基梅隆大学研发的AI程序Libratus以每100手14倍大盲(译者注:缩写为14bb/100,意为玩100手牌,平均能赢对手14倍大盲注)完胜世界级人类玩家团队,震惊所有在场人员。 比赛共打12万手,最后Libratus赢得了1,776,250个筹码,近90个买入。虽然人类玩家输惨了,但幸运的是他们并不需要真的自掏腰包把输掉的钱给赢家Libratus(虽然他们来参加这场对战也需缴纳费用)。 Lib
AI科技评论
2018/03/09
1.8K0
学界|德州扑克算法幕后研发者CMU博士Noam Brown专访:AI如何打败顶级人类牌手?
30天学习Python系列第11篇:函数内容练习题参考答案
答应关注着和打卡互动学习营的小伙伴的,对于上难度后的参考答案如约而来。注意 答案均是用的所学知识所给出的其中一种参考。并不是唯一或者最优,所以不必过于纠结。重要是学习知识点并在将来能得以熟练应用。
MegaQi
2023/10/21
6380
30天学习Python系列第11篇:函数内容练习题参考答案
文科生都能看懂的机器学习教程:梯度下降、线性回归、逻辑回归
把复杂的东西简单化,让非专业人士也能短时间内理解,并露出恍然大悟的表情,是一项非常厉害的技能。
新智元
2019/05/08
7310
文科生都能看懂的机器学习教程:梯度下降、线性回归、逻辑回归
人工智能已在赌场赢了100多万美元,德州扑克大战人类又要败了
今天是年三十儿啦,『量子位』祝大家新春快乐!在这亲友相聚的日子里,我们讲一个AI横扫赌场的故事,也挺适合你讲给他们听…… 报道 | 量子位 舒石 百万美元 年三十儿的黎明来临时,数字定格在106.5万
量子位
2018/01/30
9010
人工智能已在赌场赢了100多万美元,德州扑克大战人类又要败了
基于 mlr 包的逻辑回归算法介绍与实践(上)
本期介绍的是 《Machine Learning with R, tidyverse, and mlr》 一书的第四章——逻辑回归(logistic regression)。逻辑回归是基于概率分类的有监督学习算法,它依赖于直线方程,产生的模型非常容易解释和交流。在其最简单的形式中,逻辑回归被用来预测二分类问题,但算法的变体也可以处理多个类。
庄闪闪
2022/04/08
2.4K0
基于 mlr 包的逻辑回归算法介绍与实践(上)
PTA 1011 World Cup Betting (20 分)
With the 2010 FIFA World Cup running, football fans the world over were becoming increasingly excited as the best players from the best teams doing battles for the World Cup trophy in South Africa. Similarly, football betting fans were putting their money where their mouths were, by laying all manner of World Cup bets.
freesan44
2021/10/05
2560
PTA 1011 World Cup Betting (20 分)
Python编程小练
编写一个函数 filter_and_sum_odds,该函数接收一个整数列表 numbers,返回一个包含所有奇数的列表以及这些奇数的和。
软件架构师Michael
2025/03/18
480
推荐阅读
相关推荐
Python装饰器详解
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验