## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ## ----setup, echo=FALSE, message=FALSE----------------------------------------- library(RandomWalker) library(dplyr) library(ggplot2) ## ----coin_flip_example, fig.width=7, fig.height=4----------------------------- # Coin flip random walk coin_walk <- discrete_walk( .num_walks = 1, .n = 100, .upper_bound = 1, .lower_bound = -1, .upper_probability = 0.5 ) coin_walk |> visualize_walks(.pluck = "cum_sum_y") ## ----simple_walk-------------------------------------------------------------- discrete_walk( .num_walks = 10, .upper_bound = 1, .lower_bound = -1, .upper_probability = 0.5 ) |> head(10) ## ----drift_walk--------------------------------------------------------------- random_normal_drift_walk( .num_walks = 10, .drift = 0.1 # Positive drift ) |> head(10) ## ----brownian_motion---------------------------------------------------------- brownian_motion( .num_walks = 10, .delta_time = 1 ) |> head(10) ## ----geometric_brownian------------------------------------------------------- geometric_brownian_motion( .num_walks = 10, .initial_value = 100 ) |> head(10) ## ----mean_displacement-------------------------------------------------------- # Verify empirically walks <- random_normal_walk(.num_walks = 1000, .n = 100) walks |> summarize(overall_mean = mean(cum_sum_y)) ## ----variance_growth---------------------------------------------------------- # Verify empirically walks <- random_normal_walk(.num_walks = 1000, .n = 100) walks |> filter(step_number == 80) |> summarize( variance = var(cum_sum_y), theoretical = 80 ) ## ----distance_origin---------------------------------------------------------- # Verify with 2D walk walks_2d <- random_normal_walk(.num_walks = 100, .n = 500, .dimensions = 2) walks_2d |> euclidean_distance(.x = x, .y = y) |> group_by(step_number) |> reframe( mean_distance = mean(distance), theoretical = sqrt(step_number) ) |> filter(step_number %% 50 == 0) |> head(10) ## ----behind_scenes------------------------------------------------------------ # What rw30() does internally: # 1. Generate random steps steps <- rnorm(100, mean = 0, sd = 1) # 2. Compute cumulative sum positions <- cumsum(c(0, steps[-100])) # 3. Add to tibble walk_data <- dplyr::tibble( step_number = 1:100, y = steps, cum_sum = positions ) # 4. Add more cumulative functions walk_data <- walk_data |> mutate( cum_prod = cumprod(1 + y), cum_min = cummin(y), cum_max = cummax(y), cum_mean = cumsum(y) / step_number ) walk_data |> head(10) ## ----verify_properties-------------------------------------------------------- # Generate many walks walks <- random_normal_walk(.num_walks = 1000, .n = 100) # Property 1: Mean = 0 walks |> summarize(overall_mean = mean(cum_sum_y)) # Property 2: Variance = n walks |> filter(step_number == 80) |> summarize( variance = var(cum_sum_y), theoretical = 80 ) # Property 3: Distance ∝ √n walks |> group_by(step_number) |> reframe( mean_abs_position = mean(abs(cum_sum_y)), theoretical = sqrt(2/pi) * sqrt(step_number) # Exact for normal ) |> filter(step_number %% 20 == 0) |> head(5) ## ----final_position_dist, fig.width=7, fig.height=4--------------------------- # Generate walks walks <- random_normal_walk(.num_walks = 10000, .n = 100) # Get final positions final_pos <- walks |> group_by(walk_number) |> slice_max(step_number) |> pull(cum_sum_y) # Plot dplyr::tibble(position = final_pos) |> ggplot(aes(x = position)) + geom_histogram(aes(y = after_stat(density)), bins = 50, fill = "steelblue", alpha = 0.7) + stat_function(fun = dnorm, args = list(mean = 0, sd = 1), color = "red", linewidth = 1) + theme_minimal() + labs( title = "Distribution of Final Positions (n=100)", subtitle = "Theoretical N(0, 1) in red", x = "Final Position", y = "Density" ) ## ----path_dependency, fig.width=7, fig.height=4------------------------------- # Generate walks ending at similar positions set.seed(123) walks <- random_normal_walk(.num_walks = 100, .n = 100) # Find walks ending near 10 similar_end <- walks |> group_by(walk_number) |> filter(step_number == 80, abs(cum_sum_y - 1) < 0.5) # Plot their paths - very different! walks |> filter(walk_number %in% similar_end$walk_number) |> visualize_walks(.pluck = "cum_sum_y", .alpha = 0.5)