En este artículo implementamos de forma sencilla una simulación de Monte Carlo de precios de acciones con movimiento browniano geométrico (GBM), explicando la lógica de fondo para que pueda ejecutarla correctamente.

En finanzas matemáticas, un activo suele modelarse como un movimiento browniano geométrico, es decir, su precio obedece una ecuación diferencial estocástica (EDE). El GBM supone que el precio sube y baja al azar, pero con una tendencia general a subir o bajar con el tiempo. Lo logra con dos ingredientes: qué tan rápido cambia el precio en promedio (la deriva) y cuánto salta al azar (la volatilidad). Además, supone que los rendimientos logarítmicos del activo siguen una distribución normal.

Para este ejemplo usamos el precio de la acción de Apple y ejecutamos una simulación de Monte Carlo con GBM sobre el mismo período. Luego graficamos las simulaciones junto con la trayectoria real de la acción.

Dos formas de modelar el GBM

1. El enfoque de Black-Scholes

El marco de Black-Scholes supone que los rendimientos de un activo siguen una distribución log-normal. Al aplicar las matemáticas se obtiene la fórmula estándar del precio del activo:

S(t) = S(0) * exp((μ - 0.5 * σ²) * t + σ * W(t))

Aquí μ es la deriva (el rendimiento promedio anualizado de la acción), σ es la volatilidad (la desviación estándar de los rendimientos) y W(t) es un movimiento browniano estándar. El término -0.5 * σ² es una corrección por el efecto de “arrastre” en los rendimientos, y ya viene incluido en la fórmula.

Simulación de Monte Carlo con GBM para la acción de Apple (2021-2024)

Pasemos a la práctica. El siguiente código simula el precio de Apple de 2021 a 2024 en Python.

import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt

apple = yf.download("AAPL", start="2021-01-01", end="2024-01-01")
apple.columns = apple.columns.levels[0]
price = apple.Close
returns = price.pct_change().dropna()

t = len(returns)           # number of daily steps
dt = 1                     # one trading day per step
mu = returns.mean()        # drift
sigma = returns.std()      # volatility
simulations = 1000
S0 = price.iloc[0]

def gbm_paths(mu, sigma, W):
    return np.exp((mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * W)

Ws = np.random.standard_normal(size=(simulations, t))
gbm = gbm_paths(mu, sigma, Ws)
gbm = np.insert(gbm, 0, S0, axis=1).cumprod(axis=1)

x_axis = range(0, t + 1)
fig, ax = plt.subplots(figsize=(12, 5.5))
for path in gbm:
    ax.plot(x_axis, path, color="grey", linewidth=0.1)
ax.plot(x_axis, price, color="red", linewidth=1)
Enfoque de Black-Scholes: 1.000 trayectorias de precio simuladas (gris) frente al precio real de Apple (rojo)
Enfoque de Black-Scholes: 1.000 trayectorias de precio simuladas (gris) frente al precio real de Apple (rojo)

2. El enfoque de transformación logarítmica

Si los rendimientos son log-normales, basta con tomar el logaritmo de los rendimientos. Tras esa transformación, los datos pueden modelarse con un movimiento browniano estándar. Se llega al mismo modelo de fondo, visto desde otra perspectiva matemática.

log_returns = np.log(returns + 1)
mu_log = log_returns.mean()
sigma_log = log_returns.std()

def bm_paths(mu, sigma, W):
    return mu + sigma * W

bm = bm_paths(mu_log, sigma_log, Ws)
bm = S0 * np.exp(bm.cumsum(axis=1))
bm = np.insert(bm, 0, S0, axis=1)

fig, ax = plt.subplots(figsize=(12, 5.5))
for path in bm:
    ax.plot(x_axis, path, color="grey", linewidth=0.1)
ax.plot(x_axis, price, color="red", linewidth=1)
Enfoque de transformación logarítmica: el mismo experimento da trayectorias prácticamente idénticas
Enfoque de transformación logarítmica: el mismo experimento da trayectorias prácticamente idénticas

Comparación de ambos resultados

Los dos gráficos son prácticamente idénticos. Con rendimientos logarítmicos perfectamente normales convergen al mismo resultado, lo que confirma que ambos métodos son formas válidas de ejecutar una simulación de Monte Carlo con movimiento browniano geométrico.

BS

Bartor S.

Fundador

Todos los artículos