Simulating stock prices using GBM

@ph1l, for geometric_brownian_motion(.). do you happen to know what the param T expects?
Let's say I need to generate monthly prices for 1 year, ie. 12 per year, then I guess N has to be 12. But what value to pass for T ? Is it 1.0 ?
Is there any test code by the author that demonstrates the usage of these functions?

Update: OK, figured it out: yes T is time in years, ie. in my case 1.0
 
Last edited:
And finally, he uses drifted Brownian motion to implement geometric Brownian motion
https://isquared.digital/blog/2020-05-17-geometric-brownian-motion/
Code:
import numpy as np
np.random.seed(1234)

def brownian_motion(N, T, h):
    """
    Simulates a Brownian motion
    :param int N : the number of discrete steps
    :param int T: the number of continuous time steps
    :param float h: the variance of the increments
    """
    dt = 1. * T/N  # the normalizing constant
    random_increments = np.random.normal(0.0, 1.0 * h, N)*np.sqrt(dt)  # the epsilon values
    brownian_motion = np.cumsum(random_increments)  # calculate the brownian motion
    brownian_motion = np.insert(brownian_motion, 0, 0.0) # insert the initial condition

    return brownian_motion, random_increments

def geometric_brownian_motion(G0, mu, sigma, N, T):
    """Simulates a Geometric Brownian Motion.

    :param float G0: initial value
    :param float mu: drift coefficient
    :param float sigma: diffusion coefficient
    :param int N: number of discrete steps
    :param int T: number of continuous time steps
    :return list: the geometric Brownian Motion
    """
    # the normalizing constant
    dt = 1. * T/N
    # standard brownian motion
    W, _ = brownian_motion(N, T ,1.0)
    # generate the time steps
    time_steps = np.linspace(0.0, N*dt, N+1)

    # calculate the geometric brownian motion
    G = G0 * np.exp(mu * time_steps + sigma * W)
    # replace the initial value
    G[0] = G0

    return G
@ph1l, this is one of the best GBM algorithms I have tested so far, but IMO still not a correct GBM.
Btw, there is a bug in the description in both (or all three) functions: param T is (or has to be) of type float, not int.
Another shortcoming in the algorithm is that it always generates the given initial price, G0, as the first output. This is unnecessary und better should be removed, IMO.
And a tip for programmers: this code uses (implicitly) vector programming... :), to speed it up, so it's not that easy to grasp the algorithm... :) Ie. it works by operating on vectors... A drawback of this approach is that the vectors can get really big, depending on N, and so the memory use.

And: I myself don't have the correct GBM algorithm yet; I just know it can't be correct b/c it does not pass some stochastic tests...
 
Last edited:
You asked the right question! :)

I came from a different angle to the conclusion that the GBM algorithm must be wrong.
Or the GBM implementations I so far have tested.
I'm almost 100% sure it's wrong, but the explanation (and proof) is not that easy... but I'll give the proof soon.

I could write a scientific paper and it would be a sensation and I would become famous like Black, Scholes, Merton, Bachelier, Einstein, Newton et al. :) ...but the crude reality is: I'm living in wrong times in a highly ignorant sicko SHC and society... :)

Imagine: all the GBM simulations out there in the World are wrong! Including in nuclear research... :),
And nobody but me knows it!... :)

Btw, I found this bug in GBM after this posting of mine in the other thread recently where we had a fruitful discussion, I must say.

Proof that GBM is wrong

GBM and lognormal with same parameters will be compared to each other.

1) lognormal ( https://en.wikipedia.org/wiki/Log-normal_distribution#Generation_and_parameters ) :
Code:
  St = S0 * exp(u     + s *           rndSND)      # for t=1
  St = S0 * exp(u * t + s * sqrt(t) * rndSND)      # for any t

  where rndSND is a random number from the standard normal distribution (ie. u=0 and s=1)
  In this case it can be seen as the "z" value, here using -1 and +1 for -1SD and +1SD

  Example: see #3 below

2) GBM ( https://en.wikipedia.org/wiki/Geometric_Brownian_motion#Solving_the_SDE ) :
Code:
  St = S0 * exp((u - s * s / 2) * t + s * Wt)

  where Wt = sqrt(t) * rndSND, and
  where rndSND is a random number from the standard normal distribution (ie. u=0 and s=1)
  In this case it can be seen as the "z" value, here using -1 and +1 for -1SD and +1SD

  Example: see #3 below

3) Proof that GBM is wrong: below rndSND can be seen as the "z" value, here -1 and +1 for -1SD and +1SD :
Code:
"-1SD" :
S0=100 ; u=0.0; s=0.3 ; t=1 ; rndSND=-1.0 ; S0 * exp(u * t + s * sqrt(t) * rndSND) ; Wt = sqrt(t) * rndSND; S0 * exp((u - s * s / 2) * t + s * Wt)
74.08182206817179       # lognormal z=-1, ie. rndSND=-1, aka -1SD
70.82203534678          # GBM z=-1, ie. rndSND=-1, aka -1SD

"+1SD" :
S0=100 ; u=0.0; s=0.3 ; t=1 ; rndSND=+1.0 ; S0 * exp(u * t + s * sqrt(t) * rndSND) ; Wt = sqrt(t) * rndSND; S0 * exp((u - s * s / 2) * t + s * Wt)
134.9858807576003       # lognormal z=+1, ie. rndSND=+1, aka +1SD
129.046162087289        # GBM z=+1, ie. rndSND=+1, aka +1SD

4) Conclusion:
The values for -1SD and +1SD differ (74.08 vs. 70.82 and 134.98 vs. 129.04).
Since the values for lognormal are correct (74.08 and 134.98), then it follows that GBM is wrong. Q.E.D.

Reason is the use of Ito's lemma, ie. the term "- s^2/2" in the GBM equation.
This finding here could maybe have an impact also on BSM, where Ito's lemma gets used as well...

See also
https://en.wikipedia.org/wiki/Normal_distribution#Standard_normal_distribution
 
Last edited:
  • The state x(t) of a geometric Brownian motion satisfies an Ito differential equation:

  • d x(t) = μ * x(t) dt + σ*x(t) dw(t), where w(t) follows a standard Wiener Process.
  • The state of x(t) follows a LogNormal Distribution of [(μ-
    5OverscriptBox.png
    ) t+ Log[x0]]
  • The parameter μ can be any real number, and σ and x0 any positive real numbers.
  • The Wiener Process is a Brownian motion, continuous-time random walk, or integrated white Gaussian noise with a drift μ and volatility σ.
  • The state at time t of the Weiner process follows NormalDistribution[μ t,σ
    1OverscriptBox.png
    ].
 
  • The state x(t) of a geometric Brownian motion satisfies an Ito differential equation:

  • d x(t) = μ * x(t) dt + σ*x(t) dw(t), where w(t) follows a standard Wiener Process.
  • The state of x(t) follows a LogNormal Distribution of [(μ-
    5OverscriptBox.png
    ) t+ Log[x0]]
  • The parameter μ can be any real number, and σ and x0 any positive real numbers.
  • The Wiener Process is a Brownian motion, continuous-time random walk, or integrated white Gaussian noise with a drift μ and volatility σ.
  • The state at time t of the Weiner process follows NormalDistribution[μ t,σ
    1OverscriptBox.png
    ].
You said yours is different, but IMO it's the same GBM as in #2 in my posting above, ie. the GBM at wikipedia.
Or where do you see the difference?

I think there is something missing in the following sentence & formula, ie. the Wiener process part is missing:
The state of x(t) follows a LogNormal Distribution of [(μ-
5OverscriptBox.png
) t+ Log[x0]]

Here's a screenhot showing also the missing part in your posting:

Wolfram_GBM.png
 
Last edited:
Back
Top