Python蒙特卡洛模拟

程序员咋不秃头 2025-04-15 02:14:20

蒙特卡洛模拟是一种基于随机数和概率分布的数值计算方法,广泛应用于金融、物理、工程等领域,用于解决复杂的概率问题。它通过多次随机实验,逼近问题的解或估计某些指标的值。在现代计算中,Python 提供了丰富的库和工具,可以高效地实现蒙特卡洛模拟。

蒙特卡洛模拟的基本原理

蒙特卡洛模拟的核心思想是通过随机抽样和大量实验,逼近真实结果。

其基本步骤包括:

构建数学模型:明确问题并将其表示为概率问题。生成随机样本:根据问题的概率分布,生成大量随机数据。模拟实验:对每个随机样本执行实验或计算。统计结果:通过实验结果估计目标值或概率。

蒙特卡洛模拟的精度取决于实验次数:实验次数越多,结果越接近真实值。

示例数据准备

在实际问题中,蒙特卡洛模拟可以用于估算 π 的值、金融风险评估、随机过程模拟等。以下通过估算 π 的值引入基本实现。

用蒙特卡洛模拟估算 π 的值

在一个单位正方形中,画一个内接圆。通过随机生成点计算落入圆内的点占总点数的比例,可以近似求得 π 值:

import random# 蒙特卡洛模拟估算 πdef estimate_pi(num_samples): inside_circle = 0 for _ in range(num_samples): x, y = random.uniform(0, 1), random.uniform(0, 1) if x**2 + y**2 <= 1: inside_circle += 1 return 4 * inside_circle / num_samples# 运行模拟num_samples = 100000pi_estimate = estimate_pi(num_samples)print(f"使用 {num_samples} 次模拟估算 π 的值为:{pi_estimate}")

运行结果示例:

使用 100000 次模拟估算 π 的值为:3.13872随机过程模拟

随机过程是蒙特卡洛模拟的重要应用场景,特别是在金融和物理领域。例如,股票价格的随机变化可以用布朗运动来建模。

假设初始股票价格为 ( S_0 ),每天的价格变化服从正态分布 ( \mathcal{N}(\mu, \sigma) )。通过模拟未来若干天的价格变化,可以预测价格的可能范围。

import numpy as npimport matplotlib.pyplot as plt# Simulate stock price using Brownian motiondef simulate_stock_price(S0, mu, sigma, days, num_simulations): dt = 1 # Time step of 1 day simulations = [] for _ in range(num_simulations): prices = [S0] for _ in range(days): change = np.random.normal(mu * dt, sigma * np.sqrt(dt)) prices.append(prices[-1] * np.exp(change)) simulations.append(prices) return np.array(simulations)# ParametersS0 = 100 # Initial pricemu = 0.05 # Daily return ratesigma = 0.2 # Daily volatilitydays = 252 # Simulate one yearnum_simulations = 100 # Number of simulations# Simulate and visualize the resultssimulated_prices = simulate_stock_price(S0, mu, sigma, days, num_simulations)for prices in simulated_prices: plt.plot(prices, alpha=0.5)plt.title("Stock Price Brownian Motion Simulation")plt.xlabel("Days")plt.ylabel("Price")plt.show()

输出结果:

此代码生成若干条可能的股票价格路径,反映价格的随机波动。

概率分布实现

蒙特卡洛模拟需要随机数的支持,而这些随机数通常遵循某种概率分布。

生成正态分布随机数

正态分布广泛应用于自然现象和金融建模。

import numpy as npimport matplotlib.pyplot as plt# 生成正态分布的随机数mean, std_dev = 0, 1 # 均值和标准差samples = np.random.normal(mean, std_dev, 1000)# 可视化分布plt.hist(samples, bins=30, density=True, alpha=0.6, color='g')plt.title("Normal Distribution Random Numbers")plt.show()

输出结果:

生成均匀分布随机数

均匀分布常用于简单的随机抽样。

import numpy as npimport matplotlib.pyplot as plt# 生成均匀分布的随机数samples = np.random.uniform(0, 1, 1000)# 可视化分布plt.hist(samples, bins=30, density=True, alpha=0.6, color='b')plt.title("Uniform Distribution Random Numbers") plt.show()

输出结果:

自定义分布

可以通过概率密度函数(PDF)或累积分布函数(CDF)生成自定义分布的随机数。

import numpy as npimport matplotlib.pyplot as plt# 自定义概率密度函数def custom_pdf(x): return 2 * x # 示例:线性分布# 生成自定义分布的随机数x = np.linspace(0, 1, 1000) # 定义区间 [0, 1] 上的点y = custom_pdf(x) # 计算概率密度值custom_samples = np.random.choice(x, size=1000, p=y/y.sum()) # 生成随机数# 可视化分布plt.hist(custom_samples, bins=30, density=True, alpha=0.6, color='r', label="Random Numbers Distribution")plt.plot(x, y/y.sum(), 'k-', linewidth=2, label="Theoretical Distribution") # 叠加理论分布曲线plt.title("Custom Distribution Random Numbers") # 英文标题plt.xlabel("Value")plt.ylabel("Density")plt.legend()plt.show()

输出结果:

实际应用场景

选址问题的模拟

假设一个公司计划在城市中选址,需要评估交通流量的随机变化对选址的影响,可以通过蒙特卡洛模拟实现。

import numpy as npimport matplotlib.pyplot as plt# 模拟交通流量和利润def simulate_traffic(num_samples, traffic_mean, traffic_std): traffic = np.random.normal(traffic_mean, traffic_std, num_samples) # 生成交通流量 profit = traffic * 100 - 5000 # 利润 = 客流量 * 收入 - 固定成本 return profit# 参数设置num_samples = 10000 # 样本数量traffic_mean, traffic_std = 100, 15 # 交通流量的均值和标准差# 生成利润数据profit_samples = simulate_traffic(num_samples, traffic_mean, traffic_std)# 可视化利润分布plt.hist(profit_samples, bins=30, alpha=0.6, color='purple', label="Profit Distribution")plt.axvline(x=0, color='red', linestyle='--', label="Break-even Point") # 标记盈亏平衡点plt.title("Profit Distribution for Location Selection Problem") # 英文标题plt.xlabel("Profit (RMB)")plt.ylabel("Frequency")plt.legend()plt.show()# 计算并输出风险概率risk_probability = (profit_samples < 0).mean()print(f"Probability of Loss: {risk_probability:.2%}") # 亏损概率# 计算并输出平均利润和利润标准差mean_profit = np.mean(profit_samples)std_profit = np.std(profit_samples)print(f"Mean Profit: {mean_profit:.2f} RMB")print(f"Standard Deviation of Profit: {std_profit:.2f} RMB")

输出结果:

Probability of Loss: 0.03%Mean Profit: 5012.18 RMBStandard Deviation of Profit: 1501.25 RMB

金融衍生品定价

蒙特卡洛模拟也广泛用于金融衍生品(如期权)的定价,通过模拟资产价格路径估计衍生品的期望价值。

import numpy as npimport matplotlib.pyplot as plt# 欧式看涨期权定价的蒙特卡洛模拟def monte_carlo_option_pricing(S0, K, T, r, sigma, num_simulations, num_steps): """ 使用蒙特卡洛模拟定价欧式看涨期权。 参数: S0: 初始资产价格 K: 行权价 T: 到期时间(年) r: 无风险利率 sigma: 资产波动率 num_simulations: 模拟路径数量 num_steps: 时间步数 返回: option_price: 期权价格 """ dt = T / num_steps # 时间步长 discount_factor = np.exp(-r * T) # 贴现因子 # 模拟资产价格路径 S = np.zeros((num_simulations, num_steps + 1)) S[:, 0] = S0 # 初始价格 for t in range(1, num_steps + 1): z = np.random.standard_normal(num_simulations) # 标准正态随机数 S[:, t] = S[:, t - 1] * np.exp((r - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * z) # 计算期权收益 payoff = np.maximum(S[:, -1] - K, 0) # 计算期权价格(贴现后的平均收益) option_price = discount_factor * np.mean(payoff) return option_price, S# 参数设置S0 = 100 # 初始资产价格K = 105 # 行权价T = 1 # 到期时间(年)r = 0.05 # 无风险利率sigma = 0.2 # 波动率num_simulations = 10000 # 模拟路径数量num_steps = 252 # 时间步数(假设交易日为252天)# 定价option_price, price_paths = monte_carlo_option_pricing(S0, K, T, r, sigma, num_simulations, num_steps)print(f"欧式看涨期权的蒙特卡洛估计价格为: {option_price:.2f}")# 可视化部分资产价格路径plt.figure(figsize=(10, 6))for i in range(10): # 仅绘制前10条路径 plt.plot(price_paths[i, :])plt.title("Simulated Asset Price Paths")plt.xlabel("Time Steps")plt.ylabel("Asset Price")plt.show()

输出结果:

欧式看涨期权的蒙特卡洛估计价格为: 8.18

总结

本文详细介绍了蒙特卡洛模拟的基本原理及其在 Python 中的实现,包括 π 的估算、随机过程模拟和概率分布生成等内容。此外,还展示了蒙特卡洛模拟在选址问题和金融建模中的实际应用。通过大量的随机实验和统计分析,蒙特卡洛方法可以有效解决复杂的概率问题,是现代计算中的重要工具。

0 阅读:0
程序员咋不秃头

程序员咋不秃头

感谢大家的关注