Skip to content

Commit

Permalink
Merge pull request #20 from spsanderson/development
Browse files Browse the repository at this point in the history
Fixes #17
  • Loading branch information
spsanderson authored Jul 16, 2024
2 parents e0f6e44 + e4852ea commit d97c563
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 2 deletions.
10 changes: 8 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ Authors@R: c(
comment = c(ORCID = "0009-0006-7661-8247")
)
)
Description: What the package does (one paragraph).
Description:
This package makes it simple to generate random walks of various types.
It does so by providing a set of functions that are compatible with the
'tidyverse'. The goal is to provide a simple set of functions that are powerful
enough to generate a wide variety of random walks, while also being easy to use.
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
Expand All @@ -17,7 +21,9 @@ Depends:
R (>= 4.1.0)
Imports:
dplyr,
tidyr
tidyr,
purrr,
rlang
Suggests:
knitr,
rmarkdown,
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Generated by roxygen2: do not edit by hand

export(geometric_brownian_motion)
export(random_normal_walk)
export(rw30)
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ None

## New Features
1. Fix #9 - Add Function `rw30()` to generate 30 random walks of 100 steps each.
2. Fix #17 - Add Function `geometric_brownian_motion()`

## Minor Improvements and Fixes
None
120 changes: 120 additions & 0 deletions R/gen-geom-brown-motion.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#' Geometric Brownian Motion
#'
#' @family Generator Functions
#'
#' @author Steven P. Sanderson II, MPH
#'
#' @description Create a Geometric Brownian Motion.
#'
#' @details Geometric Brownian Motion (GBM) is a statistical method for modeling
#' the evolution of a given financial asset over time. It is a type of stochastic
#' process, which means that it is a system that undergoes random changes over
#' time.
#'
#' GBM is widely used in the field of finance to model the behavior of stock
#' prices, foreign exchange rates, and other financial assets. It is based on
#' the assumption that the asset's price follows a random walk, meaning that it
#' is influenced by a number of unpredictable factors such as market trends,
#' news events, and investor sentiment.
#'
#' The equation for GBM is:
#'
#' dS/S = mdt + sdW
#'
#' where S is the price of the asset, t is time, m is the expected return on the
#' asset, s is the volatility of the asset, and dW is a small random change in
#' the asset's price.
#'
#' GBM can be used to estimate the likelihood of different outcomes for a given
#' asset, and it is often used in conjunction with other statistical methods to
#' make more accurate predictions about the future performance of an asset.
#'
#' This function provides the ability of simulating and estimating the parameters
#' of a GBM process. It can be used to analyze the behavior of financial
#' assets and to make informed investment decisions.
#'
#' @param .n Total time of the simulation, how many `n` points in time.
#' @param .num_walks Total number of simulations.
#' @param .delta_time Time step size.
#' @param .initial_value Integer representing the initial value.
#' @param .mu Expected return
#' @param .sigma Volatility
#' @param .return_tibble The default is TRUE. If set to FALSE then an object
#' of class matrix will be returned.
#'
#' @examples
#' ts_geometric_brownian_motion()
#'
#' @return
#' A tibble/matrix
#'
#' @name geometric_brownian_motion
NULL

#' @export
#' @rdname geometric_brownian_motion

geometric_brownian_motion <- function(.num_walks = 25, .n = 100,
.mu = 0, .sigma = 0.1,
.initial_value = 100,
.delta_time = 0.003,
.return_tibble = TRUE) {

# Tidyeval ----
# Thank you to https://robotwealth.com/efficiently-simulating-geometric-brownian-motion-in-r/
num_sims <- as.numeric(.num_walks)
t <- as.numeric(.n)
mu <- as.numeric(.mu)
sigma <- as.numeric(.sigma)
initial_value <- as.numeric(.initial_value)
delta_time <- as.numeric(.delta_time)
return_tibble <- as.logical(.return_tibble)

# Checks ----
if (!is.logical(return_tibble)){
rlang::abort(
message = "The paramter `.return_tibble` must be either TRUE/FALSE",
use_cli_format = TRUE
)
}

if (!is.numeric(num_sims) | !is.numeric(t) | !is.numeric(mu) |
!is.numeric(sigma) | !is.numeric(initial_value) | !is.numeric(delta_time)){
rlang::abort(
message = "The parameters of `.n', `.num_walks`, `.mu`, `.sigma`,
`.initial_value`, and `.delta_time` must be numeric.",
use_cli_format = TRUE
)
}

# matrix of random draws - one for each day for each simulation
rand_matrix <- matrix(rnorm(t * num_sims), ncol = num_sims, nrow = t)
colnames(rand_matrix) <- 1:num_sims

# get GBM and convert to price paths
ret <- exp((mu - sigma * sigma / 2) * delta_time + sigma * rand_matrix * sqrt(delta_time))
ret <- apply(rbind(rep(initial_value, num_sims), ret), 2, cumprod)

# Return
if (return_tibble){
ret <- ret |>
dplyr::as_tibble() |>
dplyr::mutate(t = 1:(t+1)) |>
tidyr::pivot_longer(-t) |>
dplyr::select(name, t, value) |>
purrr::set_names("walk_number", "x", "y") |>
dplyr::mutate(walk_number = factor(walk_number)) |>
dplyr::arrange(walk_number, x)
}

attr(ret, "time") <- .n
attr(ret, "num_sims") <- .num_walks
attr(ret, "mean") <- .mu
attr(ret, "sigma") <- .sigma
attr(ret, "initial_value") <- .initial_value
attr(ret, "delta_time") <- .delta_time
attr(ret, "return_tibble") <- .return_tibble
attr(ret, "motion_type") <- "Geometric Brownian Motion"

return(ret)
}
79 changes: 79 additions & 0 deletions man/geometric_brownian_motion.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions man/random_normal_walk.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d97c563

Please sign in to comment.