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 maturityTí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.94freq) 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