案例:数值模拟-du tu问题
1:背景介绍
一个du tu进入du chang持续du bo,如果:
du chang:
赔率2:1
猜大小,胜率50%
du tu:
本金100元
每局下注1元
最终结果会如何?使用数值模拟实验得出结论
赚的盆满钵满
赔的底儿掉
不赚不赔,还是100块左右
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn')
plt.rcParams['font.family'] = ['Arial Unicode MS', 'Microsoft Yahei', 'SimHei', 'sans-serif']
2:数据情况
c = 1000000 # du bo次数
price = 100 # du资
生成du changdu bo开局大小数据
game = np.random.randint(0, 2, c)
game[:30], game.shape
(array([0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1,
1, 1, 0, 0, 1, 1, 1, 1]), (1000000,))
生成du tu下注方向数据
bet = np.random.randint(0, 2, c)
bet[:30], bet.shape
(array([1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 0, 1, 1]), (1000000,))
# 生成1000000个0
bet0 = np.zeros(c).astype(np.int)
bet0[:30], bet0.shape
(array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0]), (1000000,))
判断每局胜负
pl = game == bet0 # 全猜0
pl[:30]
array([ True, False, True, False, True, False, False, True, True,
True, True, False, True, False, True, True, False, True,
False, False, True, False, False, False, True, True, False,
False, False, False])
赢了多少把
np.sum(pl)
499712
pl = game == bet # 瞎猜
pl[:30]
np.sum(pl)
499571
全部押大,或全部押小,或乱下大小,结果胜率都是50%,没有区别
3:描述分析
每次下注的盈亏历史记录(本金变化历史)
# 每笔下注盈亏
pl[:30]
array([False, False, True, False, True, True, True, False, False,
False, False, True, False, False, True, True, True, True,
False, True, False, True, True, True, False, False, True,
False, True, True])
# 将盈亏 true false 转为 1 -1
pl2 = np.where(pl, 1, -1)
pl2[:30]
array([-1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1,
1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1])
理论上赚了多少钱
np.sum(pl2)
-858
每次下注后的盈亏累计(本金波动的历史)
plCum = np.cumsum(pl2)
plCum[:30]
array([-1, -2, -1, -2, -1, 0, 1, 0, -1, -2, -3, -2, -3, -4, -3, -2, -1,
0, -1, 0, -1, 0, 1, 2, 1, 0, 1, 0, 1, 2], dtype=int32)
理论最大盈利,理论最大亏损
np.max(plCum), np.min(plCum)
(104, -1593)
理论du本变化趋势图
plt.figure(figsize=(18, 10))
plt.plot(plCum + 100) # 加上本金
plt.yticks(np.arange(np.min((plCum + 100)), np.max((plCum + 100)), 50))
plt.show()
output_27_0.png
理论上下注一百万次,实际上在第一次本金为0时du tu已经被踢出场外
进一步尝试:
抽取用户本金第一次为0的索引,本索引之前的下注盈亏才是真正的盈亏
循环执行多次
# du本赔光为True
(plCum + 100) < 0
array([False, False, False, ..., True, True, True])
需要返回du本赔光的第一个值的索引(第一个True值的索引)
# 获取最大值索引
aaa = np.array([False,False,False,False,False,True,False,True,False])
np.argmax(aaa)
5
# 值为0说明没有最大值
aaa = np.array([False,False,False,False,False,False,False,False,False])
np.argmax(aaa)
0
du本第一次赔光的索引值
# du本赔光为True
pl3 = (plCum + 100) < 0
bc = np.argmax(pl3)
bc
25536
实际开局可视化
plt.figure(figsize=(18, 10))
plt.plot((plCum + 100)[:bc]) # 加上本金,只绘制第一次du bo为0前的历史
plt.yticks(np.arange(np.min((plCum + 100)[:bc]), np.max((plCum + 100)[:bc]), 10))
plt.show()
output_36_0.png
实际最大本金,和最小本金
np.max((plCum+100)[:bc]), np.min((plCum+100)[:bc])
(150, 0)
循环执行50次并可视化
price = 100
c = 10000000
plt.figure(figsize=(18,26))
for i in range(50):
# du chang生成开盘数据
game = np.random.randint(0, 2, c)
# du tu生成下注数据
bet = np.random.randint(0, 2, c)
# 得出胜负数组
pl = game == bet
# 将true false 替换为 1 -1
pl2 = np.where(pl == True, 1, -1)
# 累加,算出本金变化
plCum = np.cumsum(pl2)
# 判断第一次本金低于0的索引
dy = np.argmax((plCum + price) < 0)
# 绘制50张图
plt.subplot(10, 5, i+1)
plt.plot((plCum + price)[:dy])
# 如果dy为0,说明没有赔光本金,不会绘图
if dy == 0:
dy = c
plt.title((plCum + price)[:dy][-1])
# 调整子图间距
plt.subplots_adjust(
hspace=0.5, # 行间距
# wspace=0, # 列间距
)
plt.show()
output_40_0.png
4:结论
完全公平的du bo规则中:
单次du bo,盈亏是偶然的
赢钱是无限的,亏钱是有限的
du chang的du本比du tu大的多,
50%的胜率,仍然会导致du tu连赢或连输很多局
一个拥有有限du本的du tu,和拥有近似无限du本的du chang,持续du bo中,最终一定会输光
du性:贪婪,恐惧