Pagar sobre a média
Um call padrão depende do preço de um só dia, o último. Uma opção asiática depende do preço médio em um conjunto de datas: um call asiático paga max(média - K, 0). As empresas as usam para proteger um custo que têm continuamente, como uma compra mensal de petróleo, e são difíceis de manipular no vencimento. São *dependentes da trajetória*, então não há fórmula simples de Black–Scholes para a média aritmética, e a ferramenta usual é a simulação de Monte Carlo.
import numpy as np
# Two simulated paths: the starting price, then monthly prices; the last column is expiry
paths = np.array([[100.0, 90.0, 110.0, 130.0],
[100.0, 70.0, 80.0, 90.0]])
average = paths[:, 1:].mean(axis=1) # the monitoring dates only, not the starting price
print(average) # [110. 80.]
print(np.maximum(average - 100.0, 0.0)) # Asian call payoffs: [10. 0.]
print(np.maximum(paths[:, -1] - 100.0, 0.0)) # European call payoffs on the same paths: [30. 0.]Simular as trajetórias
As trajetórias vêm do movimento browniano geométrico, com a deriva neutra ao risco: a taxa r substitui mu. Sorteia-se uma matriz de normais padrão com uma linha por trajetória e uma coluna por data de observação, converte-se em movimentos do log do preço e faz-se uma soma acumulada ao longo de cada linha. Um só array contém então todas as trajetórias, e cada passo seguinte (médias, pagamentos) é uma operação vetorizada pelas linhas, sem laço sobre trajetórias.
import numpy as np
def simulate_paths(s0, rate, sigma, t, steps, n_paths, rng):
dt = t / steps
z = rng.standard_normal((n_paths, steps))
log_moves = (rate - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * z
return s0 * np.exp(np.hstack([np.zeros((n_paths, 1)), np.cumsum(log_moves, axis=1)]))
rng = np.random.default_rng(1)
paths = simulate_paths(100.0, 0.05, 0.2, 1.0, 12, 50000, rng) # monthly monitoring for a year
print(paths.shape) # (50000, 13)
print(round(float(paths[:, -1].mean()), 2), round(100 * np.exp(0.05), 2)) # the risk-neutral mean of the final priceO preço e sua barra de erro
O preço da opção é o pagamento médio descontado: exp(-r * T) * mean(payoffs). Um preço Monte Carlo é uma estimativa, então reporte sempre o erro padrão, std(payoffs) / sqrt(número de trajetórias) (descontado), que diz quanto o número pode estar longe da verdade: quatro vezes mais trajetórias o reduzem à metade. Um call asiático é mais barato que um europeu sobre a mesma ação, porque a média suaviza o preço e reduz a volatilidade efetiva.
import numpy as np
def simulate_paths(s0, rate, sigma, t, steps, n_paths, rng):
dt = t / steps
z = rng.standard_normal((n_paths, steps))
log_moves = (rate - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * z
return s0 * np.exp(np.hstack([np.zeros((n_paths, 1)), np.cumsum(log_moves, axis=1)]))
def asian_price(paths, strike, rate, t):
payoff = np.maximum(paths[:, 1:].mean(axis=1) - strike, 0.0)
discount = np.exp(-rate * t)
return discount * payoff.mean(), discount * payoff.std(ddof=1) / np.sqrt(len(payoff))
rng = np.random.default_rng(1)
paths = simulate_paths(100.0, 0.05, 0.2, 1.0, 12, 100000, rng)
price, error = asian_price(paths, 100.0, 0.05, 1.0)
european = np.exp(-0.05) * np.maximum(paths[:, -1] - 100.0, 0.0).mean()
print(round(float(price), 3), "+/-", round(float(error), 3))
print(round(float(european), 3), "European call on the same paths")# Geometric and arithmetic averages of the same monitoring prices
import numpy as np
prices = np.array([90.0, 110.0, 130.0])
arithmetic = prices.mean()
geometric = np.exp(np.log(prices).mean())
print(round(float(arithmetic), 3), round(float(geometric), 3)) # 110.0 108.774: the geometric average is never larger- Uma opção asiática paga sobre a média das datas de observação:
max(média - K, 0); dependente da trajetória, então sem fórmula simples e Monte Carlo é a ferramenta. - Simule todas as trajetórias em um array (linhas = trajetórias, colunas = datas) com a deriva neutra ao risco; médias e pagamentos ficam vetorizados pelas linhas.
- Preço =
exp(-r * T) * mean(payoffs)com erro padrãostd / sqrt(paths); a média o torna mais barato que um call europeu, e a versão geométrica é uma variável de controle.
A seguir: as opções com barreira, que nascem ou morrem quando o preço toca um nível.
Lab: o que é avaliado
- Fazer a média ao longo de cada trajetória com
average_price25 pts - Experimentar a média geométrica com
geometric_average25 pts - Pagar sobre a média com
asian_call_payoff25 pts - Precificá-la, com barra de erro, com
asian_price25 pts