You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中为布朗运动蒙特卡洛模拟加入自相关修正?

问题描述

本人是Python及论坛新手,若有理解偏差请见谅。现发现连续值间存在负一阶自相关,希望将其纳入布朗运动蒙特卡洛(BMMC)模拟,认为此举可缩小随时间变化的置信区间。以下为无自相关的模拟代码,参考了相关论文但未能复现结果,现提出两点疑问:

  1. 上述理解是否正确,该方法是否适用?若不适用,有哪些可纳入负一阶自相关的替代方案?
  2. 如何在现有代码中正确实现最优方法以复现论文类似结果?
# Data
data = pd.DataFrame([3.1, 4.2, 3.7, 5.1, 4.3, 6.6, 8.4, 8.1, 7.5, 11.6, 10.2, 13.2])

# Calculate the logarithmic, differenciated y of our data.
df = np.log(data).diff().dropna()

# Extract the last available value 
S0 = data.iloc[len(df)]


mu = df.mean()
var = df.var()
desvest = df.std()
n_simulations = 2000
time_units = np.arange(9)
conf_level = 0.8
z_score = NormalDist().inv_cdf((1 + conf_level) / 2.)


# Determine the drift (slope)
drift = mu - (0.5*var)

# Determine the epsilon
epsilon = norm.ppf(np.random.rand(len(time_units), n_simulations))

# Determine y
y =  drift.values + desvest.values * epsilon

# Prepare the series
y_interval_1 = np.zeros(len(time_units))
y_interval_2 = np.zeros(len(time_units))
expected_y = np.zeros(len(time_units))

# Compute the confidence interval logic
for t in range(1, len(time_units)):
    y_interval_1[t] = drift*(t-time_units[0]) + desvest *z_score*np.sqrt(t - time_units[0])
    y_interval_2[t] = drift*(t-time_units[0]) + desvest *(-1*z_score)*np.sqrt(t - time_units[0])

# Prepare the outcome series   
S = np.zeros_like(y)
S_interval_1 = np.zeros_like(y_interval_1)
S_interval_2 = np.zeros_like(y_interval_2)

# Set initial value(s) - last available value of inserted series, named S0
S_interval_1[0] = S0
S_interval_2[0] = S0
S[0] = S0
expected_y[0] = S0

# Simulate the individials trails by using a for loop
for t in range(1, len(time_units)):
    S[t] = S[t-1]*np.exp(y[t])
    S_interval_1[t] = S0*np.exp(y_interval_1[t])
    S_interval_2[t] = S0*np.exp(y_interval_2[t])
    expected_y[t] = expected_y[t-1]*np.exp(mu.values)
解答

1. 理解合理性与替代方案

理解正确性

你的核心逻辑是对的:负一阶自相关意味着相邻收益会反向抵消,长期来看收益的方差累积速度会慢于无自相关的情况,因此对应的置信区间会更窄。但标准几何布朗运动(GBM)假设收益独立同分布,无法直接纳入自相关结构,所以直接修改现有GBM代码无法实现你的需求。

替代方案

针对一阶负自相关的场景,推荐以下几种模型:

  • AR(1)模型(一阶自回归):直接对对数收益建模,捕捉一阶自相关关系,是最贴合你需求的轻量方案。
  • ARMA-GARCH模型:如果除了均值的自相关,波动率也存在聚类特征,可同时建模均值自相关和波动率异方差。
  • 带自相关扰动的随机游走:修改GBM的扰动项,让其服从AR(1)过程,保留GBM的框架但加入自相关约束。

2. 代码实现(基于AR(1)模型的最优方案)

我们选择AR(1)模型来修改现有代码,步骤分为:估计AR(1)参数、生成带自相关的模拟收益、重新计算置信区间。

修改后的完整代码

import pandas as pd
import numpy as np
from scipy.stats import norm, NormalDist
from statsmodels.tsa.arima.model import ARIMA

# 1. 数据预处理
data = pd.DataFrame([3.1, 4.2, 3.7, 5.1, 4.3, 6.6, 8.4, 8.1, 7.5, 11.6, 10.2, 13.2])
log_returns = np.log(data).diff().dropna().values.flatten()  # 转为一维数组方便建模
S0 = data.iloc[-1].values[0]  # 取最后一个观测值

# 2. 估计AR(1)模型参数
ar1_model = ARIMA(log_returns, order=(1, 0, 0)).fit()
mu_ar1 = ar1_model.params[0]  # 均值项
rho_ar1 = ar1_model.params[1]  # 一阶自相关系数
resid_var = ar1_model.resid.var()  # 残差方差
resid_std = np.sqrt(resid_var)

# 3. 模拟参数设置
n_simulations = 2000
time_units = np.arange(9)
conf_level = 0.8
z_score = NormalDist().inv_cdf((1 + conf_level) / 2.)

# 4. 生成带自相关的模拟收益序列
# 初始化收益矩阵,每行对应一个时间步,每列对应一个模拟路径
sim_returns = np.zeros((len(time_units), n_simulations))
# 第一个时间步的收益:从AR(1)的平稳分布生成
sim_returns[0] = np.random.normal(loc=mu_ar1 / (1 - rho_ar1), scale=resid_std / np.sqrt(1 - rho_ar1**2), size=n_simulations)
# 后续时间步按照AR(1)生成:r_t = mu + rho*(r_{t-1} - mu) + eta_t
for t in range(1, len(time_units)):
    sim_returns[t] = mu_ar1 + rho_ar1 * (sim_returns[t-1] - mu_ar1) + np.random.normal(loc=0, scale=resid_std, size=n_simulations)

# 5. 模拟价格路径
S = np.zeros_like(sim_returns)
S[0] = S0
for t in range(1, len(time_units)):
    S[t] = S[t-1] * np.exp(sim_returns[t])

# 6. 计算带自相关的置信区间
# 长期方差计算公式:Var(r_1+...+r_T) = T*sigma_eta²/(1-rho²) + 2*rho*sigma_eta²/(1-rho²)*(T - (1-rho^T)/(1-rho))
expected_log_price = np.log(S0) + mu_ar1 / (1 - rho_ar1) * time_units
var_total = np.zeros(len(time_units))
for t in range(len(time_units)):
    if t == 0:
        var_total[t] = 0
    else:
        T = t
        term1 = T * resid_var / (1 - rho_ar1**2)
        term2 = 2 * rho_ar1 * resid_var / (1 - rho_ar1**2) * (T - (1 - rho_ar1**T)/(1 - rho_ar1))
        var_total[t] = term1 + term2
std_total = np.sqrt(var_total)

S_interval_1 = np.exp(expected_log_price + z_score * std_total)
S_interval_2 = np.exp(expected_log_price - z_score * std_total)
expected_y = np.exp(expected_log_price)

关键修改说明

  • AR(1)参数估计:用statsmodels的ARIMA模型(order=(1,0,0)即AR(1))估计均值、自相关系数和残差方差。
  • 收益生成逻辑:不再生成独立正态扰动,而是按照AR(1)的递推公式生成带负自相关的收益序列。
  • 置信区间计算:考虑自相关后的方差累积公式,替代原GBM的简单t*sigma²,确保置信区间能正确反映负自相关带来的方差缩减。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:52:13