Curves¶
Discount curve construction and interpolation. All curve objects are equinox.Module pytrees — fully differentiable for key-rate duration computation.
DiscountCurve¶
class DiscountCurve(eqx.Module):
pillar_dates: Int[Array, "n_pillars"] # sorted ordinal dates
discount_factors: Float[Array, "n_pillars"] # DF at each pillar
reference_date: Int[Array, ""] # valuation date
day_count: str = "act_365" # static field
Fields:
| Field | Type | Static | Description |
|---|---|---|---|
pillar_dates |
Int[Array, "n"] |
No | Ordinal dates for curve nodes, sorted ascending. |
discount_factors |
Float[Array, "n"] |
No | Discount factors at each pillar. First should be 1.0. Differentiable. |
reference_date |
Int[Array, ""] |
No | Valuation date as ordinal. |
day_count |
str |
Yes | Day count convention name. |
Interpolation: Log-linear (linear in log-DF space), equivalent to piecewise-constant continuously-compounded forward rates. Flat extrapolation beyond curve range.
Usage:
# Callable — interpolate at arbitrary dates
df = curve(date) # single date
dfs = curve(date_array) # vectorized
Differentiability
discount_factors are differentiable leaves. jax.grad through any function that uses a DiscountCurve gives sensitivities to each pillar — this is how key-rate durations work.
forward_rate¶
Simply-compounded forward rate between two ordinal dates:
\[F(t_1, t_2) = \frac{DF(t_1)/DF(t_2) - 1}{\tau(t_1, t_2)}\]
zero_rate¶
Continuously-compounded zero rate to a given date:
\[r(t) = -\frac{\ln DF(t)}{\tau(\text{ref}, t)}\]