<jupyter_start><jupyter_text>Modelo Binomial - Derivativos  Inputs  Importar Pacotes<jupyter_code>import pandas as pd
import numpy as np
import yfinance as yf<jupyter_output><empty_output><jupyter_text>Série Histórica do Ativo<jupyter_code>inicio = "2020-12-31" # trocar
fim = pd.to_datetime("today") # data atual (retorna o dia de hoje, mas pode ser uma data qualquer)
ativo = "BBDC4.SA"
dados = yf.download(start = inicio, end = fim, tickers = ativo)
dados["retorno"] = dados["Adj Close"].pct_change()
dados.dropna(inplace = True)<jupyter_output>[*********************100%***********************]  1 of 1 completed<jupyter_text>Características da Opção<jupyter_code>nome = "BBDCB234" # alterar
r = 0.0915 # taxa livre de risco - alterar
#S = dados.iloc[len(dados)-1]["Adj Close"] # preço spot
S = 22.60
X = 23.17 # strike da opção - alterar
dt = 15 # dias úteis até o vencimento - alterar
C0 = 0.44 # preço atual da opção - alterar<jupyter_output><empty_output><jupyter_text>Calculando os retornos médios para cenários de alta e baixa  Opção 1: Média dos valores obtidos para os retornos de alta e baixa na série histórica<jupyter_code>df = dados[["Adj Close", "retorno"]]
pd.options.mode.chained_assignment = None  # default='warn'

df["up"] = np.where(df["retorno"] >= 0, df["retorno"], 0) # retornos de alta
df["down"] = np.where(df["retorno"] < 0, df["retorno"], 0) # retornos de baixa

u = df[df["up"] != 0].mean()["up"] # média dos retornos de alta
d = df[df["down"] != 0].mean()["down"] # média dos retornos de baixa<jupyter_output><empty_output><jupyter_text>Opção 2: Volatilidade média do ativo incorporada a cenários de alta e baixa![image-3.png](attachment:image-3.png)<jupyter_code>df = dados[["Adj Close", "retorno"]]
pd.options.mode.chained_assignment = None

s = df["retorno"].std()
u = np.exp(s)
d = 1/u
u = u - 1
d = d - 1<jupyter_output><empty_output><jupyter_text>Calcula as probabilidades de alta ou baixa  Cálculo 1: proporção de retornos de alta em relação a todas as observações<jupyter_code>df["q"] = np.where(df["retorno"] >= 0, 1, 0) 
q = sum(df["q"])/len(df["q"])<jupyter_output><empty_output><jupyter_text>Cálculo 2: probabilidade de Cox-Rubinstein![image.png](attachment:image.png)<jupyter_code>q = (np.exp(r/252*dt) - d) / (u - d)<jupyter_output><empty_output><jupyter_text>Probabilidades de cada um dos cenários finais possíveis Cada cenário é uma sequência de altas (retorno = 1 + u) e baixas (retorno = 1 + d) com probabilidades de ocorrência q e 1-q, respectivamente.![image.png](attachment:image.png) Os cenários do meio podem ser alcançados de n formas diferentes, sendo n equivalente ao seu valor no triângulo de Pascal (onde cada número é a soma dos 2 anteriores a ele, vide imagem)![image-2.png](attachment:image-2.png)<jupyter_code>mults, probs = [], [] # valores dos nós finais da árvore, com suas probabilidades 
for i in range(dt+1):
    
    mult = ((1+u)**i)*((1+d)**(dt-i))
    mults.append(mult)
    
    prob = ((q)**i) * ((1-q) ** (dt-i))
    probs.append(prob)

# retorna as linhas do triangulo de pascal, só a última interessa
def tri_pascal(n): 
    linhas = [[1], [1,1]]
    for i in range(n-1):
        linha_ant = linhas[-1]

        linha_nova = [1]
        for j in range(i+1):
            num = linha_ant[j] + linha_ant[j+1]
            linha_nova.append(num)
        linha_nova.append(1)   

        linhas.append(linha_nova)
    return linhas

# multiplica a prob pelo valor da sua posição no triângulo de pascal
probabilidades = [probs[i] * tri_pascal(dt)[-1][i] for i in range(len(probs))]<jupyter_output><empty_output><jupyter_text>Valor esperado para o preço da opção<jupyter_code># Calculando os preços possíveis
precos = [i*S for i in mults]

# Preço final - strike
resultado_call = [X-i for i in precos]
resultado_put = [i-X for i in precos]

# Preço da call é igual ao resultado se ele for positivo
precos_calls = [i if i > 0 else 0 for i in resultado_call]
precos_puts = [i if i > 0 else 0 for i in resultado_put]

# média ponderada do preço esperado da call 
C = 0
for i in range(len(precos_calls)):
    C += precos_calls[i]*probabilidades[i]

P = 0
for i in range(len(precos_puts)):
    P += precos_puts[i]*probabilidades[i]

# descontando o preço pela taxa livre de risco
C = C * np.exp(-r*dt/252)
P = P * np.exp(-r*dt/252)<jupyter_output><empty_output><jupyter_text>Resultado<jupyter_code>pd.DataFrame({"Variável" : ["Ticker da Opção",
                            "Preço Spot do Ativo",
                            "Strike da Opção",
                            "Dias-úteis até o vencimento",
                            "Taxa Livre de Risco",
                            "Preço Atual da Opção",
                            "Preço Alvo da Opção de Compra",
                            "Preço Alvo da Opção de Venda"],
                 "Valor" : [nome,
                            "R$ {:2.2f}".format(S),
                            "R$ {:2.2f}".format(X),
                            str(dt),
                            "{:.2%}".format(r),
                            "R$ {:5.2f}".format(C0),
                            "R$ {:5.2f}".format(C),
                            "R$ {:5.2f}".format(P)]})<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1397002305918524, 'fraction_numerical': 0.01960030745580323, 'mean_word_length': 3.180722891566265, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '429713', 'license': 'MIT', 'n_tokens_mistral': 2037, 'n_tokens_neox': 1956, 'n_words': 509, 'path': 'modelo-binomial-trab.ipynb', 'repo_name': 'bruno-marcelino10/opcoes-modelo-binomial', 'size': '5204'}