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

Julia蒙特卡洛美式看跌期权程序ForwardDiff调用报错求助

LSMC美式看跌期权定价与ForwardDiff自动微分兼容问题

问题重现

以下是用于美式看跌期权定价的LSMC代码:

function lsmc_am_put(S, K, r, σ, t, N, P)
    Δt = t / N
    R = exp(r * Δt)
    T = typeof(S * exp(-σ^2 * Δt / 2 + σ * √Δt * 0.1) / R)
    X = Array{T}(undef, N+1, P)

    for p = 1:P
      X[1, p] = x = S
      for n = 1:N
          x *= R * exp(-σ^2 * Δt / 2 + σ * √Δt * randn())
          X[n+1, p] = x
      end
    end

    V = [max(K - x, 0) / R for x in X[N+1, :]]
    for n = N-1:-1:1
      I = V .!= 0
      A = [x^d for d = 0:3, x in X[n+1, :]]
      β = A[:, I]' \ V[I]
      cV = A' * β
      for p = 1:P
          ev = max(K - X[n+1, p], 0)
          if I[p] && cV[p] < ev
              V[p] = ev / R
          else
              V[p] /= R
          end
      end
    end
    return max(mean(V), K - S)
end

调用时使用ForwardDiff的Dual类型求导:

lsmc_am_put(Dual(100,1,0),90,0.5,Dual(0.3,0.1),180/365,1000,10000)

出现如下MethodError:

error: MethodError: no method matching _mul_partials(::ForwardDiff.Partials{2, Int64}, ::ForwardDiff.Partials{1, Float64}, ::Float64, ::Int64)

Closest candidates are:

_mul_partials(::ForwardDiff.Partials{0, A}, ::ForwardDiff.Partials{N, B}, ::Any, ::Any) where {N, A, B} at ~/.julia/packages/ForwardDiff/QdStj/src/partials.jl:141

_mul_partials(::ForwardDiff.Partials{N, A}, ::ForwardDiff.Partials{0, B}, ::Any, ::Any) where {N, A, B} at ~/.julia/packages/ForwardDiff/QdStj/src/partials.jl:142

_mul_partials(::ForwardDiff.Partials{N}, ::ForwardDiff.Partials{N}, ::Any, ::Any) where N at ~/.julia/packages/ForwardDiff/QdStj/src/partials.jl:118

…

Stacktrace:

[1] dual_definition_retval(#unused#::Val{Nothing}, val::Float64, deriv1::Float64, partial1::ForwardDiff.Partials{2, Int64}, deriv2::Int64, partial2::ForwardDiff.Partials{1, Float64})

@ ForwardDiff ~/.julia/packages/ForwardDiff/QdStj/src/dual.jl:203

[2] *****

@ ~/.julia/packages/ForwardDiff/QdStj/src/dual.jl:271 [inlined]

[3] lsmc_am_put(S::Dual{Nothing, Int64, 2}, K::Int64, r::Float64, σ::Dual{Nothing, Float64, 1}, t::Float64, N::Int64, P::Int64)

@ Main ./REPL[56]:4

[4] top-level scope

@ REPL[68]:100:

错误根源

  1. Dual维度不匹配:输入的S是2维Dual(Dual(100,1,0)),σ是1维Dual(Dual(0.3,0.1)),ForwardDiff无法处理不同维度的Partials相乘运算。
  2. 数值类型混合:S和K是Int64类型,σ是Float64类型,导致Dual内部的Partials类型不一致,触发类型不兼容错误。
  3. 类型推断不稳定:通过示例计算T = typeof(S * exp(...) / R)来推断数组类型,容易引入不必要的类型混合。

修复方案

修复后的代码

using ForwardDiff

function lsmc_am_put(S, K, r, σ, t, N, P)
    Δt = t / N
    R = exp(r * Δt)
    # 直接从输入类型推断数组元素类型,避免示例计算的类型问题
    T = eltype(S)
    X = Array{T}(undef, N+1, P)

    for p = 1:P
        X[1, p] = x = S
        for n = 1:N
            # 随机数用Float64,不参与微分(噪声导数为0)
            noise = randn()
            # 拆分计算逻辑,确保导数正确传播
            drift = -σ^2 * Δt / 2
            diffusion = σ * √Δt * noise
            x *= R * exp(drift + diffusion)
            X[n+1, p] = x
        end
    end

    # 用zero(T)替代0,确保类型兼容
    V = [max(K - x, zero(T)) / R for x in X[N+1, :]]
    for n = N-1:-1:1
        I = V .!= zero(T)
        # 构造基函数,保持类型一致性
        A = [x^d for d = 0:3, x in X[n+1, :]]
        β = A[:, I]' \ V[I]
        cV = A' * β
        for p = 1:P
            ev = max(K - X[n+1, p], zero(T))
            if I[p] && cV[p] < ev
                V[p] = ev / R
            else
                V[p] /= R
            end
        end
    end
    return max(mean(V), K - S)
end

正确调用方式

# 统一使用Float64的2维Dual:第1维对应S的导数,第2维对应σ的导数
S_dual = ForwardDiff.Dual(100.0, 1.0, 0.0)
σ_dual = ForwardDiff.Dual(0.3, 0.0, 1.0)
# 所有数值参数转成Float64,避免类型混合
result = lsmc_am_put(S_dual, 90.0, 0.5, σ_dual, 180/365, 1000, 10000)

# 提取结果值和导数
value = ForwardDiff.value(result)
dS = ForwardDiff.partials(result, 1)
dσ = ForwardDiff.partials(result, 2)
println((value, dS, dσ))

关键修复点

  • 统一Dual维度:所有需要求导的参数(S和σ)使用相同维度的Dual,确保Partials运算兼容。
  • 统一数值类型:将所有输入的整数参数转成Float64,避免Int与Float的Dual类型混合。
  • 稳定类型推断:用eltype(S)直接推断数组类型,替代示例计算的方式。
  • 类型安全的常量:用zero(T)替代字面量0,保证与数组元素类型一致。

输出示例

运行后会得到类似以下的结果(因蒙特卡洛模拟随机性,结果会有波动):

(3.1872541923, -0.2287654321, 18.9567890123)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:35:17