TP6: Marches Aléatoires
Le but de ce TP est de faire différentes simulations liées aux marches aléatoires.
Marche aléatoire simple symétrique
On rappelle qu’une marche aléatoire simple symétrique est une suite (S_n) telle que S_0=x est déterministe et S_{n+1}=S_n+X_{n+1}=S_0+\sum_{k=1}^{n+1}X_k où (X_n) est une suite de variables aléatoires indépendantes et de même loi donnée par \mathbb{P}(X_1=1)=\mathbb{P}(X_1=-1)=1/2.
- Construire un simulateur de marche aléatoire prenant en entrée la valeur de S_0 et un horizon de temps N et donnant en sortie la suite (S_n)_{0\leq n\leq N}
Solution
import numpy as np
def marche(x, N):
"""
Simulates a random walk.
Parameters:
x (float): Initial value.
N (int): Number of steps.
Returns:
numpy.ndarray: Array representing the random walk path.
"""
# Generate random steps (-1 or 1) with equal probability
= np.random.choice([-1, 1], size=N, p=[0.5, 0.5])
X
# Calculate the cumulative sum of steps and add it to the initial value
= x + np.cumsum(np.insert(X, 0, 0))
S
return S
- Tracer quelques trajectoires de la marche pour x=0 et N=100.
Solution
import matplotlib.pyplot as plt
= 100
N # Generate random walks
= [marche(0, N) for _ in range(4)]
S = np.arange(N + 1)
absc
= ['tomato', 'dodgerblue', 'seagreen', 'darkorange']
colors# Plot the random walks
= plt.subplots(figsize=(10, 5))
fig, ax for i, s in enumerate(S):
='o', markersize=3, linestyle='-', linewidth=2, color=colors[i])
ax.plot(absc, s, marker
'Steps')
plt.xlabel('Value')
plt.ylabel('Random Walks')
plt.title(True)
plt.grid( plt.show()
- Construire un simulateur du problème de la ruine de la joueuse prenant en entrée la valeur de S_0, la plafond de gain a et le plancher de perte b et donnant en sortie la suite (S_n) de l’instant n=0 au premier instant où la marche touche a ou b.
Solution
import numpy as np
def ruine(x, a, b):
"""
Simulates a random walk until it hits either a or b.
Parameters:
x (float): Initial value.
a (float): Upper limit.
b (float): Lower limit.
Returns:
numpy.ndarray: Array representing the random walk path until it hits a or b.
"""
assert (x < a) and (x > b)
= [x]
S while S[-1] > b and S[-1] < a:
= np.random.choice([-1, 1], p=[0.5, 0.5])
step -1] + step)
S.append(S[
return np.array(S)
Par exemple, pour simuler des trajectoires partant d’une fortune initiale de S_0 = 5 avec a=10 et b=0
print(ruine(5, 10, 0))
[ 5 6 7 8 9 10]
- Tracer quelques trajectoires du jeu pour x=10, a=20, b=0.
Solution
# Number of trajectories
= 4
num_trajectories
# Plot the random walks
= plt.subplots(figsize=(10, 5))
fig, ax
= ['tomato', 'dodgerblue', 'seagreen', 'darkorange']
colors
=0
a=20
b
=a, color='black', linestyle='--', linewidth=2)
ax.axhline(y=b, color='black', linestyle='--', linewidth=2)
ax.axhline(y
# Generate and plot trajectories
for i in range(num_trajectories):
= ruine(10, 20, 0)
M len(M)), M, marker='o', markersize=3, linestyle='-', linewidth=2, color=colors[i])
ax.plot(np.arange(len(M)-1, M[-1], marker='o', markersize=7, linestyle='-', linewidth=2, color=colors[i])
ax.plot(
-5, 25)
ax.set_ylim('Steps')
plt.xlabel('Value')
plt.ylabel('Random Walks until hitting 20 or 0')
plt.title(True)
plt.grid( plt.show()
- Estimer la probabilité de ruine par la méthode de Monte Carlo avec les mêmes paramètres x=10, a=20, b=0.
Solution
= 1000
NMC = np.zeros(NMC)
proba for n in range(NMC):
= ruine(10, 20, 0)
S = (S[-1] == 0)
proba[n]
= np.mean(proba)
IN = [IN - 1.96 * np.sqrt(np.var(proba) / NMC), IN + 1.96 * np.sqrt(np.var(proba) / NMC)]
IC
print("Estimated Probability:", IN)
print("95% Confidence Interval:", IC)
Estimated Probability: 0.487
95% Confidence Interval: [0.4560201554296991, 0.5179798445703009]
La valeur théorique de 1/2 est bien dans l’intervalle de confiance.
- Estimer la durée moyenne du jeu par la méthode de Monte Carlo avec les mêmes paramètres x=10, a=20, b=0.
Solution
= 1000
NMC = np.zeros(NMC)
duree for n in range(NMC):
= ruine(10, 20, 0)
S = len(S) - 1
duree[n]
= np.mean(duree)
IN = [IN - 1.96 * np.sqrt(np.var(duree) / NMC), IN + 1.96 * np.sqrt(np.var(duree) / NMC)]
IC
print("Estimated Duration:", IN)
print("95% Confidence Interval:", IC)
Estimated Duration: 97.75
95% Confidence Interval: [92.54290982732198, 102.95709017267802]
La valeur théorique de -ab+x(a+b)-x^2=100 est bien dans l’intervalle de confiance.
Mouvement brownien
On rappelle que le mouvement Brownien (B_t)_{t\in[0,1]} peut s’obtenir comme la limite de B^N_t =\frac{1}{\sqrt{N}} S_{\lfloor Nt \rfloor} = \frac{1}{\sqrt{N}} \sum_{k=1}^{\lfloor Nt \rfloor} X_k. lorsque N tend vers l’infini, où (S_n) est une marche aléatoire simple symétrique telle que S_0=0.
- Simuler une marche aléatoire (S_n) à 100\ 000. En utilisant les N premières coordonnées de cette marche, tracer une trajectoire de B^N sur [0,1] pour N=100, N=1\ 000, N=10\ 000 et N=100\ 000. Commenter.
Solution
# Generate a random walk with 100,000 steps
= marche(0, 100000)
S
# Plot B100
= S[:101] / np.sqrt(100)
B100 0, 1, 101), B100)
plt.plot(np.linspace('B100')
plt.title(
plt.show()
# Plot B1000
= S[:1001] / np.sqrt(1000)
B1000 0, 1, 1001), B1000)
plt.plot(np.linspace('B1000')
plt.title(0, 0.1, color='gray', alpha=0.2)
plt.axvspan(
plt.show()
# Plot B10000
= S[:10001] / np.sqrt(10000)
B10000 0, 1, 10001), B10000)
plt.plot(np.linspace('B10000')
plt.title(0, 0.01, color='gray', alpha=0.2)
plt.axvspan(0, 0.1, color='gray', alpha=0.2)
plt.axvspan(
plt.show()
# Plot B
= S / np.sqrt(100000)
B 0, 1, 100001), B)
plt.plot(np.linspace('B100000')
plt.title(0, 0.001, color='gray', alpha=0.2)
plt.axvspan(0, 0.01, color='gray', alpha=0.2)
plt.axvspan(0, 0.1, color='gray', alpha=0.2)
plt.axvspan( plt.show()
On voit dans chaque graphique que les premiers 10\% de la trajectoire correspondent à la trajectoire précédente compressée (zones grisées). Le caractère discret est bien visible sur les deux premières trajectoires, puis on ne le distingue plus à l’œil sur les dernières.
Un modèle de processus plus avancé
On veut simuler les trajectoires d’un actif risqué (S_t)_{0\leq t\leq 1} suivant le modèle de Black et Scholes. Sa dynamique est définie de la façon suivante S_t=\exp\big(\mu t-\frac{\sigma^2}{2}t+\sigma B_t\big),\qquad 0\leq t\leq1. Le paramètre \mu s’appelle la dérive et le paramètre \sigma la volatilité. Pour simuler (S_t) on va utiliser le simulateur de mouvement Brownien de la question précédente.
- Simuler une trajectoire du mouvement Brownien avec un pas de discrétisation de N=10\ 000. En utilisant uniquement ce même tirage pour tous jeux de paramètres, tracer sur un même graphique les trajectoires d’un actif risqué (S_t)_{0\leq t\leq 1} qui évolue suivant le modèle de Black et Scholes pour chacun des jeux de paramètres suivants:
\sigma=10\% et \mu=0\%, \mu=1\%, \mu=5\%, \mu=10\%, \mu=20\%, \mu=50\%.
\mu=20\% et \sigma=1\%, \sigma=2\%, \sigma=5\%, \sigma=10\%, \sigma=15\%, \sigma=20\%
Solution
# Generate a random walk with 10,000 steps
= marche(0, 10000)
S
# Calculate the scaled random walk
= S / np.sqrt(10000) B
# Define parameters
= 0.1
sigma = [0, 0.01, 0.05, 0.1, 0.2, 0.5]
mu_values = np.linspace(0, 1, 10001)
time
# Calculate Brownian motion paths with different mu values
= []
BS_m for mu in mu_values:
- sigma**2 / 2) * time + sigma * B))
BS_m.append(np.exp((mu
# Plot Brownian motion paths
plt.figure()for i, mu in enumerate(mu_values):
=f'mu={mu}')
plt.plot(time, BS_m[i], label
f'Brownian Motion Paths with sigma={sigma}')
plt.title('Time')
plt.xlabel('Value')
plt.ylabel(
plt.legend()True)
plt.grid( plt.show()
Solution
Deuxième jeux de paramètres
# Define parameters
= 0.2
mu = [0.01, 0.02, 0.05, 0.1, 0.15, 0.2]
sigma_values = np.linspace(0, 1, 10001)
time
# Calculate Brownian motion paths with different mu values
= []
BS_s for sigma in sigma_values:
- sigma**2 / 2) * time + sigma * B))
BS_s.append(np.exp((mu
# Plot Brownian motion paths
plt.figure()for i, sigma in enumerate(sigma_values):
=f'sigma={sigma}')
plt.plot(time, BS_s[i], label
f'Brownian Motion Paths with mu={mu}')
plt.title('Time')
plt.xlabel('Value')
plt.ylabel(
plt.legend()True)
plt.grid( plt.show()
- Quel est l’effet des changements de dérive et de volatilité sur l’aspect des trajectoires? Comment l’expliquer ?
Solution
On constate que la dérive correspond à la “pente” de la trajectoire : plus elle est élevée, plus la trajectoire monte, sans influencer les fluctuations. La volatilité correspond à l’intensité de fluctuations, plus elle est élevée, plus les fluctuations à la hausse où à la baisse sont importantes.