第2章:概率模型构建
概率模型,说白了就是给随机世界画个像。
交易市场里,价格涨跌、成交量变化,哪一样不是随机的?我做了这么多年量化,最大的体会就是:你永远无法预测下一秒的价格,但你可以描述它"大概会怎么走"。这就是概率模型干的事。
2.1 离散概率分布:交易中的"骰子"
先说说离散概率分布。这东西其实不复杂,就是结果只有有限个可能的情况。
举个例子,你抛一枚硬币,只有正面和反面两种结果。在交易里,离散分布最常见的场景就是事件计数。
核心概念:离散概率分布描述的是可数结果的概率。比如:
- 今天涨停的概率是5%
- 明天跌停的概率是3%
- 一周内触发止损的次数
我个人习惯用二项分布来模拟交易信号的成功率。比如你有一个策略,历史胜率是60%。那么接下来10次交易中,赢7次的概率是多少?
# 二项分布计算
from scipy.stats import binom
n = 10 # 交易次数
p = 0.6 # 胜率
k = 7 # 赢的次数
prob = binom.pmf(k, n, p)
print(f"10次交易赢7次的概率: {prob:.4f}")
# 输出: 0.2150
嗯,这里要注意:二项分布假设每次交易是独立的。但真实市场里,交易之间往往有相关性。我踩过这个坑——用独立假设去算仓位,结果连续亏损时心态崩了。
我的经验:离散分布适合用来做事件频率分析。比如统计某个技术形态出现后,次日上涨的概率。我曾经用这个做过一个简单的统计套利策略,效果还不错。
2.2 连续概率分布:市场的"温度计"
连续分布就更有意思了。它描述的是无限种可能的情况。
你想想看,股票价格从100元涨到101元,中间有多少种可能?无穷多种。这就是连续分布要处理的问题。
交易中最常用的连续分布,我首推正态分布和对数正态分布。
| 分布类型 | 适用场景 | 我的用法 |
|---|---|---|
| 正态分布 | 收益率分布(短期) | 计算VaR(风险价值) |
| 对数正态分布 | 价格分布 | 期权定价模型 |
| t分布 | 厚尾数据 | 极端行情分析 |
为什么收益率用正态分布?说白了,中心极限定理告诉我们:大量独立随机变量的和趋近于正态。但真实市场的收益率有"厚尾"特征——就是极端行情比正态分布预测的要多。我吃过这个亏,用正态分布算VaR,结果2015年股灾时直接爆仓预警。
# 连续分布示例:收益率分布拟合
import numpy as np
from scipy import stats
# 模拟收益率数据
returns = np.random.normal(0.001, 0.02, 1000)
# 拟合正态分布
mu, std = stats.norm.fit(returns)
print(f"拟合结果: 均值={mu:.4f}, 标准差={std:.4f}")
# 计算95%置信区间的VaR
var_95 = stats.norm.ppf(0.05, mu, std)
print(f"95% VaR: {var_95:.4f}")
避坑指南:我曾经用纯正态分布去建模高频交易数据,结果回测漂亮,实盘一塌糊涂。后来才发现,高频数据的分布根本不是正态的,而是有很强的自相关性和尖峰厚尾特征。所以,别迷信正态分布,多看看你的数据长什么样。
2.3 蒙特卡洛模拟入门
蒙特卡洛模拟,说白了就是用大量随机试验来逼近真实结果。名字听着高大上,其实就是"暴力枚举"的升级版。
我为什么喜欢蒙特卡洛?因为它能处理那些解析解搞不定的复杂问题。比如:
- 一个策略在多种市场环境下的表现
- 投资组合的尾部风险
- 期权策略的盈亏分布
来看个简单的例子:模拟一只股票未来30天的价格路径。
# 蒙特卡洛模拟:股票价格路径
import numpy as np
import matplotlib.pyplot as plt
def simulate_price(S0, mu, sigma, days, n_simulations):
"""
S0: 初始价格
mu: 年化收益率
sigma: 年化波动率
days: 模拟天数
n_simulations: 模拟次数
"""
dt = 1/252 # 每日时间步长
prices = np.zeros((days, n_simulations))
prices[0] = S0
for i in range(1, days):
# 几何布朗运动
drift = (mu - 0.5 * sigma**2) * dt
shock = sigma * np.sqrt(dt) * np.random.normal(0, 1, n_simulations)
prices[i] = prices[i-1] * np.exp(drift + shock)
return prices
# 模拟1000条路径
paths = simulate_price(100, 0.15, 0.3, 30, 1000)
print(f"30天后价格均值: {paths[-1].mean():.2f}")
print(f"30天后价格95%区间: [{np.percentile(paths[-1], 2.5):.2f}, {np.percentile(paths[-1], 97.5):.2f}]")
我的建议:蒙特卡洛模拟的精度取决于模拟次数。1000次够用,10000次更好,但超过10万次边际效益递减。我一般用5000次作为起点,然后根据结果稳定性调整。
2.4 随机数生成器在交易中的应用
随机数生成器,是所有概率模型的"发动机"。没有它,蒙特卡洛跑不起来,分布也模拟不了。
但这里有个坑:伪随机数。计算机生成的随机数其实不是真随机,而是通过算法算出来的。如果你用默认的随机数生成器做回测,可能会得到"伪相关"的结果。
我遇到过一个问题:用Python的random模块做蒙特卡洛模拟,结果每次跑出来的结果都一样——因为种子没设好。后来改用numpy.random,并设置不同的种子,才解决了这个问题。
# 随机数生成器的正确用法
import numpy as np
# 设置种子保证可复现
np.random.seed(42)
# 生成正态分布随机数
returns = np.random.normal(0, 0.02, 1000)
# 生成均匀分布随机数(用于模拟入场时机)
entry_times = np.random.uniform(0, 1, 100)
# 生成二项分布随机数(模拟交易胜负)
wins = np.random.binomial(1, 0.6, 100) # 60%胜率
重要提醒:在实盘交易中,千万别用同一个随机数种子做决策。我见过有人用固定种子做回测,结果策略表现特别好,实盘却一塌糊涂——因为市场不会按照你设定的"随机路径"走。随机数生成器只用于模拟和测试,不是用来预测的。
知识体系总览
下面这张图,是我对本章知识结构的梳理。你可以把它当作一个"地图"来用。
这张图把四个核心模块串起来了。从离散到连续,再到蒙特卡洛模拟,最后用随机数生成器落地。每个模块都不是孤立的,它们共同构成了概率模型的基础框架。
本章核心要点:
- 离散分布处理可数事件,适合信号频率分析
- 连续分布处理连续变量,注意厚尾特征
- 蒙特卡洛模拟用大量随机试验逼近真实结果
- 随机数生成器要设置种子保证可复现
好了,概率模型这块就聊到这儿。记住一句话:模型是地图,不是 territory(领土)。再好的概率模型,也只是对真实市场的近似。保持敬畏,持续验证,这才是量化交易的正道。