Un tipo por vencimiento
Hasta ahora un único rendimiento descontaba todos los pagos de un bono. En realidad el dinero prestado a 6 meses, 2 años y 10 años gana tipos distintos, y el patrón por vencimientos es la curva de tipos. Un tipo cupón cero es el tipo anual de un único pago en una fecha dada, sin cupones intermedios. Normalmente la curva sube con el vencimiento (los inversores quieren más por esperar más), pero puede ser plana o invertida, cuando los tipos cortos superan a los largos, lo que los mercados leen como una señal de alarma sobre el crecimiento.
import numpy as np
maturities = np.array([0.5, 1, 2, 5, 10, 30]) # years where the market quotes a rate
rates = np.array([0.040, 0.042, 0.045, 0.048, 0.050, 0.052]) # an upward-sloping curve
# The rate at 3 years is not quoted: interpolate linearly between 2 years (4.5%) and 5 years (4.8%)
print(float(np.interp(3, maturities, rates))) # 0.046
print(np.interp([0.25, 7, 40], maturities, rates).tolist()) # [0.04, 0.0488, 0.052] flat outside the quoted rangeFactores de descuento y tipo a plazo
Un tipo cupón cero r para el vencimiento t da el factor de descuento (1 + r) ** -t: lo que vale hoy una unidad pagada en t. La curva también esconde expectativas. Prestar 2 años al 4,5 % debe igualar prestar 1 año al 4,2 % y volver a prestar un año a un tipo pactado f: (1 + 4,5 %)² = (1 + 4,2 %)(1 + f), así que f = 4,80 %. Ese tipo a plazo (forward) es el tipo de equilibrio del segundo año, fijado hoy. En general f = ((1 + r2) ** t2 / (1 + r1) ** t1) ** (1 / (t2 - t1)) - 1.
def discount_factor(rate, t):
return (1 + rate) ** -t
print(round(float(discount_factor(0.045, 2)), 5)) # 0.91573 one unit paid in 2 years
r1, t1, r2, t2 = 0.042, 1, 0.045, 2
forward = ((1 + r2) ** t2 / (1 + r1) ** t1) ** (1 / (t2 - t1)) - 1
print(round(forward, 5)) # 0.04801 the rate for year 2, implied by the curve
print(round((1 + r1) ** t1 * (1 + forward) ** (t2 - t1), 5), round((1 + r2) ** t2, 5)) # 1.09 1.09 both routes agreeValorar sobre toda la curva
Valorar con un único rendimiento trata igual un pago a 1 año y uno a 10 años. El enfoque por curva es más fiel: para cada pago lee el tipo cupón cero de su propia fecha (interpolando si hace falta), conviértelo en factor de descuento y suma flujo * factor. Dos bonos con los mismos flujos deben tener el mismo precio sean cuales sean sus rendimientos cotizados, y así valoran los bancos los bonos a mercado. Para un bono a 3 años del 5 % en nuestra curva el precio es 1011,25, frente a 1010,98 con un 4,6 % plano: cerca aquí porque la curva es suave, pero distintos bonos reaccionan de forma distinta cuando la curva se retuerce.
times = np.array([1.0, 2.0, 3.0])
flows = np.array([50.0, 50.0, 1050.0]) # a 3-year 5% bond with annual coupons
zero = np.interp(times, maturities, rates)
print(zero.tolist()) # [0.042, 0.045, 0.046]
print((discount_factor(zero, times)).round(5).tolist()) # [0.95969, 0.91573, 0.87379]
print(round(float((flows * discount_factor(zero, times)).sum()), 4)) # 1011.2462 on the curve
print(round(float((flows / 1.046 ** times).sum()), 4)) # 1010.9752 with one flat 4.6% instead# The forward rates between the quoted maturities, in one array expression
t = np.array([1.0, 2.0, 5.0])
r = np.array([0.042, 0.045, 0.048])
forwards = ((1 + r[1:]) ** t[1:] / (1 + r[:-1]) ** t[:-1]) ** (1 / np.diff(t)) - 1
print(forwards.round(5).tolist()) # [0.04801, 0.05] year 2 and years 3 to 5: an upward-sloping curve implies rising forwardsnp.interp mantiene el tipo plano, lo que es una convención, no un hecho. Indica el método siempre que publiques una curva.- Una curva de tipos es el tipo cupón cero por vencimiento; lee los vencimientos que faltan por interpolación (
np.interp, plano fuera del rango). - Factor de descuento
(1 + r) ** -t; tipo a plazo((1 + r2) ** t2 / (1 + r1) ** t1) ** (1 / (t2 - t1)) - 1. - Precio = suma de
flujo * factor de descuento, cada flujo al tipo cupón cero de su fecha; indica el método de interpolación.
A continuación: los pagos de las opciones, lo que paga un call o un put al vencimiento, punto de partida de la valoración de opciones.
Lab: qué se califica
- Leer un tipo entre los vencimientos cotizados con
interpolate_rate25 pts - Convertir un tipo en factor de descuento con
discount_factor25 pts - Leer el tipo futuro oculto en la curva con
forward_rate25 pts - Valorar un flujo de pagos sobre toda la curva con
price_on_curve25 pts