diff --git a/DESCRIPTION b/DESCRIPTION index ff7f165..677c983 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -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) @@ -17,7 +21,9 @@ Depends: R (>= 4.1.0) Imports: dplyr, - tidyr + tidyr, + purrr, + rlang Suggests: knitr, rmarkdown, diff --git a/NAMESPACE b/NAMESPACE index 66c7664..42285ba 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,4 +1,5 @@ # Generated by roxygen2: do not edit by hand +export(geometric_brownian_motion) export(random_normal_walk) export(rw30) diff --git a/NEWS.md b/NEWS.md index e45497b..2c7c397 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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 diff --git a/R/gen-geom-brown-motion.R b/R/gen-geom-brown-motion.R new file mode 100644 index 0000000..3ad0cb1 --- /dev/null +++ b/R/gen-geom-brown-motion.R @@ -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) +} diff --git a/man/geometric_brownian_motion.Rd b/man/geometric_brownian_motion.Rd new file mode 100644 index 0000000..0e56aaf --- /dev/null +++ b/man/geometric_brownian_motion.Rd @@ -0,0 +1,79 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/gen-geom-brown-motion.R +\name{geometric_brownian_motion} +\alias{geometric_brownian_motion} +\title{Geometric Brownian Motion} +\usage{ +geometric_brownian_motion( + .num_walks = 25, + .n = 100, + .mu = 0, + .sigma = 0.1, + .initial_value = 100, + .delta_time = 0.003, + .return_tibble = TRUE +) +} +\arguments{ +\item{.num_walks}{Total number of simulations.} + +\item{.n}{Total time of the simulation, how many \code{n} points in time.} + +\item{.mu}{Expected return} + +\item{.sigma}{Volatility} + +\item{.initial_value}{Integer representing the initial value.} + +\item{.delta_time}{Time step size.} + +\item{.return_tibble}{The default is TRUE. If set to FALSE then an object +of class matrix will be returned.} +} +\value{ +A tibble/matrix +} +\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: + +\if{html}{\out{