diff --git a/docs/src/payoffs/payoffs.md b/docs/src/payoffs/payoffs.md index a6834ea1..fb66822c 100644 --- a/docs/src/payoffs/payoffs.md +++ b/docs/src/payoffs/payoffs.md @@ -263,5 +263,5 @@ DiffFusion.string ``` ```@docs -DiffFusion.calibrate_regression! +DiffFusion.calibrate_regression ``` diff --git a/src/chainrules/payoffs.jl b/src/chainrules/payoffs.jl new file mode 100644 index 00000000..da24453e --- /dev/null +++ b/src/chainrules/payoffs.jl @@ -0,0 +1,26 @@ + +# do not differentiate AMC regression setting + +ChainRulesCore.@non_differentiable reset_regression!( + p::AmcPayoff, + path::Union{AbstractPath, Nothing}, + make_regression::Union{Function, Nothing}, +) + +ChainRulesCore.@non_differentiable reset_regression!( + p::UnaryNode, + path::Union{AbstractPath, Nothing}, + make_regression::Union{Function, Nothing}, +) + +ChainRulesCore.@non_differentiable reset_regression!( + p::BinaryNode, + path::Union{AbstractPath, Nothing}, + make_regression::Union{Function, Nothing}, +) + +ChainRulesCore.@non_differentiable reset_regression!( + p::Union{Leaf, CompoundedRate, Optionlet, Swaption}, + path::Union{AbstractPath, Nothing}, + make_regression::Union{Function, Nothing}, +) diff --git a/src/payoffs/AmcPayoffs.jl b/src/payoffs/AmcPayoffs.jl index 2d22ff23..9de72ae3 100644 --- a/src/payoffs/AmcPayoffs.jl +++ b/src/payoffs/AmcPayoffs.jl @@ -76,11 +76,11 @@ end """ - calibrate_regression!(links::AmcPayoffLinks, regr::AmcPayoffRegression) + calibrate_regression(links::AmcPayoffLinks, regr::AmcPayoffRegression) Calibrate the regression for an AMC payoff. """ -function calibrate_regression!(links::AmcPayoffLinks, regr::AmcPayoffRegression) +function calibrate_regression(links::AmcPayoffLinks, regr::AmcPayoffRegression) if length(links.z) > 0 && !isnothing(regr.path) && !isnothing(regr.make_regression) T = zeros(length(regr.path)) for x in links.x @@ -92,10 +92,9 @@ function calibrate_regression!(links::AmcPayoffLinks, regr::AmcPayoffRegression) T = T .* numeraire(regr.path, links.obs_time, links.curve_key) Z = hcat([ z(regr.path) for z in links.z ]...)' # - regr.regression = regr.make_regression(Z, T) - return true + return regr.make_regression(Z, T) end - return false # cannot do calibration + return nothing # cannot calibrate end """ @@ -105,7 +104,7 @@ Calculate the common components of AMC payoffs for a given valuation path. """ function at(links::AmcPayoffLinks, regr::AmcPayoffRegression, path::AbstractPath) if isnothing(regr.regression) # try to calibrate - calibrate_regression!(links, regr) + regr.regression = calibrate_regression(links, regr) end if length(links.z) > 0 && !isnothing(regr.regression) # use regression to calculate payoff diff --git a/test/unittests/payoffs/amc_payoffs.jl b/test/unittests/payoffs/amc_payoffs.jl index 3d444619..d0c14b8d 100644 --- a/test/unittests/payoffs/amc_payoffs.jl +++ b/test/unittests/payoffs/amc_payoffs.jl @@ -51,10 +51,10 @@ using Test p3 = DiffFusion.AmcOne(5.0, x, y, z, path, make_regression, "Std") p4 = DiffFusion.AmcSum(5.0, x, z, path, make_regression, "Std") # - @test DiffFusion.calibrate_regression!(p1.links, p1.regr) == true - @test DiffFusion.calibrate_regression!(p2.links, p2.regr) == true - @test DiffFusion.calibrate_regression!(p3.links, p3.regr) == true - @test DiffFusion.calibrate_regression!(p4.links, p4.regr) == true + @test !isnothing(DiffFusion.calibrate_regression(p1.links, p1.regr)) + @test !isnothing(DiffFusion.calibrate_regression(p2.links, p2.regr)) + @test !isnothing(DiffFusion.calibrate_regression(p3.links, p3.regr)) + @test !isnothing(DiffFusion.calibrate_regression(p4.links, p4.regr)) # DiffFusion.reset_regression!(p1, path, make_regression) DiffFusion.reset_regression!(p2, path, make_regression)