Skip to content

Commit

Permalink
Merge pull request #192 from SciML/GBB
Browse files Browse the repository at this point in the history
Geometric brownian bridge fix
  • Loading branch information
ChrisRackauckas authored Feb 8, 2024
2 parents d330a47 + 9923160 commit 27bf364
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
15 changes: 12 additions & 3 deletions src/geometric_bm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,23 @@ https://math.stackexchange.com/questions/412470/conditional-distribution-in-brow
=#
function gbm_bridge(dW, gbm, W, W0, Wh, q, h, u, p, t, rng)
if dW isa AbstractArray
return gbm.σ * sqrt((1 - q) * q * abs(h)) * wiener_randn(rng, dW) + q * Wh
gbb_mean = @.. log(W0) + q * (log(W0 + Wh) - log(W0))
gbb_std = sqrt((1 - q) * q * abs(h)) * gbm.σ

x = gbb_mean + gbb_std * wiener_randn(rng, dW)
return exp.(x) - W0
else
return gbm.σ * sqrt((1 - q) * q * abs(h)) * wiener_randn(rng, typeof(dW)) + q * Wh
gbb_mean = log(W0) + q * (log(W0+Wh) - log(W0))
gbb_std = sqrt((1 - q) * q * abs(h)) * gbm.σ

x = gbb_mean + gbb_std * wiener_randn(rng, typeof(dW))
return exp(x) - W0
end
end
function gbm_bridge!(rand_vec, gbm, W, W0, Wh, q, h, u, p, t, rng)
wiener_randn!(rng, rand_vec)
@.. rand_vec = gbm.σ * sqrt((1 - q) * q * abs(h)) * rand_vec + q * Wh
@.. rand_vec = gbm.σ * sqrt((1 - q) * q * abs(h)) * rand_vec + (log(W0) + q * (log(W0 + Wh) - log(W0)))
@.. rand_vec = exp(rand_vec) - W0
end

@doc doc"""
Expand Down
27 changes: 22 additions & 5 deletions test/bridge_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,29 @@
@test (timestep_mean(sol, 11)[1], 1.0, atol = 1e-16)
@test (timestep_meanvar(sol, 11)[2], 0.0, atol = 1e-16)

μ = 1.2
σ = 2.2
W = GeometricBrownianBridge(μ, σ, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0)
prob = NoiseProblem(W, (0.0, 1.0))
μ = 0.10500000000000001
σ = 0.1
t0 = 0.0
tend = 10.0
GB0 = 1.0
GBend = 4.0

W = GeometricBrownianBridge(μ, σ, t0, tend, GB0, GBend)
prob = NoiseProblem(W, (t0, tend))
ensemble_prob = EnsembleProblem(prob)
@time sol = solve(ensemble_prob, dt = 0.1, trajectories = 100)
@time sol = solve(ensemble_prob, dt=1.0, trajectories=100000)
ts = t0:1.0:tend
for i = 2:10
t = ts[i]
mean = log(GB0) + (t - t0) / (tend - t0) * (log(GBend) - log(GB0))
var = (t - t0) / (tend - t0) * (tend - t) * σ^2

m, v = timestep_meanvar(sol, i)

@test (m, exp(mean + var / 2), atol=1e-2)
@test (v, (exp(var) - 1) * exp(2 * mean + var), atol=1e-2)
end


Random.seed!(100)
r = 100 # should be independent of the rate, so make it crazy
Expand Down

0 comments on commit 27bf364

Please sign in to comment.