σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
Roteiros
AO
+1,2 mil alunos
Entrar
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Roteiro de Python›Módulo 4 · Precificação de renda fixa e opções›Tópico 4.3·~45 minIntermediário

Rendimento até o vencimento

Posição no roteiroMódulo 4 de 11 · Tópico 3 de 16
4.3 Rendimento até o vencimento
—Nota do lab— / 100XP total—Sequência—

Do preço de volta ao rendimento

No mercado um título é cotado pelo preço, mas os investidores comparam títulos pelo rendimento. O rendimento até o vencimento (YTM) é a única taxa de desconto em que o valor presente de todos os fluxos do título iguala seu preço: o retorno anualizado que você obtém se comprar agora, mantiver até o vencimento e todos os pagamentos forem feitos. Para um título de 10 anos com preço 925,61 e cupom de 5%, é 6%. Ao contrário do preço, o YTM não tem fórmula fechada, porque a incógnita está dentro de um polinômio de grau alto.

import numpy as np

def bond_price(face, coupon_rate, ytm, years, freq=2):
    n = int(round(years * freq))
    times = np.arange(1, n + 1) / freq
    flows = np.full(n, face * coupon_rate / freq)
    flows[-1] += face
    return (flows / (1 + ytm / freq) ** (freq * times)).sum()

price = bond_price(1000, 0.05, 0.06, 10)
print(round(price, 4))                                       # 925.6126   the market price we pretend to observe

# A back-of-the-envelope yield: annual coupon plus the yearly share of the discount, over the average of price and par
coupon = 1000 * 0.05
print(round((coupon + (1000 - price) / 10) / ((1000 + price) / 2), 5))     # 0.05966   close to 6%, but not exact

Procurar: bisseção

O preço cai de forma contínua à medida que o rendimento sobe, então dá para procurar. Tome um intervalo [low, high] que certamente contém a resposta (0% a 100%). Precifique o título no ponto médio: se o preço está acima do alvo, o rendimento deve ser maior, então suba low para o ponto médio; senão, desça high. Cada passo divide o intervalo ao meio; 40 passos o reduzem por um fator de um trilhão. A bisseção é lenta comparada a outros métodos, mas não pode falhar enquanto a resposta estiver no intervalo, o que a torna o recurso seguro.

low, high = 0.0, 1.0
for step in range(6):
    mid = (low + high) / 2
    price_mid = bond_price(1000, 0.05, mid, 10)
    print(step, round(mid, 5), round(price_mid, 2))
    if price_mid > price:      # priced too high: the yield must be higher
        low = mid
    else:
        high = mid
# 0 0.5 110.38
# 1 0.25 275.86
# 2 0.125 578.47
# 3 0.0625 908.08
# 4 0.03125 1159.97
# 5 0.04688 1024.72      the interval keeps shrinking around 6% (the target price is 925.61)

Procurar mais rápido: Newton

O método de Newton usa a inclinação. Defina f(y) = bond_price(y) - alvo; queremos f(y) = 0. No palpite atual, siga a tangente até zero: y_new = y - f(y) / f'(y). A inclinação pode ser estimada numericamente com um passo minúsculo h: (f(y + h) - f(y - h)) / (2h). Perto da resposta o número de dígitos corretos mais ou menos dobra a cada passo, então quatro ou cinco passos bastam onde a bisseção precisa de quarenta. Newton pode falhar se começar mal ou se a inclinação for plana, então mantenha um limite de passos e volte à bisseção se não convergir.

y, h = 0.05, 1e-6                            # start at the coupon rate
for step in range(5):
    f = bond_price(1000, 0.05, y) - price
    slope = (bond_price(1000, 0.05, y + h) - bond_price(1000, 0.05, y - h)) / (2 * h)
    print(step, round(y, 8), round(f, 6))
    y = y - f / slope
# 0 0.05 74.387374
# 1 0.05954347 3.245932
# 2 0.05999903 0.006916
# 3 0.06 0.0
# 4 0.06 0.0        converged to 6% after 3 steps
# Check the answer by pricing the bond at the yield we found
print(round(bond_price(1000, 0.05, y, 10), 4), round(price, 4))      # 925.6126 925.6126   the same price: the yield is right
Rendimentos são comparáveis, preços nãoUm rendimento até o vencimento supõe que você pode reinvestir cada cupom ao mesmo rendimento e que o emissor paga integralmente, então é uma promessa, não uma previsão. Um título negociado a um rendimento muito alto costuma ser um do qual o mercado duvida que será pago. Compare rendimentos apenas entre títulos de risco e prazo semelhantes.
  • O YTM é a taxa de desconto que iguala o valor presente do título ao seu preço; não tem fórmula fechada, então é procurado.
  • Bisseção: continue dividindo [low, high] ao meio (preço acima do alvo: suba low); lenta, mas segura.
  • Newton: y = y - f / slope, com inclinação numérica; converge em poucos passos mas precisa de um limite de passos e um bom início.

A seguir: a duração e a convexidade, medindo a sensibilidade do preço de um título ao rendimento.

Lab: o que é avaliado

  • Estimar o rendimento de cabeça com approx_ytm25 pts
  • Achar o rendimento dividindo o intervalo ao meio com bisect_yield25 pts
  • Achar o rendimento mais rápido com newton_yield25 pts
  • Dar nome à situação do título com classify_price25 pts
Explorador · lab-68-1
▾ lab-68-1
…
bash · no navegador
learner@quantcraft:~/lab-68-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-68-1 volta aos arquivos iniciais e o terminal é limpo. Sua solução atual será perdida — isso não pode ser desfeito.

Será redefinido
  • main.py → código inicial
  • Histórico do terminal e saída dos testes
  • Alterações não enviadas
Será mantido
  • Melhor nota do lab
  • Seu XP e sua sequência
  • Progresso da aula e anotações

Entre para executar o seu código.

Todas as aulas são gratuitas para ler. Crie uma conta ou entre para executar código, rodar os testes e enviar este lab.

  • IDE no navegador com terminal bash — nada para instalar
  • Correção instantânea, XP e o seu lugar no roteiro
Criar uma contaEntrar
OU
Continuar com o GitHub