You are expecting the GBM to perform functions it was never set out to perform. By the way, you still have not clarified what exactly you disagree with in provided solutions. You made similar outrageous claims about other models in the past and each time you were schooled and proven wrong...whats new this time?
GBM by itself is just a base model. You need to add a dynamic risk free rate and simulate the option chain to develop an accurate real word Algo trading system.
@Sergio123, it's about GBM itself. The versions I so far tested are all buggy. It much looks like that the well known GBM algorithm(s) in use are all generally buggy in the first place. And a const r, q, s is ok for me.
This looks very much professional. I'll study & test it. Thank you very much. Hmm. I just quickly skimmed over the code, but I'm not sure whether this is really a normal GBM algorithm. One has to know that there is also just "Brownian Motion" w/o the "Geometric" part, aka ABM, or Arithmetic Brownian Motion. Need to take more time to study it. Since there is not a single mentioning of "geometric", then I assume it's not GBM, othweise they would/should explicitly state "geometric". It's just missing.... :-(
Here is one with geometric in the title. https://towardsdatascience.com/geometric-brownian-motion-559e25382a55 Code: import matplotlib.pyplot as plt import numpy as np import math class GBM: def simulate(self): while(self.total_time > 0): dS = self.current_price*self.drift*self.time_period + self.current_price*self.volatility*np.random.normal(0, math.sqrt(self.time_period)) self.prices.append(self.current_price + dS) self.current_price += dS self.total_time -= self.time_period def __init__(self, initial_price, drift, volatility, time_period, total_time): # Initialize fields self.initial_price = initial_price self.current_price = initial_price self.drift = drift self.volatility = volatility self.time_period = time_period self.total_time = total_time self.prices = [] # Simulate the diffusion process self.simulate() # Simulate the diffusion proces simulations = [] n = 1000 initial_price = 500 drift = .24 volatility = .4 time_period = 1/365 # Daily total_time = 1 for i in range(0, n): simulations.append(GBM(initial_price, drift, volatility, time_period, total_time)) for sim in simulations: plt.plot(np.arange(0, len(sim.prices)), sim.prices) plt.show()
@ph1l at al, there are many GBM articles and code on the net, but I need the opinion of experts with hands-on-experience about the quality of the code and algorithm used. If you are sure & convinced that the algorithm and code is correct then we can focus on it and test further. Can you math guys check/verify this new code linked by @ph1l with the wikipedia GBM page. What difference in the algorithm is there, if any?
This algorithm & code is interesting as it doesn't use any log(), ln(), e(), or exp() That's very unusual and different from other GBM algos. I'm now going to test this GBM algo in my test framework...
This algorithm cannot be correct b/c it generates negative stock prices! This never ever should happen Code: Settings used: n = 1000 initial_price = 500 drift = 0.0 volatility = 1.5 time_period = 0.5 # ie. 2 per year total_time = 1.0 # 1 year Plot: Maybe someone inform the author (Roman Paolucci) about this finding so that he maybe can try to fix his algorithm. Link to his article and code is in prev posting.
Here's one where the author first codes standard Brownian motion. https://isquared.digital/blog/2020-04-16-brownian-motion/ Then he uses that for drifted Brownian motion. https://isquared.digital/blog/2020-05-01-drifted-brownian-motion/ And finally, he uses drifted Brownian motion to implement geometric Brownian motion https://isquared.digital/blog/2020-05-17-geometric-brownian-motion/#:~:text=Definition of Geometric Brownian Motion&text=This process follows a log,characteristic, they are never negative. including avoiding negative values. 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 Code: import numpy as np def drifted_brownian_motion(mu, sigma, N, T, seed=42): """Simulates a Brownian Motion with drift. :param float mu: drift coefficient :param float sigma: volatility coefficient :param int N : number of discrete steps :param int T: number of continuous time steps :param int seed: initial seed of the random generator :returns list: drifted Brownian motion """ # set the seed np.random.seed(seed) # standard brownian motion W, _ = brownian_motion(N, T ,1.0) # the normalizing constant dt = 1. * T/N # generate the time steps time_steps = np.linspace(0.0, N*dt, N+1) # calculate the Brownian Motion with drift X = mu * time_steps + sigma * W return X Code: 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