Equipes de tesouraria, investidores e gestores de risco raramente precisam saber o preço de um ativo no ano que vem. Precisam conhecer a faixa: quanto ele poderia subir, quanto poderia cair e qual a probabilidade de cada resultado. A simulação de Monte Carlo responde a essa pergunta gerando milhares de trajetórias de preço possíveis e lendo a distribuição dos resultados.

O modelo mais comum por trás dessas trajetórias é o movimento browniano geométrico (GBM). Ele supõe que os preços se movem aleatoriamente em torno de uma tendência, descrita por dois parâmetros: a deriva, a taxa média com que o preço muda, e a volatilidade, o quanto ele oscila em torno dessa tendência. Também supõe que os retornos logarítmicos seguem uma distribuição normal.

Para mostrar como funciona, simulamos o preço da ação da Apple de 2021 a 2024 e comparamos as trajetórias simuladas com o que de fato aconteceu.

Primeiro método: a fórmula de Black-Scholes

O framework de Black-Scholes supõe retornos log-normais, o que dá a expressão padrão do preço no instante t:

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

Aqui μ é a deriva, σ a volatilidade e W(t) um movimento browniano padrão. O termo -0.5 * σ² corrige o arrasto da volatilidade, e faz parte da fórmula.

O código abaixo estima a deriva e a volatilidade a partir dos retornos diários da Apple e simula 1.000 trajetórias.

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)
Método de Black-Scholes: 1.000 trajetórias de preço simuladas (cinza) comparadas ao preço real da Apple (vermelho)
Método de Black-Scholes: 1.000 trajetórias de preço simuladas (cinza) comparadas ao preço real da Apple (vermelho)

Segundo método: modelar diretamente os retornos logarítmicos

Se os retornos são log-normais, seus logaritmos são normais, e podem ser simulados com um movimento browniano padrão e depois convertidos de volta em preços. É o mesmo modelo visto de outro ângulo, e muitas vezes é mais fácil de explicar.

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)
Método dos retornos logarítmicos: o mesmo experimento gera trajetórias praticamente idênticas
Método dos retornos logarítmicos: o mesmo experimento gera trajetórias praticamente idênticas

O que a comparação mostra

Os dois métodos produzem distribuições praticamente idênticas, o que confirma que são dois caminhos válidos para o mesmo modelo. Para quem decide, o valor não está nas trajetórias individuais, mas na faixa que elas descrevem: a banda em que o preço provavelmente vai se mover e a probabilidade de chegar a um nível que prejudicaria o negócio.

BS

Bartor S.

Fundador

Todos os insights