σμ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 AcademyRutas
Ctrl K
AO
+1,2 k estudiantes
Iniciar sesiónUnirse ↗
Rutas
AO
+1,2 k estudiantes
Iniciar sesión
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Ruta de Python›Módulo 4 · Valoración de renta fija y opciones›Tema 4.5·~50 minIntermedio

Curvas de rendimiento e interpolación

Posición en la rutaMódulo 4 de 11 · Tema 5 de 16
4.5 Curvas de rendimiento e interpolación
—Puntuación del lab— / 100XP total—Racha—

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 range

Factores 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 agree

Valorar 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 forwards
La interpolación es una decisión de modeladoLa interpolación lineal de tipos cupón cero es la regla más simple, pero no la única: los profesionales también interpolan logaritmos de factores de descuento o usan splines, y la elección cambia los tipos a plazo y los precios entre los puntos cotizados. Más allá del último vencimiento cotizado np.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
Explorador · lab-70-1
▾ lab-70-1
…
bash · en el navegador
learner@quantcraft:~/lab-70-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-70-1 vuelve a los archivos iniciales y se limpia el terminal. Tu solución actual se perderá: no se puede deshacer.

Se restablecerá
  • main.py → código inicial
  • Historial del terminal y salida de pruebas
  • Cambios sin enviar
Se conservará
  • Mejor puntuación del lab
  • Tu XP y tu racha
  • Progreso de la lección y notas

Inicia sesión para ejecutar tu código.

Todas las clases se pueden leer gratis. Crea una cuenta o inicia sesión para ejecutar código, lanzar las pruebas y enviar este lab.

  • IDE en el navegador con terminal bash — sin instalar nada
  • Corrección instantánea, XP y tu lugar en la ruta
Crear una cuentaIniciar sesión
O
Continuar con GitHub