用Python模拟布朗运动:从花粉实验到金融建模的保姆级代码实战

张开发
2026/4/15 15:21:22 15 分钟阅读

分享文章

用Python模拟布朗运动:从花粉实验到金融建模的保姆级代码实战
用Python模拟布朗运动从花粉实验到金融建模的保姆级代码实战布朗运动的发现源于1827年植物学家罗伯特·布朗的显微镜观察但它的数学魅力远不止于此。作为量化金融和随机过程建模的核心工具布朗运动或称维纳过程在资产定价、风险管理和物理模拟中扮演着关键角色。本文将带您用Python完整实现从基础布朗运动到金融应用的完整链路每个代码块都可直接复制到Jupyter Notebook中运行验证。1. 环境准备与基础概念在开始编码前我们需要明确几个关键特性布朗运动的路径连续但不可微、增量服从正态分布、具有马尔可夫性。这些性质使其成为模拟随机波动的理想工具。安装所需库若未安装pip install numpy matplotlib seaborn验证安装import numpy as np import matplotlib.pyplot as plt print(fNumPy版本: {np.__version__})2. 标准布朗运动模拟2.1 离散化模拟方法采用时间离散化方法将连续过程转化为离散步长。关键参数包括T: 总时间N: 时间步数dt: 时间步长(T/N)def brownian_motion(T1, N1000, seedNone): if seed is not None: np.random.seed(seed) dt T/N increments np.random.normal(0, np.sqrt(dt), sizeN) return np.cumsum(increments) # 生成5条路径对比 plt.figure(figsize(10,6)) for _ in range(5): path brownian_motion(T1, N1000) plt.plot(np.linspace(0,1,1000), path, alpha0.6) plt.title(标准布朗运动的多路径模拟) plt.xlabel(时间) plt.ylabel(值) plt.grid(True)注意np.sqrt(dt)确保了增量方差与时间步长成正比这是布朗运动的本质特征2.2 性质验证通过模拟验证三个核心性质增量正态性方差随时间线性增长增量独立性# 正态性检验 from scipy import stats paths [brownian_motion() for _ in range(5000)] increments [path[500] - path[400] for path in paths] # t0.4到0.5的增量 plt.hist(increments, bins30, densityTrue) x np.linspace(-0.1, 0.1, 100) plt.plot(x, stats.norm.pdf(x, 0, np.sqrt(0.1)), r-) plt.title(增量分布验证)3. 几何布朗运动与金融建模3.1 从物理到金融的转换几何布朗运动(GBM)描述资产价格变化 dSₜ μSₜdt σSₜdBₜ参数说明μ: 漂移率预期收益率σ: 波动率S₀: 初始价格def geometric_brownian(S0100, mu0.05, sigma0.2, T1, N252): t np.linspace(0, T, N) W brownian_motion(T, N-1) W np.insert(W, 0, 0) S S0 * np.exp((mu - 0.5*sigma**2)*t sigma*W) return t, S # 股票价格模拟示例 plt.figure(figsize(12,6)) for _ in range(5): t, S geometric_brownian() plt.plot(t, S) plt.title(几何布朗运动模拟股价路径) plt.xlabel(交易日期) plt.ylabel(价格) plt.grid(True)3.2 蒙特卡洛期权定价利用GBM模拟欧式看涨期权价格def european_call(S0100, K105, r0.05, sigma0.2, T1, simulations10000): payoff [] for _ in range(simulations): _, S geometric_brownian(S0, r, sigma, T) payoff.append(max(S[-1] - K, 0)) return np.exp(-r*T) * np.mean(payoff) # 与Black-Scholes公式对比 from scipy.stats import norm def bs_call(S0, K, T, r, sigma): d1 (np.log(S0/K) (r 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) d2 d1 - sigma*np.sqrt(T) return S0*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2) mc_price european_call() bs_price bs_call(100, 105, 1, 0.05, 0.2) print(f蒙特卡洛价格: {mc_price:.4f}) print(fBS公式价格: {bs_price:.4f})4. 高级应用与优化4.1 多维布朗运动模拟对于多资产组合需要生成相关布朗运动def correlated_brownian(rho, n_assets2, T1, N1000): dt T/N # 生成独立增量 increments np.random.normal(0, np.sqrt(dt), size(N, n_assets)) # Cholesky分解构造相关性 L np.linalg.cholesky([[1, rho], [rho, 1]]) correlated increments L.T return np.cumsum(correlated, axis0) # 绘制相关系数0.7的两资产路径 paths correlated_brownian(0.7) plt.plot(paths[:,0], label资产1) plt.plot(paths[:,1], label资产2) plt.legend()4.2 性能优化技巧对于大规模模拟可采用向量化操作def vectorized_gbm(S0100, mu0.05, sigma0.2, T1, N252, n_sim10000): dt T/N t np.linspace(0, T, N) # 一次性生成所有随机数 dW np.random.normal(0, np.sqrt(dt), size(n_sim, N-1)) W np.cumsum(dW, axis1) W np.insert(W, 0, 0, axis1) # 向量化计算 exponent (mu - 0.5*sigma**2)*t sigma*W return S0 * np.exp(exponent) # 万次模拟仅需0.5秒 %time paths vectorized_gbm(n_sim10000)5. 实际案例投资组合风险分析构建包含两只相关资产的组合每只资产服从GBM# 参数设置 S0 [100, 50] # 初始价格 mu [0.08, 0.12] # 预期收益 sigma [0.2, 0.3] # 波动率 rho 0.6 # 相关系数 weights np.array([0.6, 0.4]) # 组合权重 T 1 # 1年 N 252 # 交易日 n_sim 10000 # 模拟次数 # 生成相关路径 dt T/N t np.linspace(0, T, N) # 构造相关增量 cov np.array([[1, rho], [rho, 1]]) L np.linalg.cholesky(cov) dW np.random.normal(0, np.sqrt(dt), size(n_sim, N-1, 2)) corr_dW dW L.T W np.cumsum(corr_dW, axis1) W np.insert(W, 0, 0, axis1) # 计算资产价格 S np.zeros((n_sim, N, 2)) for i in range(2): exponent (mu[i] - 0.5*sigma[i]**2)*t sigma[i]*W[:,:,i] S[:,:,i] S0[i] * np.exp(exponent) # 计算组合价值 portfolio S weights # 分析结果 final_values portfolio[:,-1] mean_return np.mean(final_values)/np.sum(S0*weights) - 1 var_95 np.percentile(final_values, 5) print(f平均收益率: {mean_return*100:.2f}%) print(f5% VaR: {np.sum(S0*weights) - var_95:.2f})可视化风险分布plt.hist(final_values, bins50, densityTrue) plt.axvline(var_95, colorr, linestyle--) plt.title(投资组合终值分布) plt.xlabel(组合价值) plt.ylabel(密度)

更多文章