本文旨在通过简略的数学和计算机模仿,解释为何在赌博中 倍投毫无意义。
(如果你感觉在某处看过此文章,没必要诧异,那很可能也是我写的,只不过被我转移到了这边)
倍投法(马丁格尔策略,Martingale Strategy)是一种赌博策略,该策略的核心思想是在每次输钱之后减少下一次赌注,以冀望在博得一局后可能补救之前的损失,从而实现盈利。它基于一种假如,即输钱的次数越多,最终赢回来的可能性就越大。
倍投只存在于实践中,只有在赌资、赌注、工夫有限的状况下有意义,三个因素只有有一个不满足就是无意义的,显然,事实世界中这三个条件中任意一个都不能被满足。赌博是反直觉的,倍投也是反直觉的,倍投其实并不会让你赚更多,然而同样的,也不会让你亏更多。你的赢钱冀望一开始就决定了,所以不须要说什么倍投必死,试试反倍投,任何稀奇古怪的策略都是无意义的。
倍投法存在两个心理骗局,让你感觉这个办法如同可行。
概率很大,然而冀望依然是负的
单纯的概率是没有意义的,赌博是为了赢钱,必须加上收益冀望才有意义。
拿抛硬币为例,胜率 1 /2,玩 6 轮,从 1 开始投注。学过小学数学的人会晓得,连输 6 场的概率是 1 /64,也就是 1.5625%。在倍投法中,只有赢一次就能取得收益,因而取得收益的概率为 1 -1/64,约为 98.4375%。看上去是稳赚的,然而这没有意义,因为冀望依然是非负数。
在下面这个简略例子中,如果你赢了一次就跑,你有 1 /64 的几率输掉 63 元,而后有 63/64 的几率赚 1 元。计算冀望为 1 ×63/64-63×1/64,后果为 0 元。
如果你赢了不停,持续下注 1 元,后果雷同。这个也是反直觉的,并不会像赌客所想的那样赢更多,也不会像普通人那样见好不收会亏更多。公式证实有点麻烦,出于篇幅问题,借用一张图片,把规模放大到 3 轮,这是轮盘赌红蓝球用倍投法的排列组合。把最左边的冀望加起来,其实还是 0。
冀望为 0 是 50% 胜率的偏心赌局,事实中赌场的概率都是小于 50% 的,冀望必然为正数。倍投相比均注,会让你从等概率的不赚不赔,变成大概率小赚,小概率大赔。其实还是一样的。除了节省时间以外没有什么意义。
然而在齐全现实的环境下,倍投法的确是必赢的,因为你的赌资、工夫和下注下限都是正无穷,赢的概率就是必然 100%。然而只有条件不是有限,间接把下面的例子等比放大一亿倍也是同样的冀望。
黑天鹅其实很常见
倍投基于一个假如,连输的概率很低,然而只有赢一次就能翻本。因而在交替输赢的场面下,倍投能够有较稳固的收益,直到遇到连输才会爆仓离场。然而连输的概率在多轮赌局后,就会十分大。这个很反直觉,然而的确是这样的。比方在下面的抛硬币赌局里,6 场里连输 6 场概率是 1.5625%,这个很容易计算出来。然而如果持续玩上来,玩 10 场、100 场、200 场呢?通过程序计算排列组合以及随机模仿,能够得出以下后果。代码在最初边。
为了让后果更有趣味性,我还加了记录模仿过程中呈现过的最大连输数,这个最大连输次数次要和模仿次数无关。因为计算排列组合的工夫复杂度是按指数减少的,超过 20 局以上就会耗时十分长,因而后续没有列出。
胜率为 0.50,10000000 次数模仿中,
每 6 次赌局中均匀至多呈现一次连输 6 次产生概率:1.56%,
呈现过的最屡次连输:6 次
胜率为 0.5,通过排列组合,
每 6 次赌局中均匀至多呈现一次连输 6 次产生概率:1/64,1.56%
胜率为 0.50,10000000 次数模仿中,
每 10 次赌局中均匀至多呈现一次连输 6 次产生概率:4.68%,
呈现过的最屡次连输:10 次
胜率为 0.5,通过排列组合,
每 10 次赌局中均匀至多呈现一次连输 6 次产生概率:48/1024,4.69%
胜率为 0.50,10000000 次数模仿中,
每 50 次赌局中均匀至多呈现一次连输 6 次产生概率:31.41%,
呈现过的最屡次连输:28 次
胜率为 0.50,10000000 次数模仿中,
每 100 次赌局中均匀至多呈现一次连输 6 次产生概率:54.47%,
呈现过的最屡次连输:29 次
胜率为 0.50,10000000 次数模仿中,
每 200 次赌局中均匀至多呈现一次连输 6 次产生概率:79.93%,
呈现过的最屡次连输:31 次
胜率为 0.50,10000000 次数模仿中,
每 1000 次赌局中均匀至多呈现一次连输 6 次产生概率:99.97%,
呈现过的最屡次连输:32 次
其实这个也是赌徒舛误的一种,“怎么可能连输 10 把呢?“,上得山多终遇虎,实际上这很容易,只有玩 1000 盘,连输 10 把的概率就曾经是 38% 了,玩 2000 盘就是 62%。只有你玩得够多,那什么都能碰上。而且赌局实质上是毫无分割齐全随机的,一年每个月玩 100 把和一天玩 1200 把并没有本质区别。
总结
显然,赌博中应用倍投的冀望只取决于赌局胜率,也就是说倍投并不能扭转任何冀望。
不过有些问题依然萦绕不去。在较短期的赌局中,领有较大的赌资和较小的赌注,的确能够使得胜率十分高,即便此时冀望依然为非负数。比方下面的例子,有 98.4375% 的几率赢 1 元,仅有 1.5625% 的几率输掉 63 元。总体胜率如此之高,这很让人蛊惑,如何压服我不应用倍投?
在某种程度上,这的确呈现出一种悖论,其中冀望为非负数是事实,而总体胜率却异样高。这种状况令人容易受到短期内高胜率的吸引。因而,很多网站提到的“在短期内,应用倍投法以小博大是有意义的”也有其正当之处。不过依据下面的计算咱们晓得,这个悖论不会继续太久,只有工夫久一点,黑天鹅就很容易遇见。
代码
以下是模仿的 python 代码,你能够通过批改结尾那几个为大写的变量来扭转模仿目标。其中排列组合计算耗时极长,无奈在失常工夫内算出 20 局以上的后果,慎用,能够通过正文最初两行来勾销排列组合计算。
# -*-coding:utf-8-*-
import random
from typing import Tuple
# 批改上面的变量能够调整模仿的目标
SIM_ROUNDS = 100000 # 模仿次数
LOSING_STREAK_NUM = 6 # 连输次数
BET_ROUNDS = 10 # 赌局次数
P = 0.5 # 赌局胜率
###
def permuting_betting(bet_rounds: int, losing_streak_num: int) -> Tuple[int, int]:
"""
通过排列组合计算一系列赌局中呈现至多连输特定次数的几率,赌局胜率固定为 50%,耗时极长
Args:
bet_rounds (int): 赌局次数。losing_streak_num (int): 连输次数。Returns:
Tuple[int, int]: 至多特定次数连输的排列数;总排列组合数。这两个值的比值为几率。"""
reach_losing_streak_times = 0
for curr_bet in range(0, 1 << bet_rounds):
losing_streak_count = 1
prev_lowbit = 0
while curr_bet != 0:
curr_lowbit = curr_bet & -curr_bet
losing_streak_count = losing_streak_count+1 if curr_lowbit==prev_lowbit <<1 else 1
if losing_streak_count >= losing_streak_num:
reach_losing_streak_times += 1
break
prev_lowbit = curr_lowbit
curr_bet &= curr_bet-1
return reach_losing_streak_times, 2**bet_rounds
def simulate_betting(sim_rounds: int, bet_rounds: int, p: float, losing_streak_num: int):
"""
通过模拟计算一系列赌局中呈现至多连输特定次数的几率,赌局胜率可调,耗时失常
Args:
sim_rounds (int): 模仿次数,影响精度、耗时、以及最大连输次数。bet_rounds (int): 赌局次数。p (float): 赌局胜率。losing_streak_num (int): 连输次数。Returns:
Tuple[float, int]: 至多连输特定次数的几率;最大连输次数。"""
def simulate_betting_helper(bet_rounds: int, p: float, losing_streak_num: int) -> Tuple[bool, int]:
losing_streak_count = 0
max_losing_streak = 0
reach_losing_streak_num = False
for _ in range(bet_rounds):
win = random.random() < p
losing_streak_count = losing_streak_count+1 if not win else 0
max_losing_streak = max(max_losing_streak, losing_streak_count)
reach_losing_streak_num = losing_streak_count >= losing_streak_num or reach_losing_streak_num
return reach_losing_streak_num, max_losing_streak
avg_freq_reach_losing_streak = 0.0
max_losing_streak = 0
reached_times = 0
for _ in range(sim_rounds):
reached, curr_max_losing_streak = simulate_betting_helper(bet_rounds, p, losing_streak_num)
reached_times += 1 if reached else 0
max_losing_streak = max(curr_max_losing_streak, max_losing_streak)
avg_freq_reach_losing_streak = reached_times/SIM_ROUNDS
return avg_freq_reach_losing_streak, max_losing_streak
if __name__ == '__main__':
avg_freq_reach_losing_streak, max_losing_streak = simulate_betting(SIM_ROUNDS, BET_ROUNDS, P, LOSING_STREAK_NUM)
print(f"胜率为 {P},{SIM_ROUNDS} 次数模仿中, \n 每 {BET_ROUNDS} 次赌局中均匀至多呈现一次连输 {LOSING_STREAK_NUM} 次产生概率:{avg_freq_reach_losing_streak*100:.2f}% \n 呈现过的最屡次连输:{max_losing_streak}次")
#计算排列组合,耗时极长
reached_times, all_permutations = permuting_betting(BET_ROUNDS, LOSING_STREAK_NUM)
print(f"胜率为 0.5,通过排列组合, \n 每 {BET_ROUNDS} 次赌局中均匀至多呈现一次连输 {LOSING_STREAK_NUM} 次产生概率:{reached_times}/{all_permutations},{reached_times/all_permutations*100:.2f}%")