## ----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)

