Random Walk and Ornstein-Uhlenbeck Processes

I’ll create an example using a stochastic process - let’s simulate and analyze a Random Walk with drift and an Ornstein-Uhlenbeck process, which is often used in financial modeling.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import numpy as np
import matplotlib.pyplot as plt

# Set random seed for reproducibility
np.random.seed(42)

def simulate_random_walk(n_steps, drift=0.1, volatility=1.0, paths=5):
"""
Simulate random walk with drift
Parameters:
- n_steps: number of time steps
- drift: trend component
- volatility: size of random movements
- paths: number of paths to simulate
"""
steps = np.random.normal(drift, volatility, (paths, n_steps))
paths = np.cumsum(steps, axis=1)
return paths

def simulate_ornstein_uhlenbeck(n_steps, theta=1.0, mu=0.0, sigma=0.5, paths=5):
"""
Simulate Ornstein-Uhlenbeck process
Parameters:
- n_steps: number of time steps
- theta: mean reversion rate
- mu: long-term mean
- sigma: volatility
- paths: number of paths to simulate
"""
dt = 0.01
t = np.linspace(0, n_steps*dt, n_steps)
paths_ou = np.zeros((paths, n_steps))

for i in range(paths):
x = np.zeros(n_steps)
x[0] = mu
for j in range(1, n_steps):
dx = theta * (mu - x[j-1]) * dt + sigma * np.sqrt(dt) * np.random.normal()
x[j] = x[j-1] + dx
paths_ou[i] = x

return t, paths_ou

# Simulation parameters
n_steps = 1000
n_paths = 5

# Simulate processes
rw_paths = simulate_random_walk(n_steps, drift=0.1, volatility=0.5, paths=n_paths)
t_ou, ou_paths = simulate_ornstein_uhlenbeck(n_steps, theta=2.0, mu=0.0, sigma=1.0, paths=n_paths)

# Create visualizations
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))

# Plot Random Walk paths
time = np.arange(n_steps)
for i in range(n_paths):
ax1.plot(time, rw_paths[i], label=f'Path {i+1}')
ax1.set_title('Random Walk with Drift')
ax1.set_xlabel('Time Steps')
ax1.set_ylabel('Value')
ax1.grid(True, alpha=0.3)
ax1.legend()

# Add theoretical drift line
drift_line = 0.1 * time
ax1.plot(time, drift_line, '--', color='black', label='Theoretical Drift', alpha=0.5)

# Plot Ornstein-Uhlenbeck paths
for i in range(n_paths):
ax2.plot(t_ou, ou_paths[i], label=f'Path {i+1}')
ax2.axhline(y=0, color='black', linestyle='--', label='Long-term Mean', alpha=0.5)
ax2.set_title('Ornstein-Uhlenbeck Process')
ax2.set_xlabel('Time')
ax2.set_ylabel('Value')
ax2.grid(True, alpha=0.3)
ax2.legend()

plt.tight_layout()
plt.show()

# Calculate and print statistics
print("Random Walk Statistics:")
print(f"Final values: {rw_paths[:, -1]}")
print(f"Mean final value: {np.mean(rw_paths[:, -1]):.3f}")
print(f"Std of final values: {np.std(rw_paths[:, -1]):.3f}")

print("\nOrnstein-Uhlenbeck Statistics:")
print(f"Final values: {ou_paths[:, -1]}")
print(f"Mean final value: {np.mean(ou_paths[:, -1]):.3f}")
print(f"Std of final values: {np.std(ou_paths[:, -1]):.3f}")

Let me explain this example which demonstrates two different types of stochastic processes:

  1. Random Walk with Drift:

    • A discrete-time process where each step includes:
      • A constant drift term (trend)
      • A random component (noise)
    • Properties:
      • Non-stationary process
      • Variance increases with time
      • Used in financial modeling for asset prices
  2. Ornstein-Uhlenbeck Process:

    • A continuous-time mean-reverting process
    • Properties:
      • Mean-reverting (tends to return to a long-term average)
      • Stationary process
      • Often used to model interest rates or volatility

Key Components of the Code:

  1. simulate_random_walk:

    • Adds drift to random normal steps
    • Uses cumulative sum to create the path
    • Multiple paths show variation in possible outcomes
  2. simulate_ornstein_uhlenbeck:

    • Implements the OU stochastic differential equation
    • Mean reversion rate ($theta$) controls speed of return to mean
    • $Sigma$ controls volatility of the process

Visualization Explanation:

Random Walk Statistics:
Final values: [109.66602791 135.41811862 102.91710728  90.64039111  75.3631803 ]
Mean final value: 102.801
Std of final values: 20.059

Ornstein-Uhlenbeck Statistics:
Final values: [ 0.57734044  0.33628409  0.89794221  0.3854573  -0.2574374 ]
Mean final value: 0.388
Std of final values: 0.378

Top Graph (Random Walk):

  • Shows $5$ sample paths with positive drift
  • Black dashed line shows theoretical drift
  • Paths tend to move upward due to positive drift
  • Increasing spread over time shows growing uncertainty

Bottom Graph (Ornstein-Uhlenbeck):

  • Shows $5$ sample paths
  • Black dashed line shows long-term mean ($0$)
  • Paths constantly revert toward the mean
  • Consistent spread shows stationary behavior

Key Differences Between the Processes:

  1. The Random Walk:

    • Tends to drift away from starting point
    • Variance increases with time
    • No mean reversion
  2. The Ornstein-Uhlenbeck Process:

    • Stays around the mean
    • Has constant variance over time
    • Shows strong mean reversion

This example demonstrates important concepts in stochastic processes:

  • Mean reversion vs random drift
  • Stationary vs non-stationary processes
  • The role of drift and volatility
  • Different types of randomness in financial modeling