########################################################################################################################################################## ### Program: SimTrade_mu_versus_sigma_R_code_2026_01_04_SB ### ### Author: Saral Bindal ### ### Contact: saralbindal.24@kgpian.iitkgp.ac.in ### ### Article on the SimTrade blog: https://www.simtrade.fr/blog_simtrade/modeling-asset-prices-financial-markets-arithmetic-geometric-brownian-motions/ ### ########################################################################################################################################################## # R program to simulate market prices using arithmetic Brownian motion and geometric Brownian motion. # Objectives of the program: # 1) Simulate market prices using ABM and GBM. # 2) Calculate mean, upper and lower line for confidence intervals. #################################################################################################### ### Organization of the program: ### ### STEP 1: Environment setup and package loading ### ### STEP 2: Define parameters ### ### STEP 3: Computation and plotting of price paths for ABM ### ### STEP 4: Computation and plotting of price paths for GBM ### #################################################################################################### #################################################################################################### ### Parameters you can change for BSM option pricing: ### ### n_sims : Number of simulations ### ### n_months : Number of time steps ### ### dt : time step ### ### mu : Annualized drift/mean ### ### sigma : Annualized volatility/standard deviation ### ### S0 : Initial market price ### #################################################################################################### ################# # Documentation # ################# # R packages # https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/Random # https://www.rdocumentation.org/packages/stats/versions/3.6.2/topics/Normal # https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/matplot # https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/axis # https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/lines # https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/polygon # https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/grid # https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/legend # Academic articles # Bachelier, L. (1900). Theory of Speculation. Annals of the Scientific School of the Ecole Normale Superieure, 3rd series, 17, 21-86. # Samuelson P. A. (1965). Rational theory of warrant pricing. Industrial Management Review, 6(2), 13-39. # Wiener N. (1923). Differential-space. Journal of Mathematics and Physics, 2, 131-174. ################################################# # STEP 1: Environment setup and package loading # ################################################# # Language used by R to display error messages Sys.setenv(LANG = "en") # Remove all objects from the R environment rm(list = ls()) # Clear the RStudio console cat("\014") # Fix the random seed (same randomness stream for ABM and GBM) set.seed(12345) ############################## # STEP 2: Define parameters # ############################## # t <- 10 # Number of years n_months <- 120 # Number of time steps dt <- 1/12 # Time step n_sims <- 100000 # Number of simulations ########################################################### # STEP 3: Computation and plotting of price paths for ABM # ########################################################### # 1. ARITHMETIC BROWNIAN MOTION #Annualized drift and volatility calibrated on the parameters of GBM m <- 8 # mu (in $) s <- 15 # sigma (in $) S0 <- 100 # Initial price (ABM can take negative values) # Generate random shocks (Brownian increments) # Each row = one time step # Each column = one simulation path increments <- matrix( rnorm(n_sims * n_months, mean = m * dt, sd = s * sqrt(dt)), nrow = n_months, ncol = n_sims ) # Convert increments into price paths using cumulative sums # Transpose so that time runs along columns price_paths <- S0 + t(apply(increments, 2, cumsum)) # Time vector (in years) t <- (1:n_months) * dt # Confidence level alpha <- 0.34 z_alpha <- qnorm(1 - (alpha/ 2)) # Theoretical values mean_path <- S0 + m * t upper_band <- S0 + m * t + z_alpha * s * sqrt(t) lower_band <- S0 + m * t - z_alpha * s * sqrt(t) # Plot ABM # Plot only a subset of paths to avoid over plotting matplot( t(price_paths[1:1000, ]), type = "l", lty = 1, col = rgb(0, 0, 0, 0.02), # Semi-transparent lines xlab = "Time (in months)", ylab = "Asset price ($)", main = paste("Monte Carlo Simulation:", n_sims, "ABM Price Paths"), font.lab = 2, # ← bold axis labels xlim = c(0, 120), xaxt = "n", ylim = c(0, 400), yaxt = "n", ) #For x-axis axis(side = 1, at = seq(0, 120, by = 10), las = 1) #For y-axis axis(side = 2, at = seq(0, 400, by = 100), las = 1) # Overlay the mean path lines(mean_path, col = "cyan", lwd = 2, lty = 2) # Add confidence interval as a shaded region polygon( c(1:n_months, rev(1:n_months)), c(lower_band, rev(upper_band)), col = rgb(0, 1, 1, 0.2), border = NA ) # Add grid for readability grid() # Legend legend( "topleft", legend = c( "Simulated price paths", "Expected price", "Confidence interval (66%)" ), col = c( rgb(0, 0, 0, 0.4), "cyan", rgb(0, 1, 1, 0.4) ), lty = c(1, 2, NA), lwd = c(1, 2, NA), pch = c(NA, NA, 15), pt.cex = 2, bty = "n" ) ########################################################### # STEP 4: Computation and plotting of price paths for GBM # ########################################################### mu <- 0.08 sigma <- 0.15 # 2. GEOMETRIC BROWNIAN MOTION m <- mu - 0.5 * sigma^2 # Drift adjustment for log-normality s <- sigma # Volatility S0 <- 100 # Initial price (GBM remains strictly positive) # Generate log returns # Each column = one simulation path # Each row = one time step log_returns <- matrix( rnorm(n_sims * n_months, mean = m * dt, sd = s * sqrt(dt)), nrow = n_months, ncol = n_sims ) # Convert log returns into price paths # Exponentiation enforces positivity of prices price_paths <- S0 * exp(t(apply(log_returns, 2, cumsum))) # Time vector (in years) t <- (1:n_months) * dt # Confidence level alpha <- 0.66 z_alpha <- qnorm((1 + alpha) / 2) # Theoretical values mean_path <- S0 * exp(mu * t) upper_band <- S0 * exp((mu - 0.5 * sigma^2) * t + z_alpha * sigma * sqrt(t)) lower_band <- S0 * exp((mu - 0.5 * sigma^2) * t - z_alpha * sigma * sqrt(t)) # Plot GBM # Plot only a subset of paths to avoid overplotting matplot( t(price_paths[1:1000, ]), type = "l", lty = 1, col = rgb(0, 0, 0, 0.02), xlab = "Time (in months)", ylab = "Asset price ($)", main = paste("Monte Carlo Simulation:", n_sims, "GBM Price Paths"), font.lab = 2, # ← bold axis labels xlim = c(0, 120), xaxt = "n", ylim = c(0, 400), yaxt = "n", ) #For x-axis axis(side = 1, at = seq(0, 120, by = 10), las = 1) #For y-axis axis(side = 2, at = seq(0, 400, by = 100), las = 1) # Overlay the mean trajectory lines(mean_path, col = "cyan", lwd = 2, lty = 2) # Add confidence interval shading polygon( c(1:n_months, rev(1:n_months)), c(lower_band, rev(upper_band)), col = rgb(0, 1, 1, 0.2), border = NA ) # Add grid lines grid() # Legend legend( "topleft", legend = c( "Simulated price paths", "Expected price", "Confidence interval (66%)" ), col = c( rgb(0, 0, 0, 0.4), "cyan", rgb(0, 1, 1, 0.4) ), lty = c(1, 2, NA), lwd = c(1, 2, NA), pch = c(NA, NA, 15), pt.cex = 2, bty = "n" ) # End of the code