Unexpected simulation behaviour of Geometric Brownian Motion with SciML


I wanted to simulate a geometric Brownian Motion of the form

GBB(t)=\exp\left(\beta t+\delta B(t)\right),

where B(t) is just some standard Brownian Motion.
Or expressed as a SDE, I want to simulate the solution

dGBB(t)=\mu GBB(t)dt+\sigma GBB(t)dB(t)

with \mu=\beta+\frac{\delta^2}{2} and \sigma=\delta.
(The latter formulation as an SDE might be more consistent to the parameters in the SciML implementation of a Geometric Brownian Motion.)
However, I want to condition this on start and endpoint, so simulate a Geometric Brownian Bridge.

What I did at first was to simulate standard Brownian Bridges and apply the linear transform and exponential function to it, for example with the below code

using Plots
using DifferentialEquations
using Distributions
using Random

# package of SciML for Noise Processes including Brownian Bridges
using DiffEqNoiseProcess

# step size of the solver
dt = 0.01

# conditions for the Brownian bridges
t0 = 0.0
tend = 10.0
W0 = 0.0
Wend = 4.0

# parameters for the linear transformation
beta = 0.1
delta = 0.1

# first simulate a Brownian Bridge and apply linear transform and exponential by hand

function BB_to_GBB(beta, delta, BB)
    GBB = [exp(beta*(i-1)*dt+delta*BB.u[i]) for i in eachindex(BB.u)]    
    return GBB

SimpleBB = BrownianBridge(t0, tend, W0, Wend)
BBprob = NoiseProblem(SimpleBB, (t0, tend))

BBensemble_prob = EnsembleProblem(BBprob)
BBensemble_sol = solve(BBensemble_prob, trajectories = 1000, dt = dt)

TransBBmean = mean([BB_to_GBB(beta, delta, BBensemble_sol[i]) for i in eachindex(BBensemble_sol)]);
plot(t0:dt:tend+dt, TransBBmean)

This works nicely and the mean process looks as I would expect it, some kind of exponentially looking curve between beginning and endpoint.
Screenshot from 2024-01-16 15-56-19

I then found that the DiffEqNoiseProcess.jl package also has a function for directly simulating Brownian Bridges. So I tried this

GB0 = exp(beta*t0+delta*W0)
GBend = exp(beta*tend+delta*Wend)

# reformulate to get the parameters of the SDE expression
mu = beta+delta^2/2
GBB = GeometricBrownianBridge(mu, delta, t0, tend, GB0, GBend)
GBBprob = NoiseProblem(GBB, (t0, tend))

GBBensemble_prob = EnsembleProblem(GBBprob)
GBBensemble_sol = solve(GBBensemble_prob, trajectories = 1000, dt = dt)
GBBmean = mean([GBBensemble_sol[i].u for i in eachindex(GBBensemble_sol)]);

plt = plot(t0:dt:tend+dt, GBBmean)
plot!(plt, t0:dt:tend+dt, TransBBmean)

Screenshot from 2024-01-16 15-58-37

But as you can see from the plot, the mean is now just a linear interpolation between start and endpoint. For me this is what I would expect from a normal Brownian bridge but not the Geometric. Moreover, I would expect the two simulation approaches to be equivalent, so the plots should be the same.

Maybe someone can help me whether I got something wrong conceptually or in my implementation.
Unfortunately, there is no documentation for the GeometricBrownianBridge function, so maybe I am just using it wrong.

Would appreciate any help on this.


This looks to be a bug. Fix discussion in Unexpected simulation behaviour of `GeometricBrownianBridge` process. · Issue #186 · SciML/DiffEqNoiseProcess.jl · GitHub