Hello to all
I am currently moving some code to Julia with the intention of improving performance. However, within a function I am running into a bottleneck when calculating the integral in one dimension of a complex function in the range [0, 1000].
This function is as follows
using HCubature
S₀ = 4000.0
K = 100.0
V₀ = 0.83500
r = 0.03
κ = 2.39271
θ = 0.01887
σ = 1.48821
λ = -0.38643
ρ = -0.97271
τ = 1.0
function price_algorithm(S₀::Float64, V₀::Float64, κ::Float64, θ::Float64,
σ::Float64, ρ::Float64, λ::Float64, K::Float64, τ::Float64, r::Float64)
a = κ * θ
b = κ + λ
function price_function(ϕ::T) where {T<:Number}
c = ρ * σ * ϕ * 1im
d = sqrt((c - b)^2 + (ϕ * 1im + ϕ^2) * σ^2)
g = (b - c + d) / (b - c - d)
part1 = exp(r * ϕ * 1im * τ)
part2 = S₀^(ϕ * 1im) * ((1 - g * exp(d * τ)) / (1 - g))^(-2 * a / σ^2)
part3 = exp(a * τ * (b - c + d) / σ^2 + V₀ * (b - c + d) * ((1 - exp(d * τ)) / (1 - g * exp(d * τ))) / σ^2)
return part1 * part2 * part3
end
function price_integral(ϕ::Float64)
num_integral = exp(r * τ) * price_function(ϕ - 1im) - K * price_function(ϕ)
dem_integral = 1im * ϕ * K^(1im * ϕ)
return num_integral / dem_integral
end
integral, _ = hquadrature(price_integral, 0, 1000)
return (S₀ - K * exp(-r * τ)) / 2 + real(integral) / π
end
The performance measured through @benchmark
is.
julia> using BenchmarkTools
julia> @benchmark price_algorithm($S₀, $V₀, $κ, $θ, $σ, $ρ, $λ, $K, $τ, $r)
BenchmarkTools.Trial: 110 samples with 1 evaluation.
Range (min … max): 39.698 ms … 90.912 ms ┊ GC (min … max): 0.00% … 0.00%
Time (median): 42.571 ms ┊ GC (median): 0.00%
Time (mean ± σ): 45.532 ms ± 7.154 ms ┊ GC (mean ± σ): 0.00% ± 0.00%
▄▁█ ▃
▇███▄█▃▅▅▃▃▃▄▆▄▃▄▄▆▁▄▄▄▅▁▄▄▁▄▁▃▁▄▃▁▃▁▁▁▁▄▁▃▁▁▁▁▁▁▁▃▁▁▁▁▁▃▁▄ ▃
39.7 ms Histogram: frequency by time 64.5 ms <
Memory estimate: 129.31 KiB, allocs estimate: 6.
Which seems to me to be extremely slow.
I would appreciate any recommendations on how to integrate this function in a more efficient way.
Note: Although I know the QuadGK
package and its function to integrate in one dimension quadgk
, this function gives a domain error for very small values close to zero (for example 1.424047472694446089e-303
).