universidade estadual de campinas faculdade de …lotavio/tgs/2014... · 2016-05-05 · e é claro...
TRANSCRIPT
UNIVERSIDADE ESTADUAL DE CAMPINAS
FACULDADE DE ENGENHARIA MECÂNICA
Relatório Parcial Trabalho de Conclusão de Curso
Aceleração do tempo execução de cálculos financeiros utilizando
GPUs
Autor: Fernando Teruo Maeji Ishikawa
Orientador: Prof. Dr. Luiz Otávio Saraiva Ferreira
Campinas, outubro de 2014
2
UNIVERSIDADE ESTADUAL DE CAMPINAS
FACULDADE DE ENGENHARIA MECÂNICA
Relatório Parcial Trabalho de Conclusão de Curso
Aceleração de tempo execução de cálculos financeiros utilizando
GPUs
Autor: Fernando Teruo Maeji Ishikawa
Orientador: Prof. Dr. Luiz Otávio Saraiva Ferreira
Curso: Engenharia de Controle e Automação
Trabalho de conclusão de curso apresentado à Comissão de Graduação da Faculdade
de Engenharia Mecânica, como requisito para a obtenção do título de Engenheiro de
Automação e Controle
Campinas, 2014
S.P. - Brasil
3
Agradecimentos
Este trabalho não teria sido iniciado e muito menos chego neste ponto sem o auxílio,
ajuda, broncas e compreensão de várias pessoas, presto minha homenagem a elas:
Prof. Dr Luis Otávio Saraiva Ferreira por ser guia, orientador e revisor deste
documento.
Aos membros da Comissão de Graduação do curso de Engenharia de Controle e
Automação da FEM/Unicamp.
Prof. Dr. Niederauer Mastelari, coordenador do curso de Engenharia de Controle e
Automação, a quem devo a possibilidade de realizar e entregar este documento.
Aos amigos com quem morei e pude conhecer e ver em várias fases da vida de cada
um. Amigos que sempre terei com muito orgulho e que sei que mesmo estando fisicamente
separados agora, sempre nos veremos e será como se ainda moramos e nos vemos todos os
dias.
A ABEUNI que me propiciou amigos, histórias, aventuras, viagens e sentimentos que
tenho certeza não encontrarei em nenhum outro local.
A MAPS S.A., empreso na qual faço parte a 3 anos, onde devo muito as pessoas e a
empresa pelo crescimento profissional, pelo conhecimento adquirido, pelas pessoas que
conheci e pelos amigos que conquistei. Além da compreensão e suporte para concluir este
trabalho e o curso.
E é claro a minha família, que esteve sempre do lado, nos problemas, nos momentos
de alegria, nas brigas, na maior tristeza que já senti e por tudo que me propiciou até o dia de
hoje, que tenho certeza não teria condições de alcançar sem o suporte e o preparo que me
deram. Muito obrigado Mãe por se sacrificar sempre pelos filhos, abdicando de tudo que fosse
pessoal pela felicidade e satisfação minha e dos irmãos. Ni, Nessa e Lipe (in memoriam) pelas
muitas brigas e amadurecimento que tivemos, pelo suporte, pelo aprendizado que tive com
vocês, pelas alegrias, tristezas e mudanças que fizeram em minha vida. As minhas tias, que na
ausência da mãe, foram as responsáveis pela minha educação, saúde e equilíbrio, assumindo
uma responsabilidade muito grande quando não precisariam, posso dizer que tenho mais de
uma mãe por causa de vocês!
4
Sumário
RESUMO ................................................................................................................................... 6
LISTA DE FIGURAS .................................................................................................................... 7
LISTA DE TABELAS .................................................................................................................... 7
ABREVIAÇÕES ........................................................................................................................... 7
SIGLAS ...................................................................................................................................... 7
1. MERCADO FINANCEIRO ..................................................................................................... 9
1.1. SISTEMA FINANCEIRO NACIONAL E SISTEMA DE PAGAMENTOS BRASILEIRO .................................... 9
1.2. NEGOCIAÇÃO E BOLETAGEM DE OPERAÇÕES ........................................................................... 10
1.3. INSTRUMENTOS FINANCEIROS: TÍTULOS E VALORES MOBILIÁRIOS ................................................ 11
1.3.1. RENDA FIXA .................................................................................................................. 11
1.3.2. RENDA VARIÁVEL - AÇÕES ............................................................................................... 12
1.3.3. COTAS DE FUNDOS ......................................................................................................... 13
1.4. INSTRUMENTOS FINANCEIROS: DERIVATIVOS .......................................................................... 13
1.4.1. TERMOS ....................................................................................................................... 14
1.4.2. FUTUROS...................................................................................................................... 14
1.4.3. SWAP .......................................................................................................................... 15
1.4.4. OPÇÕES ....................................................................................................................... 16
1.4.5. COE ............................................................................................................................ 19
2. TECNOLOGIA MAPS: JMINE E LUNA ................................................................................. 20
3. PRECIFICAÇÃO DE DERIVATIVOS: OPÇÕES ....................................................................... 21
3.1. TAXAS E CONVENÇÃO DE CONTAGEM DE DIAS ......................................................................... 22
3.2. CURVAS E INTERPOLAÇÃO ................................................................................................... 23
3.3. VOLATILIDADE .................................................................................................................. 25
3.3.1. VOLATILIDADE IMPLÍCITA ................................................................................................. 25
3.4. PRECIFICAÇÃO DE OPÇÃO DE AÇÃO POR BJERKSUND AND STENSLAND ......................................... 25
4. GPU´S E PLATAFORMAS DE COMPUTAÇÃO PARALELA .................................................... 27
4.1. OPENCL .......................................................................................................................... 28
4.2. CUDA ............................................................................................................................ 28
5. MÉTODO DE AVALIAÇÃO E COMPARAÇÃO ..................................................................... 29
5
6. ALGORITMO DE CÁLCULOS EM JAVA ............................................................................... 29
6.1. CLASSE DE CONTEXTO DE PRECIFICAÇÃO: ............................................................................... 29
6.2. CLASSE DE CÁLCULO DE FUNÇÃO NORMAL .............................................................................. 31
6.3. CLASSE QUE REPRESENTA UM VALOR DE MERCADO MÉDIO DAS OPÇÕES ....................................... 32
6.4. CLASSE QUE REPRESENTA UMA VOLATILIDADE DA OPÇÃO .......................................................... 33
6.5. CLASSE QUE CONSOLIDA E AGREGA UMA CALCULADORA DE OPÇÃO ............................................. 34
6.6. CLASSE QUE REALIZA A PRECIFICAÇÃO, CONSIDERANDO CENÁRIO ................................................ 38
7. CONCLUSÃO .................................................................................................................... 39
8. BIBLIOGRAFIA .................................................................................................................. 43
6
Resumo
ISHIKAWA, Fernando T. Maeji, Aceleração de tempo execução de cálculos financeiros
utilizando GPUs. Faculdade de Engenharia Mecânica, Universidade Estadual de Campinas.
Trabalho de conclusão de curso. 2014.
Este trabalho tem a finalidade de apresentar os resultados da comparação do tempo de
execução de algoritmos para cálculos de precificação de derivativos negociados no mercado
financeiro, inicialmente utilizando linguagem de programação Java e em seguida adaptando-o
para utilização de framework, bibliotecas e APIs com compatibilidade de linguagem CUDA.
Inicialmente iremos dar uma breve introdução sobre o mercado financeiro, em relação a
negociação, ativos e sua importância, além de mostrar o impacto que este nicho gera em
outras áreas de estudo.
A demonstração será evidenciada através da apresentação dos algoritmos de cálculos nas
duas versões e com a coleta e análise do tempo de execução, utilizando ferramentas
adequadas, da diminuição e efetividade das GPUs.
Palavras Chave: GPUs, Opções, Derivativos, Mercado Financeiro, Cálculo, Precificação.
7
Lista de Figuras Figura 2-1 Exemplo de evolução de um ativo de renda fixa
Figura 2-2 Representação de um contrato de swap
Figura 2-3 Representação de compra de call
Figura 2-4 Representação de venda de call
Figura 2-5 Representação de trava de alta (Bull Spread)
Figura 2-6 Representação de trava de baixa (Bear Spread)
Figura 3-1 Hierarquia de camadas do Jmine
Figura 4-1 Curva PRE_DI1_BMF construída no Nave
Lista de Tabelas Tabela 4-1 Parâmetros da curva PRE_DI1_BMF
Tabela 7-1 Tempo de execução do algoritmo em Java
Tabela 7-2 Tempo de execução utilizando JCuda
Abreviações PU Preço Unitário
Mtm Market-to-Market
Siglas SFN Sistema Financeiro Nacional
RSFN Rede do Sistema Financeiro Nacional
SPB Sistema de Pagamentos Brasileiro
BNDES Banco Nacional de Desenvolvimento Econômico e Social
DOC Documento de Ordem de Crédito
TED Transferência Eletrônica Disponível
IPCA Índice de Preços ao Consumidor – Amplo
IGPM Índice Geral Preços – Mercado
CDI Certificado de Depósito Interbancário
CDB Certificado de Depósito Bancário
LF Letra Financeira
CRI Certificado de Recebível Imobiliário
8
NTN-B Notas do Tesouro Nacional – Série B
GPU Graphics Processing Unit
CUDA Compute Unified Device Architecture
9
1. Mercado Financeiro
Por vários aspectos econômicos locais, no Brasil, uma das áreas que anualmente sempre
obtém crescimento, e invariavelmente tem oferta de empregos sempre aquecida é a bancária.
As instituições financeiras representam e movimentam um valor considerável da riqueza
nacional, uma consequência direta é que áreas correlatas e que prestam serviços a estas
instituições normalmente possuem bons fluxos de caixa. Iremos comentar de forma breve a
divisão do sistema financeiro nacional e o modo que estas instituições normalmente captam
recursos.
1.1. Sistema Financeiro Nacional e Sistema de Pagamentos Brasileiro
O Sistema Financeiro Nacional – SFN – pode ser dividido em três grupos de agentes [1]:
Órgãos normativos – estabelece normas e regras a serem seguidas, Entidades supervisoras –
assegura que as normas vigentes sejam cumpridas e Operadores – realizam negociações,
captam recursos, liquidam e custodiam ativos. Iremos focar principalmente neste terceiro
grupo.
Os principais agentes que fazem parte deste grupo são:
Instituições financeiras: bancos múltiplos, caixa econômica federal, bancos comerciais,
bancos de investimento, bancos de desenvolvimento, BNDES, sociedades corretoras e
distribuidoras de títulos e valores mobiliários, sociedades de crédito em geral;
Bancos de câmbio;
Bolsas mercadorias, futuros e de valores;
Sociedades de capitalização;
Sociedades seguradoras;
Resseguradoras;
Entidades abertas e fechadas de previdência.
Estes agentes possuem formas diferentes de captação de recursos e movimentação de
dinheiro:
Captação de recursos à vista: depósitos bancários;
Captação de recursos a prazo: empréstimos bancários;
Cobrança de serviços: taxas de serviços, emissão de DOC/TED;
Negociação de títulos e valores mobiliários;
Negociação de derivativos.
Iremos nos aprofundar na forma de captação por negociação de títulos, valores
mobiliários e derivativos e explicar de forma rápida seu funcionamento, negociação,
rentabilidade e algumas regras básicas.
Títulos e valores mobiliários são instrumentos financeiros onde a captação está
vinculada a algum ativo em forma escritural, isto é, existe um contrato (escritura) que define
as características deste ativo. Algumas características que normalmente constam desta
escritura: nome do ativo, emissor, data de emissão, data de validade, local de pagamento,
responsável pelo pagamento, local de negociação, forma de remuneração entre outros. Para
10
referências futuras podemos chamar este ativo de papel, pois todas estas características estão
definidas em uma folha de papel e consolidadas digitalmente.
A negociação destes papeis consistia na troca de papeis de forma física entre duas
instituições e um outro documento que relatava a operação entre as duas partes. A troca
destes papeis (liquidação física) e a permuta por moeda correte (liquidação financeira),
concluíam a negociação. Atualmente todas estas transações e liquidações são realizadas de
forma on-line, em uma plataforma integrada e única chamada de SPB – Sistema de
Pagamentos Brasileiros [2]. O principal objetivo da criação desta plataforma em 2002 foi
redução de risco sistêmico devido a falha operacional, sonegação ou até mesmo falsificação
dos agentes que compõem o SFN.
Logo, para todos estes agentes conseguirem negociar entre si e exercerem lucros com
estas operações, eles obrigatoriamente devem ter uma plataforma eletrônica adequada para
comunicação com a rede que compõe o sistema financeiro nacional – RSFN – e acessar o SPB.
1.2. Negociação e boletagem de operações
Antes da existência do SPB, a troca de ativos era feita manualmente e existia um
documento que comprovava esta negociação (boleta), a liquidação financeira nos bancos era
feita de acordo com as informações contidas na boleta. Normalmente estas boletas possuem
informações de identificação e comprovação de operação, dada pela lista abaixo. Podem
existir outros parâmetros dependendo do papel e do local de negociação:
1) Parte: a instituição que está registrando esta boleta;
2) Contraparte: agente com quem estou realizando negócio
(comprador/vendedor);
3) Papel: ativo objeto desta negociação;
4) Data da negociação: data em que a operação foi realizada;
5) Data de liquidação: data de pagamento da boleta;
6) Preço unitário (PU): quanto vale um papel que está sendo negociado, não
representa um valor financeiro, geralmente número com 6 a 8 casas decimais.
7) Quantidade: número inteiro que representa a quantidade de papeis sendo
negociado por uma boleta.
8) Valor: total a ser liquidado por esta boleta, normalmente é a quantidade
multiplicado pelo PU. Mas dependendo do tipo de operação, podem existir
valores a mais que representam taxa de negociação, custos administrativos,
etc.
A negociação entre as duas partes possui como etapa crucial a determinação do PU, a
obtenção deste valor envolve variáveis e percepções de mercado do operador e a escolha
entre as diferentes metodologias de cálculo.
Como atualmente o registro destas operações é feita eletronicamente, para agilizar o
processo de negociação existem softwares que realizam o cálculo destes PU´s de acordo com
os parâmetros escolhidos pelo usuário.
11
1.3. Instrumentos financeiros: títulos e valores mobiliários
Já comentamos de forma breve o que são títulos e valores mobiliários[3], iremos
separar em diferentes categorias para falar sobre suas principais características e citar
exemplos de alguns instrumentos financeiros.
1.3.1. Renda fixa Dentre os ativos de renda fixa podemos citar: títulos públicos, debêntures, CDBs, LFs,
CRIs, entre outros. São chamados de renda fixa pois a precificação é feita de maneira contínua,
seguindo uma curva de valorização, desta maneira conseguimos prever com certa margem de
garantia o valor destes ativos em datas futuras, eles estão menos expostos a variações de
preço em curto espaço de tempo, devido a fatores econômicos diversos, como o período de
eleições, por exemplo. Para facilitar o entendimento, iremos exemplificar utilizando a imagem
abaixo (Figura 2-1).
Figura 2-1 - Exemplo de evolução de um ativo de renda fixa
Nesta imagem, temos um ativo que irá pagar em sua data de vencimento um
determinado valor (V), este valor será atualizado por um índice de inflação e é representado
por CM. Além disso, ele paga alguns cupons de juros com uma periodicidade, representado por
J1 a J4.
Realizar a precificação do ativo seria atribuir um valor considerado justo, segundo
determinada metodologia de cálculo, em uma data qualquer, por exemplo na data e. Algumas
formas de cálculo podem ser citadas:
Cálculo accrual exponencial ou linear em dias úteis
Cálculo accrual exponencial ou linear em dias corridos
Cálculo mtm utilizando curvas de projeção e desconto
Cálculo mtm utilizando curvas de projeção e taxas e curvas de desconto
Os cálculos para obtenção deste valor justo são considerados bastante simples neste
caso, podendo na maioria dos casos serem feitos em uma planilha, que não é a melhor
maneira devido a questões como histórico de alterações, valores passados, base de dados
entre outros.
12
O ganho/perda aferido com ativos de renda fixa podem provir de duas maneiras
distintas: venda do ativo ou mantendo ele até o final, recebendo juros, correções e o próprio
resgate na data de vencimento.
Mantendo até o vencimento
Considere que na posição indicada em t1, foi realizada uma compra de valor T1 do
ativo representado, se o comprador deseja manter esta posição até o vencimento, ele irá
receber um valor respectivo a J1+J2+J3+J4+V+CM. E o resultado, considerando o período da
compra até o vencimento seria a somatório do que foi recebido subtraído pelo valor de
compra.
Compra e venda de ativo
Caso ele queira realizar uma venda antes do vencimento do papel, supondo compra
em t1 (valor T1) e venda em t2 (valor T2), ele iria receber o respectivo ao pagamento de J1 e o
valor de venda (T2), subtraído pelo valor que ele considera justo para ele nesta data de venda
(P2). Desta forma o resultado entre a compra e a venda seria: J1+T2-P2
1.3.2. Renda variável - Ações Ações são partes de uma empresa, representam um determinado valor da companhia
em posse do acionista (pessoa que detêm a ação), podemos realizar diversas operações com
uma ação: compra, venda, aluguel e como ativo objeto em uma opção. Todas estas operações
são realizadas em uma bolsa de valores (BM&FBovespa, por exemplo) e são intermediadas por
uma corretora, seja um corretor que realiza as operações pelo acionista ou utilizando o
sistema de home-broker da corretora, estas operações podem ser consolidadas segundo os
critérios: corretora, data de operação e data de liquidação financeira, formando uma nota de
corretagem. Dentro do valor desta nota de corretagem, além das operações, constam custos
com corretagem e da bolsa de valores.
São chamados de renda variável pois seu valor sofre bastante oscilação em um curto
espaço de tempo, até mesmo durante o próprio dia. A determinação do valor da ação no
mercado é realizada de acordo com a cotação da ação, a cotação pode ser representada pela
média de negociações durante o dia ou o valor de fechamento do dia. Para o acionista, a
precificação desta ação é um pouco diferente e deve ser calculada levando em consideração os
valores da operação e custo associados à nota de corretagem.
Exemplificando: uma empresa realizou a compra de 10.000 ações (nome: XPTO),
pagando um valor unitário de R$5,00. Logo, o total desta compra é de: R$50.000,00, mas
associado a esta operação deve pagar um valor de 2% para a corretora e mais 1% para a bolsa
de valores. Então o total de nota de corretagem é de R$50.000,00 + R$1.000,00+R$500,00,
totalizando uma nota de corretagem de R$51.500,00, valor este que será debitado do
comprador.
Logo para o acionista o valor unitário de cada ação que ele irá deter será:
R$51500,00/10000, obtendo um valor de R$5,15, podemos chamar este valor obtido como
custo médio do estoque.
Supondo que esta ação XPTO se valorizou com o tempo e 2 anos depois a cotação dela
vale R$8,00. Para a empresa que realizou a compra o custo médio se manteve (supondo que
não ocorreram outras compras), mesmo com a cotação sendo de R$8,00. Caso ele queira
realizar a venda com o valor da cotação, ele irá ter uma nota de corretagem de R$77.600,00 –
13
valor da operação descontado os custos de corretagem e da bolsa -, valor que será creditado
para o correntista. E o valor em estoque para esta empresa será de R$0,00, mas tendo um
lucro devido à operação de R$26.100,00.
O caso citado são operações de compra/venda à vista, temos outras operações que
possuem custos de corretagem e bolsa diferentes, como por exemplo: compra/venda day-
trade, compra/venda a termo e aluguel de ações.
1.3.3. Cotas de fundos Fundos podem ser considerado com uma grande “vaquinha” onde reunimos recursos
para aplicação em um investimento, possuem gestores qualificados para realizar a
administração e gestão do fundo, definindo estratégia de investimentos, realizando a compra
e venda de ativos em nome do fundo, cada um dos membros deste fundo são chamados de
cotistas e possuem um direito em relação ao valor deste fundo de acordo com o montante
aplicado. Cada uma destas partes a que o cotista tem direito é chamado de cota.
Para o cotista saber o valor desta cota, são divulgados diariamente a cotação deste
fundo e para saber o montante total devemos simplesmente multiplicar este valor unitário
divulgado pela quantidade.
Exemplo: a empresa comprou uma quantidade de 2000 cotas de um fundo XPTO por
um valor unitário de R$10,00. O valor deste fundo é divulgado diariamente e sofre oscilação de
acordo com a composição dos ativos deste fundo. Para o caso de compra de cotas pelo banco,
o cotista pode pagar uma taxa de administração mensal e/ou um valor que será deduzido ao
realizar a venda destas cotas.
Uma outra forma de obter esta cotação é nos casos em que estas cotas são negociadas
em bolsa de valores, neste caso a cotação pode ser obtida como uma ação, através da média
de negociações ou do valor de fechamento.
A precificação da cota pelo gestor do fundo é realizada de maneira diferente, leva-se
em consideração o patrimônio do fundo e a quantidade de cotas.
Exemplo: o fundo XPTO foi fundado em 01/03/2014 com uma quantidade total de
20.000 cotas, cada uma destas cotas possui um valor inicial de R$5,00. O patrimônio do fundo
no dia 01/03/2014 será de R$100.000,00 que é o valor total em caixa arrecadado, com este
valor o fundo realiza investimento em imóveis, ações, renda fixa entre outros, dependendo da
sua característica. Um ano após a formação deste fundo, as valorizações obtidas destes
investimentos elevam o patrimônio para R$130.000,00. Logo a cotação deste fundo passa a ser
de: R$6,5.
Para saber a calcular o patrimônio deste fundo, o gestor deve saber o mínimo da
precificação dos ativos que compõem a carteira para determinar o aumento ou diminuição do
patrimônio. Há sistemas que realizam o cálculo de patrimônio destes fundos, realizando a
precificação de cada um dos ativos que compõem o fundo.
1.4. Instrumentos financeiros: derivativos
Derivativos[4] são instrumentos financeiros em forma de contrato onde o valor
principal deste contrato está vinculado/deriva a/de um outro ativo, este chamado de ativo
objeto. Mas o valor deste ativo objeto não é conhecido, de certa forma derivativos são apostas
14
feitas no mercado de acordo com a expectativa de um negociador. Fazendo uma analogia,
como exemplo: dois amigos de faculdade, um são paulino e outro corintiano, resolvem fazer
uma aposta no início do torneio sobre quem seria o time campeão ao final do campeonato
brasileiro. Esta aposta representaria o contrato derivativo e o “ativo objeto” o time campeão,
ainda não conhecemos o valor no dia e o contrato é feito em expectativas.
Iremos citar alguns dos principais contratos derivativos negociados no mercado
atualmente, focando um pouco mais nos contratos de opções, que é o foco do trabalho
apresentado.
1.4.1. Termos Operações a termo são caracterizadas pela compra de um ativo hoje, por um valor
acordado entre as partes, mas esta operação será liquidada física e financeiramente, em uma
data futura, são utilizadas principalmente com a compra/venda de títulos de renda fixa e com
ações.
Um exemplo de operação a termo: um título de renda fixa possui um valor unitário de
R$10.150,00 na data 01/10/2014. Um negociador resolve fazer a compra de 12 títulos hoje,
mas a liquidação física (recebimento do ativo) e a liquidação financeira (entrega do dinheiro),
serão realizadas em 1 mês, no dia 03/11/2014 (próximo dia útil ao dia 01/11), por esta
operação o valor combinado foi de R$10.182,50. Mas neste dia 03/11/2014, o valor unitário
deste ativo foi calculado como R$10.182,00, ou seja caso tivesse sido deixado para comprar à
vista, 1 mês depois ele iria pagar R$0,50 mais barato por cada título.
Neste exemplo citado, o contrato derivativo é a compra a termo e o ativo objeto é o
ativo de renda fixa. Neste cenário, o negociador teve um prejuízo de R$6,00 em relação a uma
compra à vista na data futura, pois sua expectativa de mercado e valorização foi
superestimada.
1.4.2. Futuros Contratos futuros possuem algumas similaridades com as operações a termo, pois a
aposta é em relação a compra/venda de um ativo objeto em uma data futura, mas
diferentemente do termo não ocorre uma liquidação física, somente uma liquidação
financeira. As operações de futuro normalmente possuem como ativo objeto um índice,
moeda ou commodities.
No Brasil as operações de futuro são realizadas pela BM&FBovespa [5] e antes da fusão
pela BM&F (Bolsa de mercadoria e futuros), há diversas condições para operação no mercado
futuro, como margem de garantia, valor/quantidade mínima de compra/venda entre outros.
Além disso, como forma de segurança os valores do contrato possuem ajustes diário para
verificar se deve-se realizar parte do pagamento ou recebimento do valor do contrato. Estes
contratos negociados possuem um formato padrão de valor, quantidade e data e para saber
qual o tipo de contrato sendo negociado os nomes possuem uma nomenclatura do tipo FUT-
XYZ-K20. Sendo XYZ o ativo objeto e o radical o mês e ano de vencimento, sendo que cada mês
é representado por uma letra.
Um exemplo, o contrato de futuro com mnemônico FUT-DOL-M15, representa um
contrato futuro de Dólar com vencimento em junho de 2015, o tamanho deste contrato é de
US$50.000,00 e a liquidação financeira é dada na data de vencimento pela cotação do
dólar/real do dia anterior à data de vencimento. Ou seja, supondo que no dia 31/05/2015, um
15
dia antes do vencimento do contrato, a cotação de Real/Dolar (BRL/USD) seja de 2,22, neste
caso no dia do vencimento do contrato o valor em real será R$111.000,00.
Continuando com o caso acima, um fundo de investimento comprou 10 contratos de
futuros deste tipo, no dia 09/10/2014, a um valor unitário de R$2,35, ele tinha uma
expectativa de que o valor iria aumentar até a data de vencimento, neste dia ele deve
desembolsar uma quantia de R$1.175.000,00 correspondente ao PU, tamanho e quantidade
de contratos. No dia do vencimento ele receberia um valor de R$1.110.000,00, o que é feito de
fato pela BM&FBovespa são ajustes diários levando em consideração a variação do câmbio de
um dia para outro e realizando débitos/créditos diários. Isto é, caso a taxa de câmbio aumente
em 0,05 de um dia para outro ele iria receber o correspondente a R$25.000,00, caso ocorresse
uma diminuição de 0,05 na taxa de câmbio ele deveria pagar R$25.000,00. Estes ajustes são
realizados até a data de vencimento, quando ocorre a liquidação financeira e o fundo
receberia os R$111.000,00.
Os ajustes diários são efetivados como uma forma de proteção/garantia,
principalmente no caso de venda de contrato futuro por um participante da BM&FBovespa,
desta forma ela garante que a pessoa que fez a venda do contrato tenha o valor em caso de
aumento de cotação e não tenha problemas de não pagamento do contrato somente no
vencimento.
Os contratos de futuro mais comuns utilizados pelo mercado são futuros de CDI (FUT-
DI1), dólar (FUT-DOL), cupom cambial (FUT-DDI), SELIC (FUT-OC1), entre outros.
1.4.3. Swap Contratos de swap são caracterizados por ter dois ativos objetos e o valor de
liquidação do contrato é a diferença de rentabilidade entre estes dois ativos, estes dois ativos
objetos possuem a nomenclatura de ponta ativa e ponta passiva do contrato de swap e são
definidos na data de negociação do contrato, como demonstrado pela Figura 2-2.
Figura 2-2 - Representação de contrato de swap
Vamos exemplificar: na data t firmamos um contrato de swap com uma contraparte,
neste contrato é explicitado que a nossa ponta ativa é a cotação de Dolar/Real e nossa ponta
passiva (ponta ativa para a contraparte), é um índice de inflação, o IPCA. O tamanho deste
contrato é de 1000 e faremos a liquidação deste contrato 2 anos depois da data t, na posição
de PA e PP. Vamos supor que na data de início do contrato temos uma cotação USD/BRL de
2,20 e um valor de IPCA de 3946,44.
16
Na data de liquidação do contrato não vemos os valores de cada uma das pontas na
data, mas sim a diferença na rentabilidade destas duas pontas. Em dois anos a cotação de
USD/BRL aumentou para 2,35 e o valor do IPCA sofreu uma deflação para 3911,32. Isto é a
rentabilidade unitária da ponta ativa foi de 1,0681 e a da ponta passiva foi de 0,9911 e levando
em consideração o tamanho do contrato teríamos uma rentabilidade da ponta ativa de
R$1068,1 e a da ponta passiva de R$991,1. O contrato de swap é a diferença entre estas duas
rentabilidades, logo neste cenário hipotético obtivemos um ganho com este contrato de
R$77,00 e a contraparte uma perda de mesmo valor.
Este swap utilizado como exemplo não é um swap comum de ser realizado, os swaps
mais comuns envolvem utilização de CDI x Dólar, CDI x IPCA, CDI x IGPM, Dólar x Pré-fixado.
Variando de acordo com a expectativa as pontas passivas e ativas.
Há algumas modalidades a mis de swap, mas a lógica e a estrutura são bastante
parecidas, há contratos de swap com fluxos de troca de rentabilidade intermediário, os
chamados swap fluxo de caixa. Há swaps com ajustes de valores diários, como realizado em
futuro, os chamados swap cupom cambial. Posso entrar o contrato de um swap depois data de
início deste, chamado de swap decorrido.
1.4.4. Opções Opções são instrumentos financeiros derivativos em que realizar a liquidação
financeira na data de vencimento deste contrato é facultativa, isto é podemos escolher se
iremos exercer o que diz no contrato ou não, de acordo com o que for estipulado inicialmente.
Um exemplo simples de opção: um negociador faz um contrato de opção envolvendo uma
ação, pagando por este contrato R$0,50, nesta opção fica definido que em 3 semanas ele
poderá comprar 1 ação por um preço de R$10,00 da contraparte da opção. Após este período
de 3 semanas a ação que ele pode comprar definida no contrato vale R$9,00, logo, como o
valor no mercado está mais barato que o definido na opção é mais vantajoso não exercer o
que diz o derivativo, diz-se que a opção virou pó.
Baseado no exemplo conseguimos verificar que uma opção tem alguns parâmetros
básicos, que podem definidos abaixo, além dos parâmetros do exemplo iremos definir mais
alguns aspectos de opções:
1) Tipo de exercício: se é uma opção europeia ou americana;
2) Tipo de operação: se é uma opção de compra (call) ou de venda (put);
3) Ativo objeto: a que se refere esta opção, normalmente é utilizada para ações,
futuros, moedas e commodities;
4) Data da operação: data em que foi feita a compra/venda do contrato de
opção;
5) Data prevista de exercício: data ou data limite, dependendo do tipo de
exercício, em que podemos exercer o direito a compra/venda do ativo objeto.
Opções americanas podem ser exercidas até a data prevista de exercício,
enquanto as opções europeias podem ser exercidas somente na data
estipulada em contrato.
6) Prêmio: valor de compra/venda da opção;
7) Strike ou preço de exercício: valor de compra/venda do ativo objeto;
Todos estes parâmetros são suficientes para definir uma opção simples as chamadas
plain vanillas, mas caso o mercado ou operador necessite de opções um pouco mais
17
complexas ou que ajudem a limitar a perda/ganho, existem as opções exóticas, dentre estas
podemos citar principalmente as opções com barreira.
Além dos parâmetros explicitados acima, inerentes ao contrato da opção, temos
algumas outras definições:
8) Spot: preço do ativo base
As opções são bastante negociadas no mercado pois são derivativos que podem
proporcionar ganhos maiores do que quaisquer outras operações, se não for estabelecida uma
barreira. Da mesma forma, podem proporcionar perdas preocupantes para instituição/fundo
que fez o negócio. Além disso, dependendo da estratégia podemos realizar combinações entre
várias opções que diminuem o risco de perdas elevadas e proporcionam ganhos consideráveis.
Para exemplificar o uso de diversas opções iremos mostrar alguns gráficos que permitem
melhor visualização dos possíveis ganhos com as opções.
A Figura 2-3 representa os possíveis ganhos e perdas provenientes de uma compra de
opção de compra, o eixo x representa os diferentes valores para o spot do ativo objeto e o eixo
y representa o resultado da operação. Para esta opção hipotética temos um strike de 10 e um
prêmio de 0,5. Isto significa que com um spot de 10,5 temos uma situação de break even, em
que o valor da opção é zero. Após este valor teríamos um ganho ilimitado e antes deste valor
teríamos uma perda com a opção, mas esta é limitada ao valor pago pelo prêmio.
Figura 2-3 - representação de compra de call
A representação de uma venda de opção de compra é demonstrada na figura 2-4, ao
contrário da compra de call vemos um ganho limitado ao prêmio da venda da opção e perdas
que podem ser ilimitadas com a variação do spot do ativo.
-0,6
-0,4
-0,2
0
0,2
0,4
0,6
0,8
1
1,2
99.
19
.199
99
999
99
999
99
39
.300
00
000
00
000
00
79.
49.
59
.599
99
999
99
999
90
89
.699
99
999
99
999
90
49
.799
99
999
99
999
90
19
.899
99
999
99
999
89
79
.999
99
999
99
999
89
31
0.1
10
.19
99
999
99
999
99
91
0.3
10
.41
0.5
10
.61
0.7
10
.81
0.9 11
11
.11
1.2
11
.31
1.4
11
.5
Compra de call
18
Figura 2-4 - Representação de venda de call
Como citado, podemos realizar combinações de opções formando várias estratégias,
para citar algumas: trava de alta (bull spread), trava de baixa (bear spread), borboleta
(butterfly), box entre outras. Temos a representação de algumas delas em gráficos e como
deve ser feito a estratégia para atingir esta configuração.
A estratégia de trava de alta ou Bull Spread é representada pela Figura2-5, para atingir
esta configuração devemos realizar uma compra e uma venda de call, sendo que o strike da
opção de compra é menor do que a de venda. A estratégia de trava de baixa é o contrário da
trava de alta, ainda temos uma compra e uma venda de call, mas o strike da venda é menor do
que o da compra, conforme Figura 2-6. A estratégia Butterfly envolve estar posicionado em 2
compras e 2 vendas de opções.
Figura 2-5 - Representação de trava de alta (Bull Spread)
-1,2
-1
-0,8
-0,6
-0,4
-0,2
0
0,2
0,4
0,6
99
.19
.19
99
999
99
999
999
39
.30
00
000
00
000
000
79
.49
.59
.59
99
999
99
999
990
89
.69
99
999
99
999
990
49
.79
99
999
99
999
990
19
.89
99
999
99
999
989
79
.99
99
999
99
999
989
31
0.1
10
.19
99
999
999
99
999
10
.31
0.4
10
.51
0.6
10
.71
0.8
10
.9 111
1.1
11
.21
1.3
11
.41
1.5
Venda de call
-1,5
-1
-0,5
0
0,5
1
1,5
8.5
8.6
999
99
999
99
99
99
3
8.9
9.1
9.3
000
00
000
00
00
00
7
9.5
9.6
999
99
999
99
99
90
4
9.8
999
99
999
99
99
89
7
10.1
10.3
10.5
10.7
10.9
11.1
11.3
11.5
11.7
11.9
12.1
12.3
12.5
12.7
12.9
Bull Spread
19
Figura 2-6 - Representação de trava de baixa (Bear Spread)
Além destas estratégias e gráficos mostrados inicialmente poderíamos traçar os
gráficos de compra de opção de venda (compra de put), venda de opção de venda (venda de
put) e das outras combinações possíveis. O objetivo aqui não é mostrar todas estratégias
possíveis, mas elucidar a complexidade de cálculo, controle de posições em relação a várias
opções distintas e possibilidades de perdas e ganhos.
Todos estes gráficos mostram o valor de expectativa de perda/ganho em relação ao
dia de exercício, mas o mercado precisa destas informações antes da efetivação da ação,
realizar a precificação das opções seria obter o valor das opções (eixo y dos gráficos), antes da
data de exercício da opção.
Assim como no mercado de futuros e ações o acesso a estas operações é feito
exclusivamente via corretoras, e a negociação é realizada no âmbito da BM&FBovespa.
1.4.5. COE Recentemente a CETIP, uma das agentes do SPB, começou a disponibilizar e permitir a
negociação e emissão de certificado de operações estruturadas, os COEs[6], ele representa em
um único instrumento uma estratégia complexa envolvendo vários outros instrumentos
financeiros, poderia combinar uma renda fixa com futuro ou ação com opções de ação entre
outros.
Um exemplo: para realizar uma estratégia de butterfly precisamos estar posicionados
em 4 posições diferentes de opções com valores de exercício diferentes. Não é simples
conseguir comprar e vender estas diferentes opções nos termos desejados, poderíamos utilizar
um único instrumento que representaria estas combinações através de um COE.
Hoje a emissão de COE é restrita a bancos e foi autorizada a negociação somente no
final de 2013, logo é um segmento que está começando mas tem grande potencial
futuramente. Como envolve a combinação de diversos instrumentos, a precificação destes
COEs se torna um pouco mais complexas pois envolvem uma quantidade maior de variáveis a
serem consideradas.
-1,5
-1
-0,5
0
0,5
1
1,5
8.5
8.6
99
99
999
999
99
993
8.9
9.1
9.3
00
00
000
000
00
007
9.5
9.6
99
99
999
999
99
904
9.8
99
99
999
999
99
897
10
.1
10
.3
10
.5
10
.7
10
.9
11
.1
11
.3
11
.5
11
.7
11
.9
12
.1
12
.3
12
.5
12
.7
12
.9
Bear Spread
20
2. Tecnologia MAPS: Jmine e Luna A MAPS S.A. é uma empresa de tecnologia que que faz softwares para o mercado
financeiro, possui um portfólio de produtos que atendem diversas instituições em diferentes
segmentos. Possui sistema para bancos que realiza a troca de informações com o SPB, sistema
de controle de ativos e passivos de tesourarias, sistema de controladoria e custodia de fundos
de investimento, sistema de gestão de fundos para assets e sistemas de risco de mercado. Para
atender estas áreas, hoje possui mais de 12 produtos utilizados em grandes instituições
financeiras e assets.
Um dos produtos mais difundidos e considerado uma referência no mercado é o Luna,
sistema voltado para risco de mercado e regulatórios, este produto já existe no mercado a
mais de 10 anos e sua plataforma tecnológica é baseada em linguagem de programação C++. O
sistema pode ser facilmente instalado em um computador com sistema operacional Windows.
O sistema Luna é uma ferramenta para análise de risco, que calcula a exposição e
variação de ativos e derivativos a determinados parâmetros, utilizadas pelo gestor. Para
realizar o cálculo de exposições de risco é necessário precificar ativos e derivativos, através da
metodologia empregada e de alguns parâmetros utilizados no cálculo destes, conseguimos
fazer uma análise confiável para tomada de decisões.
Os sistemas de tesouraria, controladoria, custódia e gestão de fundos são plataformas
desenvolvidas em linguagem de programação java e são sistemas web, possível de utilização
através de um navegador de internet e independente do sistema operacional utilizado pelo
usuário. Possuem vantagens em relação a uma plataforma de instalação em uma máquina,
como compartilhamento de informações, multi-acesso, utilização de máquina virtual entre
outros. Estes sistemas foram desenvolvidos de maneira muito rápida pela empresa, em 6 anos
foram construídos mais de 10 sistemas, isso foi possível devido a idealização e implementação
de um framework que possibilita acelerar o desenvolvimento de softwares, muitas das
funcionalidades são comuns a todos os produtos, algumas funções básicas inerentes a
tecnologia Java e frameworks conhecidos, mas simplificadas para utilização e manutenção
mais rápidas, como escrita/leitura de banco de dados, infraestrutura de testes, layout de
páginas entre outros. E outras de negócio, como controle de diferentes praças e feriados,
controle de diferentes agentes, precificação e cálculo de risco de mercado.
Este framework é chamado de Jmine e nele há diversos códigos, classes e controles
que são herdados e utilizados intensamente pelos produtos. O Jmine é dividido em camadas,
sendo que uma dela é open source, disponível para utilização e alterações, esta camada na
empresa é chamada de jmine-tec-open e para utilização open-source simplesmente jmine.
Além do jmine-tec-open, há o jmine-tec-legacy, com algumas configurações que fariam com
que a camada não pudesse ser open source. Estas duas camadas têm funções básicas de
tecnologia utilizadas pelos sistemas, como construção de páginas web, leitura/escrita de
bando de dados, controle de base quente/base fria, rastreabilidade, credenciais de acesso
entre outros.
Acima destas camadas de tecnologia há as seguintes camadas de negócio: biz-base,
invest-base, invest-gerencial, invest-operacional e invest-ativos, existe uma hierarquia entre
elas, como demonstrado na figura abaixo:
21
Figura 3-7 - Hierarquia de camadas do Jmine
Os tamanhos dos blocos não representam exatamente o tamanho, em quantidade de
código, de cada camada. Os produtos MAPS estão acima destas camadas, alguns em diferentes
níveis, de acordo com a necessidade. Iremos nos focar em uma camada em particular, o jmine-
invest-base, muitos dos produtos utilizam esta parte do framework pois ela é a responsável
pela precificação de ativos e derivativos. A estrutura utilizada para precificação é bastante
complexa, temos diversos modelos de cálculos e para cada caso, dependendo do tipo de ativo,
do fundo entre outros podemos utilizar um modelo diferente. Então a estrutura deve ser
robusta e flexível o suficiente para realizar o cálculo de maneira correta, além disso caso
ocorra algum problema o usuário não deve esperar muito tempo para sua resolução, então
deve-se possibilitar uma rápida correção, até mesmo sem a troca de versão do produto.
Pelo exposto acima, verificamos que dentro da mesma empresa temos duas
plataformas tecnológicas diferentes que realizam a precificação de ativos e derivativos (Luna e
Jmine), e as metodologias empregadas nas duas plataformas muitas vezes são diferentes.
Além disso, observamos que existe uma variação de cálculo de uma instituição para outra,
dado que os produtos da MAPS estão presentes em diversos clientes distintos.
Neste trabalho iremos desenvolver um algoritmo de cálculo similar ao existente em
um dos sistemas, pois garantimos deste modo que é utilizado em larga escala pelo mercado e
conseguimos verificar a assertividade do código desenvolvido, comparando os resultados
gerados.
3. Precificação de derivativos: Opções A precificação de opções [7] é a obtenção do valor justo dela antes da data de exercício.
Temos inúmeras metodologias de cálculo dependendo principalmente do tipo de exercício da
opção e do ativo objeto.
Uma metodologia bastante banal mas que é utilizada em alguns clientes da MAPS é a
utilização do Modelo Cotação e pode ser facilmente aplicada para algumas opções
padronizadas disponibilizadas pela BM&FBovespa, suas características são bastante fechadas a
bolsa disponibiliza o valor delas diariamente. A precificação por este modelo envolve
simplesmente multiplicar a quantidade pelo PU divulgado.
Para as opções flexíveis, não conseguimos utilizar este modelo, logo deve-se
desenvolver um cálculo para cada tipo de opção, abaixo seguem algumas metodologias de
cálculo bastante difundidas pelo mercado:
22
Black-Scholes
Black
Black 76
Garman
Bjerksund and Stensland
Merton, Reiner e Rubinstein
Antes de explicarmos rapidamente estas metodologias há alguns conceitos voltados ao
mercado financeiro necessários para entender todas as fórmulas disponibilizadas.
3.1. Taxas e convenção de contagem de dias Taxas podem se referir a taxas de juros de papeis negociados em algumas operações,
no tópico sobre instrumentos financeiros considerados de renda fixa o exemplo dado havia
cupons ou juros que eram pagos regularmente, o cálculo destes juros é obtido através da taxa
de juros nominais definida durante a criação do instrumento. Um exemplo, para uma NTNF
(título público), a taxa de juros nominal é defina como 10%, este valor equivale a um PU de
juros de aproximadamente R$48,808848. Para obter este valor devemos obter um fator a
partir desta taxa, para obtermos este valor precisamos saber qual é o método de cálculo
(linear ou exponencial), uma data início e a data fim que devemos considerar no cálculo. Após
conhecer a data início e fim precisamos saber que tipo de convenção utilizaremos entre estas
duas datas para calcular o fator.
No Jmine, a nomenclatura de convenção de contagem de dias é: ACT360, ACT252,
ACT365, A30360, B21252 entre outros. No cálculo com convenção de contagem de dias
ACT360, obtemos a quantidade de dias corridos entre as datas início e fim e dividimos por 360,
para ACT252 obtemos a quantidade de dias úteis entre as duas datas e dividimos por 252, para
A30360 precisamos saber o número de anos fechados, meses fechados e dias entre as duas
datas para conseguirmos calcular o valor do fator.
Outro caso bastante comum de taxas é durante a negociação de um ativo, ao realizar a
compra de uma NTNB (título público), por exemplo, o operador não negocia diretamente qual
será o PU da operação, mas uma taxa para esta operação, e através de determinadas
metodologias de cálculo conseguimos obter o PU da operação. Por exemplo, um trader do
Banco do Brasil fez a compra de uma NTN-B de vencimento 15/05/2017, para essa compra ele
negociou uma taxa de 5,16%, este valor representa na data de compra (14/10/2014), um PU
para operação de R$2.582,176452. Caso ele negociasse uma taxa maior, teria obtido um valor
de PU menor, ou seja, para estes casos são inversamente proporcionais. Os valores das
operações de alguns ativos são coletados e monta-se uma taxa indicativa média de negociação
e são disponibilizados em sites especializados, como por exemplo ANBIMA[8] e pelos próprios
locais de negociação como BM&FBovespa e CETIP.
Um outro caso de taxa de juros é no caso de taxa de juros de ativo livre de risco, ela
representa um custo de oportunidade de adquirir um ativo durante um determinado período
de tempo. Quanto maior o custo do dinheiro do prazo de vencimento, mais atrativo é comprar
a opção ao invés de adquirir o ativo objeto diretamente, já que ao efetivar a opção temos um
custo menor.
23
3.2. Curvas e interpolação Uma das funções da divulgação de taxas é para o cálculo de indexadores, um
indexador bastante difundido no mercado é o CDI, frequentemente ouvimos a expressão:
investimento A dará um retorno de 95%CDI, por exemplo. Este CDI é um indexador obtido
através das taxas médias de operações de DI (instrumento financeiro), realizadas entre bancos.
Ou também pode ser utilizado para a construção de curvas, que são ferramentas para
conseguir estimar, projetar ou descontar um valor de uma data base para uma data alvo.
Podemos dar alguns exemplos de curvas que podem ser construídas a partir de taxas (nomes
seguem nomenclatura utilizada no Jmine), a PRE_100%CDI, construída a partir das taxas de
negociação de contratos de swap pré x DI, valores divulgados pela BM&FBovespa, ou a curva
PRE_DI1_BMF, que os valores são originados a partir das taxas de negociação de contratos de
FUT-DI1.
O exemplo abaixo dá uma amostra de uma curva construída em um dos sistemas
MAPS (Nave), utilizando o framework Jmine e os dados fontes utilizados para a construção
desta curva.
Figura 4-8 - Curva PRE_DI1_BMF construída no Nave
Curva: PRE_DI1_BMF
Data base Data vértice Taxa Fator
14/10/2014 02/01/2015 10,950 1,0233596159
14/10/2014 01/04/2015 11,310 1,0510059493
14/10/2014 01/07/2015 11,570 1,0804013043
14/10/2014 01/10/2015 11,780 1,1133630735
14/10/2014 04/01/2016 11,850 1,1456659229
14/10/2014 01/04/2016 11,890 1,1777608599
14/10/2014 01/07/2016 11,880 1,2111242733
14/10/2014 03/10/2016 11,860 1,2462674291
14/10/2014 02/01/2017 11,760 1,2785810819
14/10/2014 03/04/2017 11,730 1,3137507400
14/10/2014 03/07/2017 11,700 1,3485218245
14/10/2014 02/10/2017 11,700 1,3869537032
14/10/2014 02/01/2018 11,670 1,4233797526
14/10/2014 02/04/2018 11,685 1,4625985755
14/10/2014 02/07/2018 11,660 1,5023289103
14/10/2014 01/10/2018 11,630 1,5433670713
24
14/10/2014 02/01/2019 11,580 1,5827397795
14/10/2014 01/04/2019 11,530 1,6220550172
14/10/2014 01/07/2019 11,490 1,6633997496
14/10/2014 01/10/2019 11,431 1,7069947010
14/10/2014 02/01/2020 11,380 1,7504005792
14/10/2014 01/04/2020 11,360 1,7956812788
14/10/2014 01/07/2020 11,340 1,8411849130
14/10/2014 01/10/2020 11,290 1,8878678251
14/10/2014 04/01/2021 11,230 1,9325725439
14/10/2014 01/04/2021 11,219 1,9817469218
14/10/2014 01/07/2021 11,209 2,0330537952
14/10/2014 01/10/2021 11,199 2,0882337218
14/10/2014 03/01/2022 11,190 2,1431458552
14/10/2014 01/07/2022 11,153 2,2522111646
14/10/2014 02/01/2023 11,120 2,3697187855
14/10/2014 03/07/2023 11,111 2,4941599245
14/10/2014 02/01/2024 11,104 2,6264573555
14/10/2014 01/07/2024 11,097 2,7644439432
14/10/2014 02/01/2025 11,090 2,9167946410
14/10/2014 02/01/2026 11,090 3,2416203304 Tabela 4-3-1 - Parâmetros da curva PRE_DI1_BMF
As colunas da tabela com parâmetros, possuem o seguinte significado:
Data base: data de referência da curva;
Data vértice: são as datas alvos, coincidem com as datas de vencimentos dos
contratos futuros de DI1;
Taxa: taxa da curva, neste caso são exatamente os valores de negociação dos
contratos de futuro, com a respectiva data vértice, são os valores que dão
origem a curva;
Fator: calculado a partir da taxa, é o valor que utilizamos, de fato, durante o
cálculo de projeção e algum ativo.
Para obter o fator, a partir da taxa, utilizamos a seguinte fórmula:
����
1001 +
����� =
Sendo, du (Data base, Data vértice) o número de dias úteis entre a Data base e a Data
vértice.
Para exemplificar a utilização de curvas, podemos citar o caso de projeção de valores,
vamos supor que na data 14/10/2014 calculamos o valor de juros de um papel de renda fixa, o
valor obtido foi de R$1.000,00. Este fluxo será pago no dia 01/04/2015, para estimarmos este
valor devemos basicamente multiplicar o valor na data base de cálculo (14/10/2014) pelo fator
da curva correspondente ao vértice em 01/04/2015. Logo temos que o valor projetado é de
R$1.051,0059.
Há alguns casos em que precisamos de uma data alvo (vértice), inexistente como
parâmetro da curva, para estes casos devemos realizar uma interpolação com os dados
conhecidos. Alguns exemplos e métodos de interpolação usados: Flat_Forward, Cubic Spline,
25
Exponencial dias corridos, Liner dias úteis entre outros. Muitos destes métodos são vistos
durante algumas disciplinas do curso de engenharia e não focaremos neste assunto, mas deve-
se ressaltar que são conceitos importantes para a boa utilização desta ferramenta. O conceito
de interpolação também pode ser aplicado no item posterior, em relação a volatilidade.
3.3. Volatilidade O conceito de volatilidade está associado ao nível de incerteza sobre o
comportamento futuro do mercado, normalmente utilizamos três maneiras de estudar e
calcular a volatilidade: histórica, implícita e estimada. É uma medida de dispersão dos retornos
dos ativos-objetos, quanto maior a volatilidade maior é a variação do valor do ativo ao longo
do tempo e maior a incerteza quanto ao preço esperado no futuro, desta forma o valor da
opção e consequentemente o prêmio é uma função crescente em relação a volatividade.
A volatilidade histórica assume que os dados passados são relevantes para o
comportamento do ativo no futuro, isto é, a volatilidade presente é estimada a partir de dados
passados.
Volatilidade implícita é a busca por um consenso de mercado, para tentar determinar,
observamos os prêmios pagos pelas opções negociadas no mercado. É o principal modo de
cálculo de volatilidade para opções.
E a volatilidade estimada é apurada a partir de projeções de comportamento de
mercado, desta forma identificamos a variabilidade passível de ocorrer.
Para o cálculo de volatilidade são utilizadas algumas metodologias de cálculo neste
trabalho iremos nos focar na volatilidade implícita, pois é a utilizada para o cálculo de opções.
3.3.1. Volatilidade implícita A volatilidade implícita varia de acordo com os valores de preço de exercício ou de
prazo da opção, procura-se determinar qual a volatilidade que aplicada ao modelo torne o
prêmio teórico calculado igual do prêmio do mercado. Como ela é baseada no preço de
mercado de várias opções não conseguimos calcular esta variável de maneira analítica,
necessitando utilizada através de cálculo numérico e múltiplas iterações. Uma condição para o
correto cálculo da volatilidade é a existência de liquidez no mercado para termos valores de
mercado e desta forma realizar o cálculo da volatilidade. Mesmo com estas considerações, a
maioria das hipóteses de precificação assumem que a volatilidade é a mesma.
3.4. Precificação de opção de ação por Bjerksund and Stensland
Esta aproximação pode ser utilizada para opções americanas de ações, futuros e
moedas, é um método analítico e computacionalmente bastante eficiente, sua metodologia é
baseada em um limite chamado de preço de disparo, para este trabalho iremos nos focar no
cálculo da opção de ação com aproximação de Bjerksund and Stensland.
Os principais parâmetros que afetam o cálculo desta metodologia são:
Preço de mercado do ativo objeto ou Spot (S);
Preço de exercício ou strike (X);
Taxa de juros livre de risco (R);
Período entre emissão e vencimento (T), em anos;
26
Volatilidade (σ);
Preço de disparo (I);
Taxa de carregamento (b);
Função acumulada da normal padronizada (N);
Temos metodologias diferentes para o cálculo de uma call (C) para uma put (P), que
serão explicitadas, antes disso, algumas considerações devem ser feitas na determinação de
valor de um call:
Se S ≥ I, a melhor alternativa é exercer a opção imediatamente e o valor da
opção será � = � − �
Quando b ≥ r, nunca será vantajoso exercer a opção de compra antes do
vencimento, neste caso utiliza-se o modelo Black-Scholes
Para b ≤ r, o preço da call será dado pela fórmula:
� = ��� − ��(�, �, �, �, �) + �(�, �, 1, �, �) − �(�, �, 1, �, �) − ��(�, �, 0, �, �)
+ ��(�, �, 0, �, 1)
Sendo:
� = (� − �)���
� = �1
2−
�
��� +��
�
��−1
2��
+ 2�
��
Além disso, temos que:
�(�, �, �, �, �) = ���� ��(�) − ��
���
��� −2�� �
���
�√���
� = �−� + �� +�
��(� − 1)���T
� =−�� �
���
+ �� + �� −12�
��� �
�√�
� =2�
��+ (2� − 1)
E o preço de disparo, pode ser definido por:
� = �� + (�� − ��)�1 − ��(�)�
ℎ(�) = −��� + 2�√�� ���
�� − ���
�� =�
� − 1�
�� = �����, ��
� − ����
27
O preço de uma put (P), para qualquer valor de b, pode ser obtido a partir de uma
transformação do cálculo de um call, alterando os parâmetros de taxa de juros livre e de taxa
de carregamento, dado pela equação abaixo:
�(�, �, �, �, �, �) = �(�, �, �, � − �, −�, �)
O cálculo da função acumulada normal padronizada pode ser dado por, garantindo um
valor de até 4 casas decimais:
�(�) =1
√2�� ����
−��
2�
�
��
��
1 − �(�)(��� + ���� + ���
�), ����� ≥ 0
1 − �(−�), ����� ≤ 0
Onde:
� =1
1 + 0,33267�
�� = 0,4361836
�� = −0,1201676
�� = 0,9372980
�(�) =1
√2�����
�
4. GPU´s e plataformas de computação paralela
As Unidades de Processamento Gráfico[9] (GPU, das siglas em inglês Graphics
Processing Unit), são dispositivos eletrônicos idealizados inicialmente para utilização em
computação gráfica, voltadas principalmente ao mercado de jogos eletrônicos para
computadores pessoais. Conseguem, de forma muito rápida, manipular e alterar memórias
para desta for acelerar o processo de criação de imagens e visualização em telas. Estão
presentes em algumas placas de vídeo de computadores pessoais, mas podem ser encontradas
em sistemas embarcados, estações de trabalho, smartphones, vídeo-games entre outros. Em
computadores pessoais foram popularizados principalmente pela Nvidia a partir do final da
década de 90, mas principalmente em meados do ano 2000, atualmente outras empresas
constroem suas placas de vídeo com GPUs.
A partir de certo momento, verificou-se que esta ferramenta poderosa poderia ser
utilizada na otimização de processamento e cálculos não ligados a gráficos, mas que
apresentavam uma complexidade razoável. Alguns exemplos são: engenharia de petróleo,
térmica, fluídos e para o mercado financeiro. Para este último caso é uma ferramenta que está
28
sendo utilizada gradativamente, pois muitos das plataformas do mercado financeiro não
conseguiriam utilizar as GPUs pois não estão adaptadas para tanto.
Como são ferramentas criadas para melhora e otimização de visualização de gráficos,
as empresas que queriam utilizar esta ferramenta poderosa precisavam adaptar seu
desenvolvimento para compatibilizar com a linguagem de máquina que as GPUs entendessem.
Para conseguirmos utilizar o potencial das GPUs precisamos de uma linguagem de
programação consistente com a linguagem da máquina e que seja possível de executar através
de várias plataformas distintas e heterogêneas dentro de um computador, precisamos acessar
tanto as CPUs quanto as GPUs dentro do computador para utilizarmos ao máximo o potencial.
Como estamos realizando cálculo em diversos lugares diferentes, temos um caso de
computação paralela, em que os processos e operações são resolvidos em diversos lugares
diferentes e com diferentes threads.
Alguns exemplos de linguagens de programação que fazem uso de computação
paralela e consegue realizar o cálculo através das GPUs são OpenCL e CUDA, iremos abordar
nos tópicos seguintes.
4.1. OpenCL Open Computing Language[10] (OpenCL) é um framework de programação que
consegue executar comandos em diferentes plataformas de um computador, como as CPUs,
GPUs entre outros. É uma linguagem baseada em C99 que consegue enviar, executar
comandos e controlar estes aparelhos e para programar interfaces para estas aplicações
(APIs). É um framework open source utilizado por empresas como Intel, Apple, AMD, Samsung
entre outros.
Como ela é baseada em uma linguagem predecessora da linguagem C, não possui
algumas ferramentas e em alguns casos é bastante limitada em relação a facilidade de escrita
de código, performance e até mesmo compilação. Mas o principal problema seria em relação a
migração de sistemas atuais para conseguir utilizar o poder de processamento de
programação paralela e das GPUs, pois teriamos um retrabalho grande de reescrita destes
códigos para esta plataforma.
4.2. CUDA A linguagem CUDA [11] (Compute Unified Dive Architecture) foi criada em 2007 e é uma
plataforma de computação paralela criada pela Nvidia e implementada nas GPUs produzidas
pela empresa. Por ser uma plataforma dedicada e desenvolvida para utilização especifica em
uma arquitetura de hardware, a linguagem CUDA permite explorar todo potencial de
processamento em alta performance disponibilizada nas placas NVIDIA. Alguns exemplos de
avanços obtidos com o uso de CUDA são: identificação e placas ocultas em artérias, análise de
fluxo de tráfego aéreo e até mesmo visualização de moléculas.
O aprendizado é relativamente simples, dado que no próprio site da NVIDIA são
disponibilizados uma quantidade razoável de material, exemplos, documentação, códigos e
casos de uso para as APIs e bibliotecas envolvendo CUDA.
29
Uma vantagem da utilização de CUDA é a possibilidade de trabalhar e enviar códigos
escritos originalmente em uma outra linguagem e com pouca adaptação enviar diretamente a
GPU, não é necessário uma linguagem de compilação especifica, facilitando o trabalho e
reduzindo a curva de aprendizado de uma nova linguagem de programação que poderia
envolver sintaxes e regras próprias. Algumas linguagens em que há suporte para utilização do
CUDA são Fortran, C, Phyton, Java, .NET entre outras. Este é um dos pontos que passa a ser
vantajoso a utilização das GPUs, pois não temos um custo alto para adaptação dos programas
já existentes para tentar um ganho de performance, além de que alterar o código para uma
linguagem nova acarreta novos testes, problemas inesperados, incompatibilidade entre
outros.
5. Método de avaliação e comparação
Iremos criar um algoritmo em linguagem de programação Java que realiza a
precificação de uma opção de ação utilizando o método de Bjerksund and Stensland, calculado
muito importante no mercado financeiro e utilizado em vários agentes de mercado de forma
oficial. Mas o objetivo deste trabalho não é simplesmente a implementação de um código que
faça a precificação de um derivativo, mas sim possibilitar a melhoria e ganhos de performance
considerável com a utilização das GPUs. Para isso iremos utilizar o código em Java e adapta-lo
utilizando framework, biblioteca e APIs com acesso a GPUs, o JCUDA, e comparando o tempo
de execução em uma mesma máquina
Para replicar as condições e garantindo que outros fatores sejam equivalentes, como
uso de memória e processamento do computador com atividades paralelas entre outros,
iremos mensurar e analisar o tempo de resposta dos dois programas e compara-los para medir
o ganho de performance, além disso é importante ter uma boa percepção do tempo de criação
do código e da adaptação para possibilitar o uso da GPUs, este é um parâmetro importante a
ser considerado no trabalho.
A máquina de teste utiliza um sistema operacional Linux, distribuição Ubuntu, e a
compilação, execução e desenvolvimento serão feitos na IDE Eclipse.
6. Algoritmo de cálculos em java
A seguir mostraremos o algoritmo de cálculo, em java, para realizar a precificação de
uma opção hipotética.
6.1. Classe de contexto de precificação:
package es952.precificacao; import java.math.BigDecimal; import jmine.tec.utils.date.Date;
30
/** * @author fernando * */ public class Context { private String tipo; private double strike; private double taxaCarregamento; private double taxaJurosLivre; private Date dataCalculo; private Date dataVencimento; /** * @return {@link String} tipo */ public String getTipo() { return this.tipo; } /** * @return {@link double} strike */ public double getStrike() { return this.strike; } /** * @return {@link double} taxaCarregamento */ public double getTaxaCarregamento() { return this.taxaCarregamento; } /** * @return {@link double} taxaJurosLivre */ public double getTaxaJurosLivre() { return this.taxaJurosLivre; } /** * @return {@link Date} dataEmissao */ public Date getDataCalculo() { return this.dataCalculo; } /** * @return {@link Date} dataVencimento */ public Date getDataVencimento() { return this.dataVencimento; } /** * Set de strike da opção
31
* @param strike {@link BigDecimal} */ public void setTipo(String tipo) { this.tipo = tipo; } /** * Set de strike da opção * @param strike {@link double} */ public void setStrike(double strike) { this.strike = strike; } /** * Set da taxa de carregamento * @param taxaCarregamento {@link double} */ public void setTaxaCarregamento(double taxaCarregamento) { this.taxaCarregamento = taxaCarregamento; } /** * Set da taxa de juros livre de risco * @param taxaJurosLivre {@link double} */ public void setTaxaJurosLivre(double taxaJurosLivre) { this.taxaJurosLivre = taxaJurosLivre; } /** * Set da data de emissão da opção * @param dateEmissao {@link Date} */ public void setDataCalculo(Date dataCalculo) { this.dataCalculo = dataCalculo; } /** * Set da data de vencimento da opção * @param dataVencimento {@link Date} */ public void setDataVencimento(Date dataVencimento) { this.dataVencimento = dataVencimento; } }
6.2. Classe de cálculo de função normal
package es952.precificacao; import java.math.BigDecimal; import org.omg.CORBA.PRIVATE_MEMBER; import jmine.tec.utils.date.Date; /** * @author fernando *
32
*/ public class FuncaoNormal { /** * @return {@link BigDecimal} valor */ public double getValorFuncao(double valorBase) { double A1 = 0.4361836; double A2 = -0.1201676; double A3 = 0.9372980; double valorFuncao; if (valorBase >= 0) { double fatorKx = 1 / (1+0.33267*valorBase); double fatorNx = 1; fatorNx = fatorNx / Math.sqrt(2 * Math.PI); fatorNx = fatorNx * (Math.pow(Math.E, (valorBase * valorBase) / 2)); valorFuncao = A1 * fatorKx; valorFuncao = valorFuncao + (A2 * fatorKx * fatorKx); valorFuncao = valorFuncao + (A3 * Math.pow(fatorKx, 3)); valorFuncao = valorFuncao * fatorNx; valorFuncao = 1 - valorFuncao; return valorFuncao; } else { return 1-(this.getValorFuncao(-valorBase)); } } }
6.3. Classe que representa um valor de mercado médio das opções package es952.precificacao; import java.math.BigDecimal; import jmine.tec.utils.date.Date; /** * @author fernando * */ public class ValorMercado { private double valor; private Date data; /** * @return {@link double} valor */ public double getValor() { return this.valor; } /** * @return {@link Date} data */ public Date getData() { return this.data;
33
} /** * Setta o valor de volatividade para uma determinada data. * @param valor {@link double} */ public void setValor(double valor) { this.valor = valor; } /** * Setta uma data da volatilidade. * @param data {@link Date} */ public void setData(Date data) { this.data = data; } }
6.4. Classe que representa uma volatilidade da opção
package es952.precificacao; import java.math.BigDecimal; import jmine.tec.utils.date.Date; /** * @author fernando * */ public class Volatilidade { private double valor; private Date data; /** * @return {@link BigDecimal} valor */ public double getValor() { return this.valor; } /** * @return {@link Date} data */ public Date getData() { return this.data; } /** * Setta o valor de volatividade para uma determinada data. * @param valor {@link BigDecimal} */ public void setValor(double valor) { this.valor = valor; } /** * Setta uma data da volatilidade. * @param data {@link Date} */ public void setData(Date data) {
34
this.data = data; } }
6.5. Classe que consolida e agrega uma calculadora de opção package es952.precificacao; import jmine.tec.utils.date.Date; import jmine.tec.component.exception.BusinessException; import jmine.tec.component.exception.MessageHolder; /** * @author fernando * */ public class CalculadoraOpcao { private double ANO_360 = 360; private double alpha; private double beta; private double precoDisparo; private double fatorT; /** * Executa o cálculo de precificação de acordo com o contexto passado. * * @param ctx * @throws Exception */ public double execute(Context ctx, Volatilidade volatilidade, ValorMercado valorMercado) throws Exception { double valor = 0; this.fatorT = this.getDaysFractionBetween(ctx.getDataCalculo(), ctx.getDataVencimento()); this.beta = this.calculaBeta(ctx.getTaxaCarregamento(), ctx.getTaxaJurosLivre(), volatilidade.getValor()); this.precoDisparo = this.calculaPrecoDisparo(this.beta, ctx.getStrike(), ctx.getTaxaJurosLivre(), ctx.getTaxaCarregamento(), this.fatorT, volatilidade.getValor()); this.alpha = this.calculaAlpha(this.precoDisparo, ctx.getStrike(), this.beta, volatilidade.getValor()); if (ctx.getTipo().equals("C")) { if (valorMercado.getValor() >= (this.precoDisparo)) { valor = valorMercado.getValor() - (ctx.getStrike()); } else { if (ctx.getTaxaCarregamento() <= (ctx.getTaxaJurosLivre())) { double fator1 = this.alpha * (Math.pow(valorMercado.getValor(), this.beta)); double fator2 = this.alpha * (this.calculaFatorPhi(valorMercado.getValor(), this.fatorT, this.beta, this.precoDisparo, this.precoDisparo, ctx.getTaxaJurosLivre(), ctx.getTaxaCarregamento(), volatilidade.getValor(), valorMercado.getValor(), this.precoDisparo));
35
double fator3 = this.calculaFatorPhi(valorMercado.getValor(), this.fatorT, 1, this.precoDisparo, this.precoDisparo, ctx.getTaxaJurosLivre(), ctx.getTaxaCarregamento(), volatilidade.getValor(), valorMercado.getValor(), this.precoDisparo); double fator4 = this.calculaFatorPhi(valorMercado.getValor(), this.fatorT, 1, ctx.getStrike(), this.precoDisparo, ctx.getTaxaJurosLivre(), ctx.getTaxaCarregamento(), volatilidade.getValor(), valorMercado.getValor(), this.precoDisparo); double fator5 = ctx.getStrike() * ( this.calculaFatorPhi(valorMercado.getValor(), this.fatorT, 0, this.precoDisparo, this.precoDisparo, ctx.getTaxaJurosLivre(), ctx.getTaxaCarregamento(), volatilidade.getValor(), valorMercado.getValor(), this.precoDisparo)); double fator6 = ctx.getStrike() * ( this.calculaFatorPhi(valorMercado.getValor(), this.fatorT, 0, ctx.getStrike(), 1, ctx.getTaxaJurosLivre(), ctx.getTaxaCarregamento(), volatilidade.getValor(), valorMercado.getValor(), this.precoDisparo)); valor = fator1 + (fator2) + (fator3) + (fator4) + (fator5) + (fator6); } else { // TODO lancar exceção de negócio corretamente MessageHolder holder = new MessageHolder(" ", " ", null); throw new BusinessException(holder); } } } return valor; } /** * Calcula preço de disparo da opção. * * @param ctx */ public double calculaPrecoDisparo(double beta, double strike, double txJuros, double txCarreg, double periodo, double vol) { double betaInf = 1; double betaZero = 1; double ht = 1; double htBeta = 1; double htSqrt = 1; double valor; betaInf = beta; betaInf =betaInf / ((betaInf-1)); betaInf = betaInf * strike;
36
betaZero = (txJuros / ((txJuros - txCarreg))); betaZero = betaZero*(strike); if (betaZero >= strike) { betaZero = betaZero; } else { betaZero = strike; } htBeta = betaZero / (betaInf - betaZero); htSqrt = vol*2; htSqrt = htSqrt*(Math.sqrt(periodo)); ht = txCarreg*periodo; ht = ht+htSqrt; ht = ht*htBeta; ht = -ht; valor = betaInf - betaZero; valor = valor * (1-(Math.pow(Math.E, ht))); valor = valor + betaZero; return valor; } /** * Realiza o cálculo do parâmetro Beta, utilizado nas contas de * precificação. * * @param ctx */ private double calculaBeta(double txCarreg, double txJuros, double vol) { double betaSqrt = 2; double betaPow = 1; double beta = 1; beta = beta / 2; beta = beta - ((txCarreg / (vol*vol))); betaSqrt = betaSqrt*(txJuros); betaSqrt = betaSqrt/ (vol*vol); betaPow = betaPow / 2; betaPow = (txCarreg / (vol*vol))-(betaPow); betaPow = betaPow*betaPow; betaSqrt = betaSqrt + betaPow; betaSqrt = Math.sqrt(betaSqrt); beta = beta+betaSqrt; return beta; } /** * @param ctx * @return alpha */ private double calculaAlpha(double precoDisparo, double strike, double beta, double vol) { double alpha = 1; alpha = precoDisparo; alpha = alpha - strike; alpha = alpha * (Math.pow(precoDisparo, -beta));
37
return alpha; } /** * Retorna o número de dias entre duas datas de forma anualizada, * considerando uma convenção de contagem de dias ACT360. * * @param dataBase * @param dataAlvo * @return dias entre as datas */ private double getDaysFractionBetween(Date dataBase, Date dataAlvo) { double fracao = 0; double daysBetween; daysBetween = dataAlvo.getDateJulian() - dataBase.getDateJulian(); fracao = daysBetween / ANO_360; return fracao; } /** * @param ctx * @param vol * @param paramNi * @return */ private double calculaFatorK(double txCarreg, double vol, double paramNi) { double fatorK; fatorK = 2 * txCarreg; fatorK = (fatorK / (vol*vol)); fatorK = fatorK+(2 * paramNi); fatorK = fatorK - 1; return fatorK; } /** * @param ctx * @param vol * @param paramNi * @return */ private double calculaFatorGamma(double txJuros, double txCarreg, double periodo, double vol, double paramNi) { double fatorGamma; fatorGamma = paramNi - 1; fatorGamma = fatorGamma*(paramNi); fatorGamma = fatorGamma / 2; fatorGamma = fatorGamma * (vol) * (vol); fatorGamma = fatorGamma + (paramNi * txCarreg); fatorGamma = fatorGamma - txJuros; fatorGamma = fatorGamma * periodo; return fatorGamma; } /** * @param ctx * @param vol * @param paramH * @param paramNi * @param valorMercado * @return */
38
private double calculaFatorD(double txCarreg, double periodo, double vol, double paramH, double paramNi, double valorMercado) { double fatorD; fatorD = -0.5; fatorD = fatorD + paramNi; fatorD = fatorD * vol * vol; fatorD = fatorD + txCarreg; fatorD = fatorD * periodo; fatorD = fatorD+ Math.log(valorMercado / paramH); fatorD = fatorD / vol; fatorD = fatorD / Math.sqrt(periodo); return -fatorD; } /** * @param ctx * @param valorMercado * @param paramH * @param paramNi * @return */ private double calculaFatorPhi(double paramS, double paramT, double paramNi, double paramH, double paramI, double txJuros, double txCarreg, double vol, double valorMercado, double precoDisparo) { double fatorGamma = this.calculaFatorGamma(txJuros, txCarreg, paramT, vol, paramNi); double fatorD = this.calculaFatorD(txCarreg, paramT, vol, paramH, paramNi, valorMercado); double fatorK = this.calculaFatorK(txCarreg, vol, paramNi); FuncaoNormal normalD = new FuncaoNormal(); double fatorNormalD = normalD.getValorFuncao(fatorD); double paramNormalComplexa = 2 * Math.log(precoDisparo/ valorMercado); paramNormalComplexa = paramNormalComplexa / vol; paramNormalComplexa = paramNormalComplexa/ Math.sqrt(paramT); paramNormalComplexa = fatorD - paramNormalComplexa; FuncaoNormal normalComplexa = new FuncaoNormal(); double fatorNormalComplexa = normalComplexa.getValorFuncao(paramNormalComplexa); double fatorPhi; fatorPhi = fatorNormalComplexa * Math.pow(precoDisparo / valorMercado, fatorK); fatorPhi = fatorNormalD - fatorPhi; fatorPhi = fatorPhi * (Math.pow(valorMercado, fatorGamma)); fatorPhi = fatorPhi * (Math.pow(Math.E, fatorGamma)); return fatorPhi; } }
6.6. Classe que realiza a precificação, considerando cenário package es952.precificacao; import java.math.BigDecimal; import jmine.tec.component.exception.BusinessException;
39
import jmine.tec.utils.date.Date; /** * @author fernando * */ public class Precificador { /** * @param args */ public static void main(String[] args) { Context ctx = new Context(); ctx.setDataCalculo(new Date(2014, 10, 04)); ctx.setDataVencimento(new Date(2015, 07, 01)); ctx.setStrike(40); ctx.setTaxaCarregamento(-0.04); ctx.setTaxaJurosLivre(0.04); ctx.setTipo("C"); Volatilidade vol = new Volatilidade(); vol.setData(new Date(2014, 10, 04)); vol.setValor(0.35); ValorMercado valorMercado = new ValorMercado(); valorMercado.setData(new Date(2014, 10, 04)); valorMercado.setValor(40); CalculadoraOpcao calcCall = new CalculadoraOpcao(); try { double valor = calcCall.execute(ctx, vol, valorMercado); System.out.println("O valor desta opção é: " + valor); } catch (BusinessException e) { System.out.println("Não foi possível calcular a opção, mude os parâmetros ou utilize outro método"); e.printStackTrace(); } catch (Exception e) { System.out.println("ERRO"); e.printStackTrace(); } } }
7. Conclusão
Para os testes com tecnologia CUDA utilizamos um conjunto de bibliotecas Java que
realiza a comunicação com um compilador C e por sua vez envia comandos para a GPU
executar, este conjunto possui o nome JCuda[12] e foram disponibilizados para utilização em
ambiente Linux por Mark Bishop. Cada uma destas bibliotecas está encapsulada em um
arquivo .jar para utilização em linguagem de programação Java e um arquivo .so (shared
object) que realiza a compilação das bibliotecas e dos arquivos de código .java que fazem uso
de APIs das bibliotecas, a extensão .so é similar aos arquivos .dll utilizados em um sistema
operacional Windows ou um arquivo .dylib utilizado em um Mac.
40
Deve-se realizar a configuração do ambiente de desenvolvimento para utilização,
compilação e execução do código através da IDE Eclipse ou até mesmo para execução por linha
de comando através de comandos como javac e java. Para os testes deste trabalho a
configuração do ambiente foi realizada pela inclusão dos arquivos da biblioteca JCuda em
variável de ambiente CLASSPATH e pela definição de variáveis de ambiente CUDA
(CUDA_HOME) e inclusão do executável CUDA (download do site da nvidia) em caminho de
execução (PATH).
As bibliotecas que compõe o JCuda são:
JCublas: é vinculada a biblioteca cuBLAS (NVIDIA CUDA Basic Linear Algebra
Subroutines), utilizada principalmente para operações com vetores e/ou
matrizes matemáticas.
JCufft: permite utilizar a biblioteca cuFFT (NVIDIA CUDA Fast Fourier
Transform), como o nome já diz, fornece métodos para implementar e calcular
transformadas de Fourier.
JCudpp: está relacionada a biblioteca cuDPP (NVIDIA CUDA Data Parallel
Primitive), contém métodos básicos que realizam cálculos paralelos primitivos,
como operações com vetores/matrizes de dados, ordenação de dados,
manutenção de hash table, entre outros dados considerados primitivos.
JCurand: realiza a interface com a biblioteca cuRAND (NVIDIA CUDA Random
Number Generator), que gera valores aleatórios, utilizada que pode ser
utilizada principalmente para testes de performance.
JCusparse: faz a comunicação com biblioteca cuSPARSE (NVIDIA CUDA Sparse
Matrix), com funções e APIs para operações com matrizes esparsadas.
Podemos realizar testes de performance CUDA de duas maneiras distintas, um modo é
adaptar todas as classes criadas e mostradas na seção de algoritmo para ao invés de utilizar as
operações matemáticas de doubles de maneira convencional, utilizar as funções
disponibilizadas em biblioteca CUDA. Uma outra abordagem que podemos utilizar é adaptar a
classe Precificador.java para ao invés de realizar o cálculo uma vez, realizar o cálculo de
diversos contextos de precificação, com diferentes dados de mercado e de volatilidade. Desta
maneira precisamos criar um objeto que possui estes três parâmetros e armazena-los em uma
estrutura de dados, como um vetor ou uma coleção (ArrayList). Não existe maneira ideal para
realizar um teste que se aproxime de um caso que possa ser vivenciado ou aplicado em uma
empresa, os dois casos possuem alguns prós e contras.
A substituição de todos as classes e funções de cálculo garantem o máximo de
performance utilizando uma GPU pois as operações com primitivos serão realizadas na GPU,
mas podemos apontar alguns problemas com esta abordagem: alterar os métodos de cálculo
podem fazer com que a calculadora de precificação fique errada, isto é, temos toda uma
estrutura que faz um cálculo correto e estável em diversos clientes, alterar estas funções
podemos causar uma instabilidade, fazendo com que o cálculo de um valor errado. Para
garantir uma manutenção correta precisamos de diversos testes que validem esta calculadora
em diversos cenários possíveis. No teste apresentado neste trabalho temos diversas funções e
classes que realizam um cálculo de uma call com uma metodologia, em um sistema real
41
deveríamos implementar o cálculo tanto de uma call quanto de uma put e devemos
disponibilizar o cálculo por outras aproximações, como Monte Carlo, Black-Scholes-Merton,
etc. Com isto deveríamos adaptar todas as calculadoras e garantir que todas estas alterações
fiquem corretas. Um outro problema é o mais básico de todos e está vinculado as estruturas
primitivas utilizadas, os cálculos apresentados na seção de algoritmo foram realizados com
double, caso as contas envolvessem a utilização de BigDecimal, um primitivo inexistente em C,
este tipo de adaptação seria feito em duas etapas, transformação para double e em seguida
para funções CUDA, este último problema pode causar graves distorções principalmente em
questão de arredondamento.
Alterar a classe principal, que chama o cálculo de opção, para realizamos diversos
cálculos através de um vetor ou coleção tem pontos positivos e negativos. O ponto positivo é a
alteração em uma quantidade bem menor de código e caso tivéssemos outras calculadoras
que utilizam outros métodos ou uma calculadora que faz as contas para uma put não
precisaríamos alterar elas também. Um ponto negativo, mas que não pode ser evidenciado
pelo algoritmo explicitado, é que o resultado da precificação, apresentado em tela no
algoritmo do tópico anterior, também será armazenado em uma estrutura de dados, como um
vetor ou coleção. Esta alteração apresenta um grande problema que é a alteração da
assinatura de resposta do método, o valor calculado pelo algoritmo é utilizado futuramente,
seja para apresentação em relatórios gerenciais ou para cálculos de risco e resultado. Se
alterarmos o método de um único valor escalar para uma estrutura devemos alterar todos as
outras classes que utilizam esta precificação.
Pelos pontos expostos acima, nenhum método seria ideal para adaptar ou converter
um sistema já existente para utilizar uma GPU, pois o custo para efetivar esta manutenção
seria extremamente alto. Desta maneira verificamos que a utilização de programação CUDA é
recomendada no caso de construir um sistema do zero e tendo como requisito utilizar a
tecnologia de GPUs.
Para o escopo e objetivos deste trabalho, que é apresentar melhoras com cálculos
financeiros através de linguagem de programação CUDA, também temos prós e contras com as
duas abordagens distintas. Adaptar todos algoritmos de cálculo para operações matemáticas
em CUDA é mais trabalhoso e não temos uma preocupação em relação a incompatibilidade da
assinatura e teríamos uma vantagem de realizar testes de performance para diversos cenários,
todos estes pontos levariam a uma abordagem de alterar a estrutura de precificação para
utilizar um vetor ou coleção. Mas o objetivo deste trabalho é apresentar melhoras do cálculo
financeiro, ao mudar a estrutura não estaríamos validando o algoritmo de cálculo financeiro,
mas sim uma melhora de performance devido a estrutura de dados utilizada. Logo, os
resultados que iremos apresentar se baseiam em adaptação do código java apresentado
anteriormente de modo que as operações matemáticas básicas sejam alteradas para utilizar
JCuda.
Dado o exposto acima, apresentamos inicialmente o tempo de execução do algoritmo
de cálculo apresentado no tópico anterior. Para estes testes realizamos a execução do código
21 vezes consecutivas, ignorando o primeiro resultado, pois normalmente a primeira execução
apresenta uma latência maior devido a compilação inicial do código.
Número da execução Tempo de execução em mili-segundos (ms)
1 20
42
2 18
3 18
4 23
5 24
6 19
7 21
8 27
9 19
10 23
11 20
12 19
13 21
14 22
15 26
16 19
17 23
18 21
19 20
20 27
Tabela 7-1 - Tempo de execução do algoritmo em Java
Da tabela de resultados, verificamos que o tempo médio de execução do algoritmo
em Java é de: 21,5 ms. Um tempo muito rápido para a quantidade de cálculos executados.
Com o código alterado/replicado utilizando a biblioteca JCUda, temos os seguintes
resultados:
Número da execução Tempo de execução em mili-segundos (ms)
1 18
2 19
3 21
4 22
5 19
6 18
7 20
43
8 21
9 22
10 20
11 18
12 17
13 20
14 18
15 19
16 18
17 21
18 22
19 23
20 22
Tabela 7-2 - Tempo de execução com JCuda
Da tabela verificamos um tempo médio de 19,9 ms. A tendência seria afirmar que
obtivemos uma melhora no tempo de execução, no entanto esta diferença é pequena e está
dentro da margem de erro da execução em Java, não sendo possível afirmar que obtivemos
um ganho de performance com a execução. Verificado os valores da tabela a única coisa que
podemos afirmar é uma maior concentração dos resultados utilizando JCuda em torno da
média, enquanto a execução em Java possui alguns dados discrepantes. Caso ignorássemos
estes valores discrepantes, o valor médio seria mais próximo, logo não podemos afirmar um
ganho de performance em relação a estes cálculos.
Estes resultados, de certa forma são esperados, pois o maior custo de performance em
linguagem de programação Java é em relação a consulta/escrita em bancos de dados, como os
algoritmos de cálculos utilizam somente cálculos matemáticos e estes já são otimizados devido
à larga utilização, não conseguimos um ganho considerável no tempo de execução. Caso
utilizássemos uma abordagem de estrutura de dados (vetores/lista), provavelmente os valores
obtidos seriam melhores para evidenciar um ganho no desempenho, mesmo sem utilizar
tabelas em banco de dados.
É importante frisar que os resultados obtidos não invalidam a importância, já
demonstrada em outros trabalhos, de utilização de GPUs e da programação CUDA. Mas ao
realizar um trabalho destes, deve-se ter em mente qual a melhor maneira de obter máximo
ganho com as GPUs, através da arquitetura da placa, aplicação e modo de uso.
8. Bibliografia [1] https://www.bcb.gov.br/?SFNCOMP e links derivados a partir deste. Acessado
em agosto/2014
44
[2] https://www.bcb.gov.br/?SPB e links derivados a partir deste. Acessado em
agosto/2014
[3] CVM – Comissão de Valores Mobiliários. Mercado de Valores Mobiliários
Brasileiro. 3ed, 2014
[4] HULL, John C. Options, Futures and Other Derivatives. Prentice Hall. 8th ed,
2012.
[5]
http://www.bmfbovespa.com.br/Sumario2.aspx?menu=2&sitemap=22230&idiom
a=pt-br
[6] http://www.cetip.com.br/coe. Acessado em setembro/2014.
[7] HAUG, Espen G. The Complete Guide to Option Pricing Formulas. McGraw-Hill.
2nd ed, 2006.
[8] http://www.anbima.com.br/merc_sec/resultados/msec_14out2014_ntn-b.asp.
Acessado em 14/10/2014.
[9] http://www.nvidia.com.br/object/w21hat-is-gpu-computing-br.html, acessado
em 14/10/201422
[10] http://en.wik20ipedia.org/wiki/OpenCL, acessado em 14/10/2014
[11] http://www.nvi18dia.com.br/object/cuda_home_new_br.html, acessado em
14/10/201417
[12] http://ww20w.jcuda.org/, acessado em 03/11/2014