Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como usar simulações do Modelo Browniano Geométrico para apreçar um contrato de opção Europeia?

+2 votos
215 visitas
perguntada Nov 5, 2016 em Finanças por Caue (226 pontos)  

Discuta os detalhes, implemente o programa em Python e compare o resultado com o valor teórico dado pela fórmula de Black-Scholes para vários níveis de aproximação.

Compartilhe

1 Resposta

+3 votos
respondida Nov 8, 2016 por Caue (226 pontos)  
selecionada Nov 8, 2016 por Caue
 
Melhor resposta

1 - Movimento Browniano Geométrico

Um processo estocástico \(S(t)\) é Movimento Browniano Geométrico - MBG quando \(log S(t)\) é um Movimento Browniano - MB com valor inicial \(logS(0)\).

O MBG é utilizado para modelar o preço de ações, visto que o retorno dos preços é um MB.
Destaca-se que enquanto o retorno das ações pode assumir valores negativos, o preço das ações deve ser sempre positivo, o que é característica do MBG, pois a função exponencial assume apenas valores positivos.

O MBG pode ser representado em forma de equação diferencial estocástica:

\[ \frac{dS(t)}{S(t)} = \mu dt + \sigma dW(t) \]

com \(W\) representando o Movimento Browniano padrão.

A solução da equação diferencial acima é:

\[ S(t)=S(0)e^{(\mu-\frac{\sigma^2}{2})t+\sigma W(t)} \]

Portanto, para simular o caminho dos preços, utilizaremos a seguinte equação recursiva:

\[ S(t_{i+1})=S(t_{i})exp[(\mu-\frac{1}{2}\sigma^2)(t_{i+1}-t_{i})+\sigma\sqrt{t_{i+1}-t_{i}}Z_{i+1}] \\ i = 0,1,2,...,n-1 \\ \text{Sendo } Z_{1},Z_{2},...,Z_{n} \text{ variáveis aleatórias}\\ \text{independentes com distribuição normal padronizada.} \]

Na implementação, utilizaremos a seguinte notação:

\((t_{i+1}-t_{i} )\rightarrow dt\)
\( n \rightarrow number\_steps \)
\( number\_steps * dt = time\_to\_expiration \)

2 - Precificação de Opções

Como o valor da opção é determinado na data (futura) de seu vencimento, para encontrar o preço na data atual devemos trazer para valor presente o valor esperado da opção. Seguiremos então os seguintes passos:

  1. Gerar vários caminhos do preço da ação, da data atual até a data de vencimento da opção;
  2. Calcular, para cada caminho, o valor da opção na data do vencimento, de acordo com o preço final da ação;
  3. Fazer a média entre todos os valores calculados;
  4. Trazer a valor presente a média (valor esperado) dos valores calculados;
  5. Este valor presente é o preço da opção na data atual.

3 - Taxa Livre de Risco

Assumimos que existe uma taxa de juros (com capitalização contínua), dada por \(r\), com a qual é possível tomar emprestado ou investir, sem risco.
Com investidores neutros ao risco, todos os ativos devem ter a mesma taxa média de retorno.
Portanto, com uma medida neutra ao risco, devemos ter \(\mu = r\) nas equações apresentadas e poderemos trazer o preço das opções a valor presente utilizando também a taxa livre de risco \(r\).
Na simulação, consideramos a taxa livre de risco como 14% ao ano, de acordo com a Taxa Selic em vigor.

4 - Implementação

A simulação foi implementada em Python 3.5.1 e disponibilizada em um arquivo do tipo Jupyter Notebook para melhor visualização.
Foram obtidos os preços de fechamento diário de quatro ativos negociados na Bovespa através do Google Finance.
A partir dos preços, calculou-se os retornos diários e a matriz de covariância destes retornos.
Foi necessário definir as características das opções, como o tipo (call ou put), os preços de exercício (strike) e o dia do vencimento, 19 de dezembro de 2016. A data inicial da simulação é o dia 4 de novembro de 2016.

A imagem será apresentada aqui.

A imagem será apresentada aqui.

5 - Simulação de Monte Carlo

Para simular o caminho de cada ação, foram gerados valores seguindo uma distribuição normal com média 0 e desvio padrão \(\sigma\) específico de cada ação.
Considerou-se, também, a correlação entre cada ação na geração dos valores. Assim, o caminho do preço das ações estará mais próximo do esperado pelo mercado.
É necessário definir duas variáveis para a simulação: O número de passos em cada simulação, e o número total de simulações:

  • O número de passos definido será utilizado para calcular o tamanho do
    passo \((t_{i+1}-t_{i} )\), chamado de \(dt\).
  • O número total de simulações, ou o número total de caminhos para cada ativo, é decisivo para o cálculo da média dos preços finais. Caso o número seja pequeno, os preços calculados podem não corresponder ao esperado.

A imagem será apresentada aqui.

6 - Equação de Black-Scholes

Por fim, implementou-se a equação de Black-Scholes para conferir o resultado da simulação.

\[ \text{call: } C = S.N(d1) - Ke^{-rT}.N(d2) \\ \text{put: } P = Ke^{-rT}.N(-d2) - S.N(-d1) \\ d1 = \frac{ log(\frac{S}{K}) + (r + \frac{\sigma^2}{2})T}{\sigma\sqrt{T}} \\ d2 = \frac{ log(\frac{S}{K}) + (r - \frac{\sigma^2}{2})T}{\sigma\sqrt{T}} \]

Para uma simulação com 100 mil caminhos, os valores calculados foram idênticos. Com um número de caminhos igual a 100, houve preço com diferença de mais de 20%.

A imagem será apresentada aqui.

7 - Conclusões

Quando assumimos que o preço de um ativo segue um Movimento Browniano Geométrico, podemos utilizar a equação de Black-Scholes para precificar uma opção Européia desse ativo, pois a equação nos fornecerá um valor mais preciso em menos tempo.
A simulação, porém, é imprescindível para modelar diversas outras situações nas quais a equação de Black-Scholes não atende. Alguns exemplos:

  1. Quando o preço da opção depende da trajetória do preço do ativo, como as opções asiáticas;
  2. Quando o preço segue um caminho descontínuo, com saltos;
  3. Quando o desvio padrão do retorno não é constante (\(\sigma = \sigma(t)\)).

Arquivo com a Implementação: Link

Referência: Monte Carlo Methods in Financial Engineering, de Paul Glasserman.

comentou Nov 13, 2016 por Saulo (426 pontos)  
Resposta excelente!

- A parte teórica está muito boa. Sucinta e completa.
- O código-fonte está muito bem escrito, que facilita a leitura e compreensão.
- As conclusões demonstram conhecimento e trazem contribuições valiosas.

Seguem alguns comentários para ajudar a quem interessar:

- Na seção 1, usando sua equação diferencias estocástica, pelo Lema de Itô, pode-se escrever:

d(ln(S(t))) = (mu - sigma^2/2)*dt + sigma*dW(t)

E, usando a aproximação de Euler, chega-se na sua equação recursiva. Essa observação facilita essa derivação.

- Com relação ao código-fonte:
  * Na seção 4, você menciona que executou em Python 3.5.1. Só de curiosidade, eu tentei executar em Python 2.7, mas não consegui. Depois eu executei com sucesso em Python 3.5.2. Portanto, o código funciona apenas com Python 3.
  * A anualização foi feita considerando-se 252 dias.
  * No método "monte_carlo_simulation": (i) Na teoria, você usou a variável Z com variância 1. Na simulação, você usou a matriz de covariância na geração do Z e desconsiderou a multiplicação pelo sigma na equação de diferenças, que é uma abordagem interessante para simular que existe correlação entre os ativos; (ii) a variável "path" retornada corresponde a S(t)/S(0) da última simulação.
  * Nos seus ifs de call e put que você essencialmente multiplica por -1, e muito comum fazer isso multiplicando por (-1.0)**(int(type[idx] == 'call')-1.0), que dá o mesmo efeito do if. Mas a sua solução é muito mais clara e didática. Eu só mencionei isto para fins de aprendizagem de quem está lendo.

Segue minha dúvida, que acho que é interessante deixar o registro:
- No código-fonte, como foi feita a escolha do preço de exercício (strike)? Os preços de strike no código-fonte são [18.12, 16.00, 18.34, 39.74].

Parabéns pelo post! Excelente!
comentou Nov 17, 2016 por Caue (226 pontos)  
editado Nov 17, 2016 por Caue
Obrigado pelos comentários, Saulo.

Alguns esclarecimentos:

* O código é compatível com Python 3.  Para visualizar as principais diferenças entre as duas versões, indico o seguinte link: http://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html
* Para a anualização, é comum considerar 252 dias de negociação em um ano.
* A variável Z representa uma variável aleatória que segue uma distribuição normal padronizada, Z ~ N(0,1). Porém, na solução, ela aparece multiplicada por sigma. Assim, podemos definir uma variável Z' = sigma * Z, de forma que Z' ~ N(0, sigma). No código, ao utilizar o método np.random.multivariate_normal passamos a média desejada 0 e a matriz de covariância, que inclui o sigma. Ou seja, multivariate_normal retorna a Z'.
* A variável path corresponde a S(t)/S(0) para que seja melhorada a visualização do caminho dos preços (ajuste de escala).

Quanto ao critério de escolha das opções:

* Selecionei duas puts e duas calls, com o objetivo de verificar a precificação para os dois tipos de contrato.
* Foi escolhido o vencimento de dezembro de 2016, para ter um período maior para a simulação.
* Relativo ao strike, escolhi as opções com maior volume de negociação no mercado no dia da simulação. Como os preços variam, essas opções podem ser pouco negociadas atualmente (ou não mais negociadas, caso a data seja igual ou superior ao vencimento, 19/Dez/16).

Para executar o código fonte, sugiro baixar o arquivo .ipynb
e executar de acordo com o seguinte tutorial:
http://jupyter.readthedocs.io/en/latest/running.html#running
...