The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
Understanding the fundamentals of random walks and how RandomWalker implements them.
A random walk is a mathematical model describing a path consisting of a succession of random steps. At each point in time, the next step is determined by chance.
Imagine flipping a coin: - Heads: Move one step forward (+1) - Tails: Move one step backward (-1) - Start: Position 0
After 10 flips, you might be at position +2, -4, or anywhere else. This is a random walk!
# 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")Each step is ±1 with equal probability:
discrete_walk(
.num_walks = 10,
.upper_bound = 1,
.lower_bound = -1,
.upper_probability = 0.5
) |> head(10)
#> # A tibble: 10 × 8
#> walk_number step_number y cum_sum_y cum_prod_y cum_min_y cum_max_y
#> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 -1 99 0 99 99
#> 2 1 2 1 100 0 99 101
#> 3 1 3 1 101 0 99 101
#> 4 1 4 -1 100 0 99 101
#> 5 1 5 -1 99 0 99 101
#> 6 1 6 -1 98 0 99 101
#> 7 1 7 -1 97 0 99 101
#> 8 1 8 -1 96 0 99 101
#> 9 1 9 1 97 0 99 101
#> 10 1 10 1 98 0 99 101
#> # ℹ 1 more variable: cum_mean_y <dbl>Properties: - Symmetric (unbiased) - Steps are independent - Mean position = 0 - Variance grows linearly with time
Steps have a non-zero mean (bias in one direction):
random_normal_drift_walk(
.num_walks = 10,
.drift = 0.1 # Positive drift
) |> head(10)
#> # A tibble: 10 × 8
#> walk_number step_number y cum_sum_y cum_prod_y cum_min_y cum_max_y
#> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 1.46 1.46 0 1.46 1.46
#> 2 1 2 3.80 5.26 0 1.46 3.80
#> 3 1 3 -1.82 3.44 0 -1.82 3.80
#> 4 1 4 3.00 6.44 0 -1.82 3.80
#> 5 1 5 2.80 9.24 0 -1.82 3.80
#> 6 1 6 6.19 15.4 0 -1.82 6.19
#> 7 1 7 3.49 18.9 0 -1.82 6.19
#> 8 1 8 7.47 26.4 0 -1.82 7.47
#> 9 1 9 9.45 35.8 0 -1.82 9.45
#> 10 1 10 7.60 43.4 0 -1.82 9.45
#> # ℹ 1 more variable: cum_mean_y <dbl>Properties: - Asymmetric (biased) - Tends to move in one direction - Mean position ≠ 0 - Can model trending data
Continuous-time random walk:
brownian_motion(
.num_walks = 10,
.delta_time = 1
) |> head(10)
#> # A tibble: 10 × 8
#> walk_number step_number y cum_sum_y cum_prod_y cum_min_y cum_max_y
#> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 0.355 0.355 0 0.355 0.355
#> 2 1 2 1.72 2.07 0 0.355 1.72
#> 3 1 3 0.996 3.07 0 0.355 1.72
#> 4 1 4 -0.730 2.34 0 -0.730 1.72
#> 5 1 5 -0.176 2.16 0 -0.730 1.72
#> 6 1 6 1.61 3.77 0 -0.730 1.72
#> 7 1 7 2.28 6.05 0 -0.730 2.28
#> 8 1 8 0.381 6.43 0 -0.730 2.28
#> 9 1 9 -0.0780 6.36 0 -0.730 2.28
#> 10 1 10 -1.66 4.69 0 -1.66 2.28
#> # ℹ 1 more variable: cum_mean_y <dbl>Properties: - Continuous in time - Normally distributed increments - Foundation of stochastic calculus - Used in physics and finance
Multiplicative random walk (always positive):
geometric_brownian_motion(
.num_walks = 10,
.initial_value = 100
) |> head(10)
#> # A tibble: 10 × 8
#> walk_number step_number y cum_sum_y cum_prod_y cum_min_y cum_max_y
#> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 1.00 101. 200. 101. 101.
#> 2 1 2 1.00 102. 401. 101. 101.
#> 3 1 3 1.01 103. 805. 101. 101.
#> 4 1 4 1.01 104. 1619. 101. 101.
#> 5 1 5 1.00 105. 3243. 101. 101.
#> 6 1 6 1.01 106. 6506. 101. 101.
#> 7 1 7 1.01 107. 13095. 101. 101.
#> 8 1 8 1.01 108. 26373. 101. 101.
#> 9 1 9 1.01 109. 53132. 101. 101.
#> 10 1 10 1.01 110. 106945. 101. 101.
#> # ℹ 1 more variable: cum_mean_y <dbl>Properties: - Cannot go negative - Used for stock prices - Log-normal distribution - Percentage changes are normal
For a symmetric random walk starting at 0:
Expected value after n steps = 0
For standard random walk:
Variance after n steps = n
Expected distance grows as √n:
E[|position|] ∝ √n
# 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)
#> # A tibble: 10 × 3
#> step_number mean_distance theoretical
#> <int> <dbl> <dbl>
#> 1 50 0.193 7.07
#> 2 50 0.193 7.07
#> 3 50 0.193 7.07
#> 4 50 0.193 7.07
#> 5 50 0.193 7.07
#> 6 50 0.193 7.07
#> 7 50 0.193 7.07
#> 8 50 0.193 7.07
#> 9 50 0.193 7.07
#> 10 50 0.193 7.07For 1D symmetric walk: - Probability of eventual return = 1 (certain to return) - Expected return time = ∞ (infinite expected time!)
For 2D symmetric walk: - Probability of eventual return = 1
For 3D symmetric walk: - Probability of eventual return ≈ 0.34 (not certain!)
Random walks exhibit scaling invariance: - If you zoom out by factor k - Time scales by k² - Position scales by k
Position after n steps:
X(n) = X(0) + Σ(i=1 to n) Δᵢ
Where Δᵢ are independent random steps.
For standard normal walk: - Δᵢ ~ N(0, 1) - X(n) ~ N(0, n) - E[X(n)] = 0 - Var[X(n)] = n
Continuous-time stochastic process:
dX(t) = μ dt + σ dW(t)
Where: - μ = drift coefficient - σ = volatility coefficient - W(t) = standard Wiener process
Properties: - W(0) = 0 - W(t) ~ N(0, t) - W(t) - W(s) ~ N(0, t-s) for t > s - Independent increments
For stock prices:
dS(t) = μ S(t) dt + σ S(t) dW(t)
Solution:
S(t) = S(0) exp((μ - σ²/2)t + σW(t))
Properties: - Always positive - Log-normal distribution - Used in Black-Scholes model
# 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)
#> # A tibble: 10 × 7
#> step_number y cum_sum cum_prod cum_min cum_max cum_mean
#> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 2.24 0 3.24 2.24 2.24 2.24
#> 2 2 0.691 2.24 5.48 0.691 2.24 1.47
#> 3 3 0.665 2.93 9.12 0.665 2.24 1.20
#> 4 4 0.901 3.60 17.3 0.665 2.24 1.12
#> 5 5 0.0452 4.50 18.1 0.0452 2.24 0.908
#> 6 6 1.09 4.54 37.9 0.0452 2.24 0.939
#> 7 7 -1.05 5.63 -1.76 -1.05 2.24 0.655
#> 8 8 0.0292 4.59 -1.81 -1.05 2.24 0.577
#> 9 9 -0.302 4.62 -1.27 -1.05 2.24 0.479
#> 10 10 -0.0866 4.31 -1.16 -1.05 2.24 0.4231D Walk: - Single value per step: y -
Position: cum_sum
2D Walk: - Two values per step: x,
y - Position: (cum_sum_x, cum_sum_y) -
Distance: sqrt(cum_sum_x² + cum_sum_y²)
3D Walk: - Three values per step: x,
y, z - Position:
(cum_sum_x, cum_sum_y, cum_sum_z) - Distance:
sqrt(cum_sum_x² + cum_sum_y² + cum_sum_z²)
| Term | Definition | Example |
|---|---|---|
| Walk | A single realization of the random process | One stock price path |
| Step | One random increment | Daily price change |
| Trajectory | Path taken by the walk | Price history |
| Cumulative sum | Running total of steps | Stock price level |
| Displacement | Distance from starting point | Profit/loss |
| Excursion | Distance from reference point | Drawdown |
| First passage time | Time to first reach a level | Time to profit |
| Return time | Time to return to starting point | Recovery time |
| Term | Definition |
|---|---|
| Mean | Average value |
| Variance | Spread of values |
| Standard deviation | √Variance |
| Skewness | Asymmetry measure |
| Kurtosis | Tail heaviness |
| Quantile | Percentile value |
| Confidence interval | Range containing true value with probability |
| Distribution | Use Case | Parameters |
|---|---|---|
| Normal | General purpose | μ (mean), σ (sd) |
| Uniform | Equal probabilities | min, max |
| Exponential | Waiting times | λ (rate) |
| Poisson | Event counts | λ (rate) |
| Cauchy | Heavy tails | location, scale |
| Binomial | Success counts | n (trials), p (prob) |
# Generate many walks
walks <- random_normal_walk(.num_walks = 1000, .n = 100)
# Property 1: Mean = 0
walks |>
summarize(overall_mean = mean(cum_sum_y))
#> # A tibble: 1 × 1
#> overall_mean
#> <dbl>
#> 1 -0.0319
# Property 2: Variance = n
walks |>
filter(step_number == 80) |>
summarize(
variance = var(cum_sum_y),
theoretical = 80
)
#> # A tibble: 1 × 2
#> variance theoretical
#> <dbl> <dbl>
#> 1 1.41 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)
#> # A tibble: 5 × 3
#> step_number mean_abs_position theoretical
#> <int> <dbl> <dbl>
#> 1 20 0.378 3.57
#> 2 20 0.378 3.57
#> 3 20 0.378 3.57
#> 4 20 0.378 3.57
#> 5 20 0.378 3.57# 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"
)Random walks are path-dependent - the ending doesn’t tell you the route:
# 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)Now that you understand the basics:
Ready to generate walks? Head to the Getting Started vignette!
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.