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

Python蒙特卡洛障碍期权定价绘图报错:x与y维度不匹配

蒙特卡洛障碍期权绘图报错:ValueError: x and y维度不匹配

运行代码时出现错误:ValueError: x and y must have same first dimension, but have shapes (10,) and (5,),作为Python新手找不到问题所在,代码如下:

import numpy as np
import numpy.random as npr
import matplotlib.pyplot as plt

def mc_single_barrier_do(S0, K, T, H, r, vol, N, M):

    # Constants
    dt = T / N  # change in time
    nudt = (r - 0.5 * vol ** 2) * dt  # deterministic component
    volsdt = vol * np.sqrt(dt)  # diffusion coefficient
    erdt = np.exp(r * dt)  # discount factor

     # Standard Error Placeholders
    sum_CT = 0
    sum_CT2 = 0
     # Monte Carlo Method
    for i in range(M):

        # Barrier Crossed Flag
        BARRIER = False
        St = S0

        for j in range(N):
            epsilon = np.random.normal()
            Stn = St * np.exp(nudt + volsdt * epsilon)
            St = Stn
            Ptn = np.exp(-2. * (H - St) * (H - Stn) / (St ** 2. * volsdt ** 2.))
            Pt = Ptn
            if Pt >= npr.uniform():
                BARRIER = True
        if np.amin(St) > H and BARRIER == False:
            CT = np.maximum(St - K, 0)

        else:
            CT = 0.

        sum_CT = sum_CT + CT
        sum_CT2 = sum_CT2 + CT * CT

    C0_MC = np.exp(-r * T) * sum_CT / M
    return C0_MC


def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):

    assert (method in ['MC', 'AV', 'CV'])
    
    mean_payoffs = np.zeros(int(np.ceil(max_sample / 10)))
    
    if method == 'MC':
        for n_sample in range(10, max_sample + 1, 10):
            payoffs = mc_single_barrier_do(n_sample, S0, K, T, H, r, vol, N)
            mean_payoffs[int(n_sample / 10 - 1)] = np.mean(payoffs)
        
    return mean_payoffs

r = 0.1
vol = 0.2
T = 2
N = 20
dt = T / N
S0 = 50
K = 50
H = 45
max_sample = 100

MC_price_estimates = sim_iterator(S0, T, r, vol, K, H, max_sample, N, method='MC')
x_axis1 = range(10, max_sample + 1, 10)
plt.plot(x_axis1, MC_price_estimates)
plt.xlabel("No. of Simulations")
plt.ylabel("Estimated option price")
plt.title("Ordinary Monte Carlo Method")
plt.legend()
plt.show()

问题分析与修复

1. 函数参数顺序完全错位

这是维度不匹配的核心原因:

  • mc_single_barrier_do定义的参数顺序是(S0, K, T, H, r, vol, N, M),但调用时把模拟次数n_sample(对应参数M)放到了第一个位置,参数全部错位,导致返回结果异常。
    修复: 正确调用应为mc_single_barrier_do(S0, K, T, H, r, vol, N, n_sample)
  • sim_iterator的定义参数顺序是(max_sample, N, S0, T, r, vol, K, H, method),但调用时参数顺序完全混乱,导致max_sample传入的是S0=50,生成的mean_payoffs数组长度为5,而x_axis1是10到100共10个元素,自然维度不匹配。
    修复: 正确调用应为sim_iterator(max_sample, N, S0, T, r, vol, K, H, method='MC')

2. 多余的np.mean()调用

mc_single_barrier_do已经返回该模拟次数下的平均期权价格,不需要再用np.mean()处理,直接赋值即可:

mean_payoffs[int(n_sample / 10 - 1)] = payoffs

3. np.amin(St)逻辑错误

St是单个价格值,不是数组,np.amin()在这里毫无意义,应该记录整个价格路径,再取路径最小值判断是否触碰障碍:

# 替换原循环中的St变量为路径数组
path = [S0]
for j in range(N):
    epsilon = np.random.normal()
    Stn = path[-1] * np.exp(nudt + volsdt * epsilon)
    path.append(Stn)
    # ... 其他逻辑
# 检查路径最小值
if np.min(path) > H and BARRIER == False:

修复后的完整代码

import numpy as np
import numpy.random as npr
import matplotlib.pyplot as plt

def mc_single_barrier_do(S0, K, T, H, r, vol, N, M):
    # Constants
    dt = T / N  # 时间步长
    nudt = (r - 0.5 * vol ** 2) * dt  # 确定性漂移项
    volsdt = vol * np.sqrt(dt)  # 扩散项系数

    # 用于计算均值和方差的累加变量
    sum_CT = 0
    sum_CT2 = 0

    # 蒙特卡洛主循环
    for i in range(M):
        BARRIER = False
        path = [S0]  # 存储整个价格路径

        for j in range(N):
            epsilon = np.random.normal()
            Stn = path[-1] * np.exp(nudt + volsdt * epsilon)
            path.append(Stn)
            # 计算障碍触发概率(原逻辑保留)
            Ptn = np.exp(-2. * (H - path[-2]) * (H - path[-1]) / (path[-2] ** 2. * volsdt ** 2.))
            if Ptn >= npr.uniform():
                BARRIER = True

        # 判断是否获得行权价值
        if np.min(path) > H and not BARRIER:
            CT = np.maximum(path[-1] - K, 0)
        else:
            CT = 0.

        sum_CT += CT
        sum_CT2 += CT * CT

    # 折现后的期权价格
    C0_MC = np.exp(-r * T) * sum_CT / M
    return C0_MC


def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
    assert (method in ['MC', 'AV', 'CV'])
    
    # 计算数组长度:从10到max_sample,步长10,共max_sample//10个元素
    mean_payoffs = np.zeros(max_sample // 10)
    
    if method == 'MC':
        idx = 0
        for n_sample in range(10, max_sample + 1, 10):
            payoffs = mc_single_barrier_do(S0, K, T, H, r, vol, N, n_sample)
            mean_payoffs[idx] = payoffs
            idx += 1
        
    return mean_payoffs

# 参数设置
r = 0.1
vol = 0.2
T = 2
N = 20
S0 = 50
K = 50
H = 45
max_sample = 100

# 正确调用迭代函数
MC_price_estimates = sim_iterator(max_sample, N, S0, T, r, vol, K, H, method='MC')
x_axis1 = range(10, max_sample + 1, 10)

# 绘图
plt.plot(x_axis1, MC_price_estimates)
plt.xlabel("模拟次数")
plt.ylabel("估计期权价格")
plt.title("普通蒙特卡洛方法")
plt.legend(["蒙特卡洛估计"])
plt.show()

内容的提问来源于stack exchange,提问作者El. Nik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:25:33