这是课程"做你自己的套利机器人"的辅助课。第 11 课提到订单有 10% 的概率失败,第 15 课说 z 分数大于 2 大约每 100 天出现 2 天。本页把这两个说法讲具体。
直接的办法:凭感觉
问一个人"订单失败的可能性有多大",他会说"挺可能"或"不太可能"。这没法写进程序,而且两个人对这些词的理解不同。解决办法是用 0 到 1 之间的一个数:0 表示从不,1 表示总是,0.1 表示 100 次里有 10 次。
概率是可以数出来的比例
不要空想,去数。把一枚虚拟硬币抛 1000 次,看它多少次正面朝上:
import random
random.seed(1)
flips = [random.random() < 0.5 for _ in range(1000)]
print(sum(flips) / 1000)
rolls = [random.randint(1, 6) for _ in range(60000)]
print([round(rolls.count(k) / 60000, 3) for k in range(1, 7)])
0.473
[0.167, 0.168, 0.165, 0.168, 0.168, 0.164]
硬币给出 0.473,不是正好 0.5:只抛 1000 次,有噪声。骰子掷了 60 000 次,每个面都接近 1/6 = 0.1667。试验越多,噪声越小。第 11 课的模拟就是这个思路:把交易运行 10 000 次,然后数一数。
本课程只需要两条规则:
- 所有可能结果的概率加起来等于 1。如果订单以 0.1 的概率失败,那么成功的概率是 0.9。
- 对两个相互独立的事件,概率相乘:两者都发生的概率是 a × b。两个订单,各自以 0.9 成功,两个都成功的概率是 0.81。
钟形曲线
许多量,比如人的身高或价格每天的小幅噪声,都会聚集在平均值附近,离得越远,数值越少。图形像一口钟,这种分布叫正态分布。两个数就能完整描述它:平均值(中心)和标准差(宽度),都在上一篇预备课里讲过。
有用的事实是:离中心若干个标准差之内,钟形曲线占多大比例:
from statistics import NormalDist
random.seed(1)
r = [random.gauss(0, 1) for _ in range(100000)]
for k in (1, 2, 3):
print(k, round(sum(abs(x) < k for x in r) / len(r), 4), round(2 * NormalDist().cdf(k) - 1, 4))
print(round(sum(x > 2 for x in r) / len(r), 4), round(1 - NormalDist().cdf(2), 4))
1 0.6804 0.6827
2 0.9538 0.9545
3 0.9973 0.9973
0.0228 0.0228
每一行里,第一个数是对 100 000 个随机值计数得到的,第二个数是公式给出的精确值。两者吻合。所以大约 68% 的值在平均值的 1 个标准差之内,约 95% 在 2 个之内,99.7% 在 3 个之内。最后一行说明,高出平均值 2 个以上的概率是 0.0228,大约 100 次里有 2 次。
第 15 课的 z 分数规则就是由此而来:z 大于 2 大约每 100 天出现 2 天(小于 −2 再有 2 天),所以这是值得看一眼的罕见事件。
钟形曲线在哪里会骗你
真实价格的极端波动比钟形曲线预测的多,而且世界可能改变,使旧的平均值不再成立。z 分数为 2 在图上很少见,但依赖它的策略仍然需要止损,并在没见过的数据上测试。第 15 课会演示这一点。
你的练习
- 运行代码,和课程对比。
- 手算:一个订单以 0.9 成功,一笔交易需要连续 3 个这样的订单。三个都成功的概率是多少?用 100 000 次模拟检查。
- 把
k改成 1.5 和 2.5,比较计数得到的比例和精确比例。 - 取上一篇预备课里的公交延误数据。以其余九天的平均值和标准差来算,那个晚点 30 分钟的日子在钟形曲线下算罕见吗?
下一步
现在第 11 课和第 15 课对你开放了。