You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何基于自定义随机函数生成Pandas DataFrame用于蒙特卡洛模拟?

如何用Pandas从零创建遵循随机微分方程的蒙特卡洛模拟DataFrame?

完全可以做到!针对你需要的1000条股票价格模拟路径、100个时间步的需求,我们可以基于几何布朗运动(也就是Black-Scholes模型里的股票价格过程)来生成对应的Pandas DataFrame。下面我会一步步给你讲清楚实现思路和代码。

核心思路回顾

你提到的股票价格过程公式是几何布朗运动的离散形式,具体来说,每个时间步的价格更新公式是:

( S_t = S_{t-1} \times \exp\left( (r - q - 0.5\sigma^2)\Delta t + \sigma \sqrt{\Delta t} \times Z \right) )
其中:

  • ( S_{t-1} ) 是上一个时间步的价格
  • ( r ) 无风险利率,( q ) 股息率,( \sigma ) 波动率
  • ( \Delta t ) 单个时间步的时长(比如T=1年的话,100个时间步就是( \Delta t = 0.01 ))
  • ( Z ) 标准正态分布的随机数

我们需要让每行的第0列(初始时间步)都等于321,然后逐列计算后续的价格。

具体实现步骤

1. 导入必要的库

首先得导入Pandas和NumPy(用NumPy做向量运算比纯Pandas循环效率高太多,适合大规模模拟):

import pandas as pd
import numpy as np

2. 定义模拟参数

先把你需要的参数都明确好,示例值可以根据你的实际需求调整:

# 模拟基础参数
s0 = 321  # 初始股价
n_paths = 1000  # 模拟路径数(对应DataFrame行数)
n_steps = 100  # 时间步数(对应DataFrame列数)
T = 1  # 总时间周期(比如1年)
r = 0.05  # 无风险利率
q = 0.02  # 股息率
sigma = 0.2  # 波动率
dt = T / n_steps  # 单个时间步的时长

3. 生成随机数矩阵

生成所有需要的标准正态随机数,形状是(n_paths, n_steps-1)——因为初始价格已经确定,只需要从第1列到第99列(共99个时间步)的随机数:

# 生成标准正态分布的随机数矩阵
z = np.random.normal(0, 1, size=(n_paths, n_steps - 1))

4. 计算价格变化乘数

根据公式先算出每个时间步的价格乘数(也就是指数部分):

# 计算漂移项(固定部分)
drift = (r - q - 0.5 * sigma ** 2) * dt
# 计算扩散项(随机部分)
diffusion = sigma * np.sqrt(dt) * z
# 得到每个时间步的价格乘数
price_multipliers = np.exp(drift + diffusion)

5. 构建价格矩阵并转为DataFrame

初始化矩阵后,把初始价格放到第一列,再逐列计算后续价格:

# 初始化全零价格矩阵
price_matrix = np.zeros((n_paths, n_steps))
price_matrix[:, 0] = s0  # 第一列全部设为初始价格321

# 逐列计算后续价格:每一列 = 前一列 * 对应时间步的乘数
for t in range(1, n_steps):
    price_matrix[:, t] = price_matrix[:, t-1] * price_multipliers[:, t-1]

# 转为Pandas DataFrame
monte_carlo_df = pd.DataFrame(price_matrix)

6. 可选:美化DataFrame

如果需要给列加上时间步标签(比如t0, t1...t99),可以执行下面的代码:

monte_carlo_df.columns = [f"t{i}" for i in range(n_steps)]

为什么用NumPy而不是纯Pandas循环?

你的模拟规模是1000×100,用NumPy的向量运算比Pandas逐行/逐列循环快得多,尤其是后续需要扩大模拟规模(比如10000条路径)时,这种方法的效率优势会更明显。

验证结果

你可以查看前几行数据确认效果,初始价格都是321,后续价格符合随机波动趋势:

print(monte_carlo_df.head())

输出示例大概是这样:

t0         t1         t2         t3  ...        t96        t97        t98        t99
0  321.00000  322.45678  320.12345  323.98765  ...  351.23456  349.87654  352.12345  350.98765
1  321.00000  319.87654  318.12345  319.98765  ...  305.67890  307.12345  306.87654  308.23456
2  321.00000  323.12345  325.67890  324.98765  ...  362.34567  360.87654  363.12345  361.98765
3  321.00000  320.67890  322.12345  321.87654  ...  335.45678  337.12345  336.87654  338.23456
4  321.00000  321.98765  320.45678  322.67890  ...  342.34567  340.87654  343.12345  341.98765

这样就完全满足你的需求了——1000行模拟路径、100列时间步,每行初始值321,后续列严格遵循几何布朗运动的随机方程。


内容的提问来源于stack exchange,提问作者VISQL

火山引擎 最新活动