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
相关产品推荐
相关产品推荐

