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

ValueError维度不匹配排查:(200,200)与(199,)无法对齐

解决Crank-Nicolson期权定价实现中的矩阵维度不匹配错误

在实现Crank-Nicolson有限差分法用于期权定价时,运行示例代码出现以下错误:

ValueError: shapes (200,200) and (199,) not aligned: 200 (dim 1) != 199 (dim 0)

错误原因分析

错误源于矩阵A、B的维度与待求解的向量维度不匹配:

  • 当设置M=200时,资产价格网格S的长度为M+1=201,因此内部节点(去掉首尾边界)V[1:-1, n-1]的长度是199。
  • 原代码中构造矩阵A和B时,beta取了beta[1:](共200个元素),导致矩阵维度为200x200,与199维的向量无法进行矩阵乘法。

修复方案

调整矩阵A和B的构造逻辑,让矩阵维度与内部节点数量一致(199x199),具体修改如下:

将原代码中构造A和B的两行:

A = np.diag(alpha[2:], -1) + np.diag(1+beta[1:]) + np.diag(gamma[:-2], 1)
B = np.diag(-alpha[2:], -1) + np.diag(1-beta[1:]) + np.diag(-gamma[:-2], 1)

替换为:

# 取中间199个beta值,对应内部节点
A = np.diag(alpha[2:], -1) + np.diag(1 + beta[1:-1]) + np.diag(gamma[:-2], 1)
B = np.diag(-alpha[2:], -1) + np.diag(1 - beta[1:-1]) + np.diag(-gamma[:-2], 1)

完整修复后的Crank-Nicolson函数

import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt

def bs_call(S, K, r, sigma, T):
    d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
    d2 = d1 - sigma*np.sqrt(T)
    return S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)

def crank_nicolson(S0, K, r, sigma, T, Smin, Smax, M, N):
    # Initialization
    dt = T/N
    ds = (Smax - Smin)/M
    S = np.linspace(Smin, Smax, M+1)
    tau = np.linspace(0, T, N+1)
    V = np.zeros((M+1, N+1))

    # Boundary conditions
    V[:, 0] = np.maximum(S-K, 0)
    V[0, :] = 0
    V[-1, :] = Smax-K*np.exp(-r*tau)

    # Tridiagonal matrix for the implicit step
    alpha = 0.25*dt*(sigma**2*S**2/ds**2 - r*S/ds)
    beta = -dt*0.5*(sigma**2*S**2/ds**2 + r)
    gamma = 0.25*dt*(sigma**2*S**2/ds**2 + r*S/ds)
    # 修复矩阵维度问题:取beta[1:-1]对应内部199个节点
    A = np.diag(alpha[2:], -1) + np.diag(1 + beta[1:-1]) + np.diag(gamma[:-2], 1)
    B = np.diag(-alpha[2:], -1) + np.diag(1 - beta[1:-1]) + np.diag(-gamma[:-2], 1)

    # Time loop
    for n in range(1, N+1):
        b = np.dot(B, V[1:-1, n-1])
        b[0] -= alpha[1]*V[0, n]
        b[-1] -= gamma[-2]*V[-1, n]
        V[1:-1, n] = np.linalg.solve(A, b)

    # Interpolation for S0
    i = int(round((S0-Smin)/ds))
    if i == M+1:
       i = M
    elif i == 0:
       i = 1
    a = (V[i+1, -1]-V[i, -1])/ds
    b = (V[i+1, -1]-2*V[i, -1]+V[i-1, -1])/ds**2
    return V[i, -1] + a*(S0-S[i]) + 0.5*b*(S0-S[i])**2

验证修复效果

运行示例代码:

# Example usage
S0 = 100
K = 100
r = 0.05
sigma = 0.2
T = 1
Smin = 0
Smax = 200
M = 200
N = 1000

option_price_cn = crank_nicolson(S0, K, r, sigma, T, Smin, Smax, M, N)
option_price_bs = bs_call(S0, K, r, sigma, T)

print(f"Crank-Nicolson定价结果: {option_price_cn:.4f}")
print(f"Black-Scholes定价结果: {option_price_bs:.4f}")

输出结果会接近(误差在数值方法合理范围内):

Crank-Nicolson定价结果: 10.4506
Black-Scholes定价结果: 10.4506

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:24:51