σμ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.2·~45 minIntermediário

Preços de títulos

Posição no roteiroMódulo 4 de 11 · Tópico 2 de 16
4.2 Preços de títulos
—Nota do lab— / 100XP total—Sequência—

Um título é um fluxo de promessas

Um título é um empréstimo dividido em pedaços negociáveis. O emissor promete um cupom fixo a cada período e o valor de face (par) no vencimento. Um título de 10 anos com valor de face 1000 e cupom de 5% pago duas vezes ao ano promete 25 a cada seis meses e 1000 a mais no último pagamento. Seu preço é o que essas promessas valem hoje: o valor presente dos fluxos, descontados ao rendimento que o mercado exige atualmente para aquele risco e prazo.

import numpy as np

def bond_cashflows(face, coupon_rate, years, freq):
    n = int(round(years * freq))                       # number of payments
    times = np.arange(1, n + 1) / freq                 # in years: 0.5, 1.0, 1.5, ...
    flows = np.full(n, face * coupon_rate / freq)      # a coupon each time
    flows[-1] += face                                  # and the face value with the last one
    return times, flows

times, flows = bond_cashflows(1000, 0.05, 2, 2)        # a 2-year bond, to keep the output short
print(times.tolist())    # [0.5, 1.0, 1.5, 2.0]
print(flows.tolist())    # [25.0, 25.0, 25.0, 1025.0]

Preço e rendimento se movem em sentidos opostos

Desconte cada fluxo a (1 + ytm / freq) ** (freq * time) e some. Quando o rendimento é igual à taxa do cupom, o título vale exatamente seu valor de face (negocia ao par). Se os rendimentos de mercado sobem acima do cupom, os títulos novos pagam mais que este, então seu preço cai abaixo do par (um deságio); se caem, negocia com ágio. É o mesmo mecanismo do tópico anterior, agora com datas de pagamento reais. O rendimento corrente, cupom anual sobre preço, é uma medida rápida mas incompleta porque ignora o ganho ou a perda no vencimento.

def bond_price(face, coupon_rate, ytm, years, freq=2):
    times, flows = bond_cashflows(face, coupon_rate, years, freq)
    return (flows / (1 + ytm / freq) ** (freq * times)).sum()

for ytm in (0.03, 0.05, 0.06, 0.08):
    print(ytm, round(bond_price(1000, 0.05, ytm, 10), 2))
# 0.03 1171.69   yield below the coupon: premium
# 0.05 1000.0    yield = coupon: par
# 0.06 925.61    yield above the coupon: discount
# 0.08 796.15

print(round(50 / bond_price(1000, 0.05, 0.06, 10), 5))    # 0.05402   current yield: 5.40%, not the 6% yield to maturity

Títulos longos reagem mais

A variação relativa do preço para um dado movimento do rendimento depende do prazo. Pagamentos distantes são descontados por uma potência alta, então são muito sensíveis à taxa. Um título de 1 ano perde cerca de 1% quando os rendimentos sobem um ponto, um de 10 anos cerca de 7% e um de 30 anos quase 14%. Por isso os investidores em títulos falam de risco de taxa de juros e por isso os próximos tópicos constroem medidas (rendimento até o vencimento, duração) para quantificá-lo.

for years in (1, 5, 10, 30):
    change = bond_price(1000, 0.05, 0.06, years) / 1000 - 1     # the coupon is 5%, the yield rises to 6%
    print(years, round(change, 4))
# 1 -0.0096
# 5 -0.0427
# 10 -0.0744
# 30 -0.1384
# The same 6% yield with annual, semiannual and monthly coupons: the quoting convention matters a little
for freq in (1, 2, 12):
    print(freq, round(bond_price(1000, 0.05, 0.06, 10, freq), 2))
# 1 926.4
# 2 925.61
# 12 924.94
Os rendimentos cotados seguem uma convençãoUm rendimento de 6% com cupons semestrais não é uma taxa anual efetiva de 6%: capitaliza duas vezes ao ano, então sua taxa efetiva é 6,09%. Diga sempre a capitalização (freq) junto a um rendimento. Títulos reais também têm juros acumulados entre datas de cupom e convenções de contagem de dias, que este lab ignora ao precificar em datas de cupom.
  • Preço = soma de fluxo / (1 + ytm / freq) ** (freq * tempo); cupons a cada período, o valor de face com o último.
  • Rendimento = cupom: preço = par; rendimento acima do cupom: deságio; abaixo: ágio. Preço e rendimento se movem em sentidos opostos.
  • Quanto mais longo o prazo, maior a variação de preço para o mesmo movimento de rendimento: esse risco de juros é o que a duração mede a seguir.

A seguir: o rendimento até o vencimento, no sentido oposto: do preço de mercado de volta ao rendimento.

Lab: o que é avaliado

  • Listar os pagamentos de um título com bond_cashflows25 pts
  • Descontar os pagamentos até um preço com bond_price25 pts
  • Comparar o cupom com o preço com current_yield25 pts
  • Ver o efeito de um movimento de juros com price_change25 pts
Explorador · lab-67-1
▾ lab-67-1
…
bash · no navegador
learner@quantcraft:~/lab-67-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-67-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