第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%胜率

重要提醒:在实盘交易中,千万别用同一个随机数种子做决策。我见过有人用固定种子做回测,结果策略表现特别好,实盘却一塌糊涂——因为市场不会按照你设定的"随机路径"走。随机数生成器只用于模拟和测试,不是用来预测的。

知识体系总览

下面这张图,是我对本章知识结构的梳理。你可以把它当作一个"地图"来用。

概率模型构建知识体系 概率模型构建 离散概率分布 连续概率分布 蒙特卡洛模拟 随机数生成器 二项分布 泊松分布 事件频率分析 正态分布 对数正态分布 t分布(厚尾) 价格路径模拟 策略回测 风险分析 伪随机数 种子设置 可复现性 核心:用概率描述不确定性,用模拟验证策略 离散 → 连续 → 模拟 → 应用

这张图把四个核心模块串起来了。从离散到连续,再到蒙特卡洛模拟,最后用随机数生成器落地。每个模块都不是孤立的,它们共同构成了概率模型的基础框架。

本章核心要点

  1. 离散分布处理可数事件,适合信号频率分析
  2. 连续分布处理连续变量,注意厚尾特征
  3. 蒙特卡洛模拟用大量随机试验逼近真实结果
  4. 随机数生成器要设置种子保证可复现

好了,概率模型这块就聊到这儿。记住一句话:模型是地图,不是 territory(领土)。再好的概率模型,也只是对真实市场的近似。保持敬畏,持续验证,这才是量化交易的正道。

专注资料整理