API Reference

Curves

Discount factor, zero rate, forward rate, spread, composite, parametric, and implied curve classes.

All types are available via flat import:

from vade import DiscountCurve, LineCurve, ForwardCurve, SpreadCurve, CompositeCurve, TurnOfYearCurve, FXImpliedCurve, NelsonSiegel, NelsonSiegelSvensson, SmithWilson, IRImpliedCurve, CreditImpliedCurve, FittedBondCurve

See Conventions for all accepted string parameter values.

Contents: DiscountCurve | LineCurve | ForwardCurve | SpreadCurve | CompositeCurve | TurnOfYearCurve | FXImpliedCurve | NelsonSiegel | NelsonSiegelSvensson | SmithWilson | IRImpliedCurve | CreditImpliedCurve | FittedBondCurve

See also: Curve Building Guide for end-to-end curve construction workflows.


DiscountCurve

Discount factor curve with interpolated DF values. Rust-backed.

Constructor

DiscountCurve(nodes, *, interpolation="log_linear", id="curve", convention="act360", modifier="modified_following", calendar=None, t=None, endpoints="not_a_knot")

Parameters

NameTypeDefaultDescription
nodesNodeValuesrequiredDiscount factor nodes as {date: float} dict or ([dates], [values]) tuple. Positional-only.
interpolationstr"log_linear"Interpolation method for discount factors
idstr"curve"Curve identifier
conventionstr"act360"Day count convention for rate calculations
modifierstr"modified_following"Business day adjustment rule
calendarBusinessCalendar or NoneNoneBusiness day calendar
tlist[datetime.date] or NoneNoneKnot dates for B-spline interpolation
endpointsstr"not_a_knot"Endpoint condition for spline methods

NodeValues accepts Dict[datetime.date, float | Dual | Dual2] or Tuple[List[datetime.date], List[float | Dual | Dual2]].

See Conventions for accepted interpolation values. See Conventions for accepted convention values.

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date
.zero_rate(start, end)float | Dual | Dual2Continuously compounded zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)DiscountCurveParallel shift by bp basis points
.translate(days)DiscountCurveTranslate curve forward by N days
.roll(days)DiscountCurveRoll curve forward (time decay)
.to_json()strSerialize to JSON string
.from_json(s) (static)DiscountCurveDeserialize from JSON string

Return types are Union[float, Dual, Dual2] -- see the type system guide for when each variant appears.

Example

import datetime
from vade import DiscountCurve

nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.97,
    datetime.date(2026, 1, 1): 0.94,
}
curve = DiscountCurve(nodes, interpolation="log_linear", convention="act365f")

df = curve.discount_factor(datetime.date(2024, 7, 1))
assert 0.97 < df < 1.0  # interpolated mid-year discount factor

zr = curve.zero_rate(datetime.date(2024, 1, 1), datetime.date(2025, 1, 1))
assert 0.02 < zr < 0.04  # zero rate implied by DF=0.97

shifted = curve.shift(10)  # shift by 10 basis points

LineCurve

Value-based curve for zero rates, spreads, or other quantities. Rust-backed.

Constructor

LineCurve(nodes, *, interpolation="linear", id="curve", convention="act360", modifier="modified_following", calendar=None, t=None, endpoints="not_a_knot")

Parameters

NameTypeDefaultDescription
nodesNodeValuesrequiredValue nodes as {date: float} dict or ([dates], [values]) tuple. Positional-only.
interpolationstr"linear"Interpolation method
idstr"curve"Curve identifier
conventionstr"act360"Day count convention
modifierstr"modified_following"Business day adjustment rule
calendarBusinessCalendar or NoneNoneBusiness day calendar
tlist[datetime.date] or NoneNoneKnot dates for B-spline interpolation
endpointsstr"not_a_knot"Endpoint condition for spline methods

See Conventions for accepted interpolation values.

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date (derived from stored values)
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)LineCurveParallel shift by bp basis points
.translate(days)LineCurveTranslate curve forward by N days
.roll(days)LineCurveRoll curve forward (time decay)
.to_json()strSerialize to JSON string
.from_json(s) (static)LineCurveDeserialize from JSON string

Example

import datetime
from vade import LineCurve

nodes = {
    datetime.date(2024, 1, 1): 0.030,
    datetime.date(2025, 1, 1): 0.035,
    datetime.date(2026, 1, 1): 0.040,
}
curve = LineCurve(nodes, interpolation="linear", convention="act365f")

zr = curve.zero_rate(datetime.date(2024, 1, 1), datetime.date(2024, 7, 1))
assert 0.03 <= zr <= 0.035  # interpolated mid-year rate

fr = curve.forward_rate(datetime.date(2024, 1, 1), datetime.date(2025, 1, 1))
assert fr > 0  # positive forward rate

ForwardCurve

Forward rate curve with native forward rate representation. Rust-backed.

Nodes represent instantaneous forward rates (not discount factors). Uses Gauss-Legendre quadrature for discount factor integration.

Constructor

ForwardCurve(nodes, *, interpolation="flat_forward", id="forward_curve", convention="act365f", modifier="modified_following", calendar=None, t=None, endpoints="not_a_knot")

Parameters

NameTypeDefaultDescription
nodesNodeValuesrequiredForward rate nodes as {date: float} dict or ([dates], [values]) tuple. Positional-only.
interpolationstr"flat_forward"Interpolation method for forward rates
idstr"forward_curve"Curve identifier
conventionstr"act365f"Day count convention
modifierstr"modified_following"Business day adjustment rule
calendarBusinessCalendar or NoneNoneBusiness day calendar
tlist[datetime.date] or NoneNoneKnot dates for B-spline interpolation
endpointsstr"not_a_knot"Endpoint condition for spline methods

See Conventions for accepted interpolation values.

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date (integrated from forward rates)
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)ForwardCurveParallel shift by bp basis points
.translate(days)ForwardCurveTranslate curve forward by N days
.roll(days)ForwardCurveRoll curve forward (time decay)
.to_json()strSerialize to JSON string
.from_json(s) (static)ForwardCurveDeserialize from JSON string

Example

import datetime
from vade import ForwardCurve

# Instantaneous forward rates (per-day units matching internal x-axis)
nodes = {
    datetime.date(2024, 1, 1): 8.2e-5,
    datetime.date(2025, 1, 1): 9.0e-5,
    datetime.date(2026, 1, 1): 1.0e-4,
}
curve = ForwardCurve(nodes, interpolation="flat_forward", convention="act365f")

df = curve.discount_factor(datetime.date(2025, 1, 1))
assert 0.9 < df < 1.0  # discount factor integrated from forward rates

fr = curve.forward_rate(datetime.date(2024, 1, 1), datetime.date(2025, 1, 1))
assert 0.02 < fr < 0.04  # annualized forward rate

SpreadCurve

Spread curve: base curve plus additive or multiplicative spread. Rust-backed.

The base curve is passed as a JSON string (from curve.to_json()). Spread nodes are zero-rate spreads at specified dates.

Constructor

SpreadCurve(base_json, spread_nodes, *, mode="additive", spread_interpolation="linear", convention="act365f", id="spread_curve")

Parameters

NameTypeDefaultDescription
base_jsonstrrequiredJSON string of the base curve (from .to_json()). Positional-only.
spread_nodesNodeValuesrequiredSpread values as {date: float} dict or ([dates], [values]) tuple. Positional-only.
modestr"additive"Spread mode: "additive" or "multiplicative"
spread_interpolationstr"linear"Interpolation method for spread values
conventionstr"act365f"Day count convention
idstr"spread_curve"Curve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date (base + spread)
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.to_json()strSerialize to JSON string
.from_json(s) (static)SpreadCurveDeserialize from JSON string

Note: SpreadCurve does not support .shift(), .translate(), or .roll().

Example

import datetime
from vade import DiscountCurve, SpreadCurve

base_nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.97,
    datetime.date(2026, 1, 1): 0.94,
}
base = DiscountCurve(base_nodes, interpolation="log_linear", convention="act365f")
base_json = base.to_json()

spread_nodes = {
    datetime.date(2024, 1, 1): 0.001,
    datetime.date(2025, 1, 1): 0.002,
    datetime.date(2026, 1, 1): 0.003,
}
spread = SpreadCurve(base_json, spread_nodes, mode="additive")

df = spread.discount_factor(datetime.date(2025, 1, 1))
assert 0.9 < df < 1.0  # spread-adjusted discount factor

Advanced Example

Multiplicative mode and JSON roundtrip:

import datetime
from vade import DiscountCurve, SpreadCurve

# Base OIS curve with realistic discount factors
base = DiscountCurve(
    {
        datetime.date(2025, 6, 16): 1.0,
        datetime.date(2026, 6, 16): 0.9615,
        datetime.date(2027, 6, 16): 0.9240,
        datetime.date(2028, 6, 16): 0.8880,
    },
    interpolation="log_linear",
    convention="act360",
)

# Credit spread term structure (in zero-rate space)
spread_nodes = {
    datetime.date(2025, 6, 16): 0.005,
    datetime.date(2026, 6, 16): 0.008,
    datetime.date(2027, 6, 16): 0.012,
    datetime.date(2028, 6, 16): 0.015,
}

# Additive spread: zero_rate = base_zero_rate + spread
additive = SpreadCurve(base.to_json(), spread_nodes, mode="additive")
df_add = additive.discount_factor(datetime.date(2027, 6, 16))
assert 0.85 < float(df_add) < 0.95  # lower DF than base due to spread

# Multiplicative spread: discount_factor = base_df * spread_df
multiplicative = SpreadCurve(base.to_json(), spread_nodes, mode="multiplicative")
df_mult = multiplicative.discount_factor(datetime.date(2027, 6, 16))
assert 0.85 < float(df_mult) < 0.95

# JSON roundtrip preserves all parameters
restored = SpreadCurve.from_json(additive.to_json())
df_restored = restored.discount_factor(datetime.date(2027, 6, 16))
assert abs(float(df_restored) - float(df_add)) < 1e-12

See also: Curve Building Guide for spread curve usage in multi-curve frameworks.


CompositeCurve

Composite curve combining multiple curves. Rust-backed.

Discount factors are computed as the product of discount factors from all component curves.

Constructor

CompositeCurve(curves, id=None)

Parameters

NameTypeDefaultDescription
curveslistrequiredList of curve objects to combine
idstr or NoneNoneCurve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Product of component discount factors at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)CompositeCurveParallel shift by bp basis points
.translate(days)CompositeCurveTranslate curve forward by N days
.to_json()strSerialize to JSON string
.from_json(s) (static)CompositeCurveDeserialize from JSON string

Note: CompositeCurve does not support .roll().

Example

import datetime
from vade import DiscountCurve, CompositeCurve

nodes1 = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.98,
    datetime.date(2026, 1, 1): 0.96,
}
nodes2 = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.99,
    datetime.date(2026, 1, 1): 0.98,
}
curve1 = DiscountCurve(nodes1, convention="act365f")
curve2 = DiscountCurve(nodes2, convention="act365f")

composite = CompositeCurve([curve1, curve2])
df = composite.discount_factor(datetime.date(2025, 1, 1))
assert 0.96 < df < 0.98  # product of 0.98 * 0.99

Advanced Example

DF multiplicativity proof and IRS pricing with a composite funding curve:

import datetime
from vade import DiscountCurve, CompositeCurve, IRS

# OIS discount curve (risk-free rate ~4%)
ois = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2026, 6, 16): 0.9615,
     datetime.date(2027, 6, 16): 0.9240},
    convention="act360", id="ois",
)

# Funding spread curve (credit spread ~20bps)
spread = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2026, 6, 16): 0.998,
     datetime.date(2027, 6, 16): 0.996},
    convention="act360", id="spread",
)

# Composite = OIS x Spread (DF is product of components)
funding = CompositeCurve([ois, spread], id="funding")
df_composite = funding.discount_factor(datetime.date(2026, 6, 16))
df_ois = ois.discount_factor(datetime.date(2026, 6, 16))
df_spread = spread.discount_factor(datetime.date(2026, 6, 16))
assert abs(float(df_composite) - float(df_ois) * float(df_spread)) < 1e-10

# Use composite curve for IRS discounting
irs = IRS(
    effective=datetime.date(2025, 6, 16),
    termination="2y",
    frequency="s",
    convention="act360",
    fixed_rate=4.0,
    notional=10_000_000,
    currency="usd",
)
npv = irs.npv(funding)
assert isinstance(float(npv), float)

TurnOfYearCurve

Turn-of-year adjusted curve with date-specific bumps. Rust-backed.

The inner curve is passed as a JSON string (from curve.to_json()). Bumps are {date: bp_adjustment} for turn-of-year effects.

Constructor

TurnOfYearCurve(inner_json, bumps, *, convention="act365f", calendar=None, id="toy_curve")

Parameters

NameTypeDefaultDescription
inner_jsonstrrequiredJSON string of the inner curve (from .to_json()). Positional-only.
bumpsDict[datetime.date, float]requiredDate-specific basis point adjustments. Positional-only.
conventionstr"act365f"Day count convention
calendarBusinessCalendar or NoneNoneBusiness day calendar
idstr"toy_curve"Curve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date (inner + bumps)
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.to_json()strSerialize to JSON string
.from_json(s) (static)TurnOfYearCurveDeserialize from JSON string

Note: TurnOfYearCurve does not support .shift(), .translate(), or .roll().

Example

import datetime
from vade import DiscountCurve, TurnOfYearCurve

nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.97,
    datetime.date(2026, 1, 1): 0.94,
}
inner = DiscountCurve(nodes, interpolation="log_linear", convention="act365f")
inner_json = inner.to_json()

bumps = {
    datetime.date(2024, 12, 31): 5.0,
    datetime.date(2025, 12, 31): 3.0,
}
toy = TurnOfYearCurve(inner_json, bumps, convention="act365f")

df = toy.discount_factor(datetime.date(2025, 1, 1))
assert 0.9 < df < 1.0  # adjusted discount factor

Advanced Example

Year-end effect on discount factors and JSON roundtrip:

import datetime
from vade import DiscountCurve, TurnOfYearCurve

# Smooth underlying curve
inner = DiscountCurve(
    {
        datetime.date(2025, 6, 16): 1.0,
        datetime.date(2026, 6, 16): 0.9615,
        datetime.date(2027, 6, 16): 0.9240,
        datetime.date(2028, 6, 16): 0.8880,
    },
    interpolation="log_linear",
    convention="act365f",
)

# Year-end bumps in basis points (5bp at 2025 year-end, 3bp at 2026 year-end)
bumps = {
    datetime.date(2025, 12, 31): 5.0,
    datetime.date(2026, 12, 31): 3.0,
}
toy = TurnOfYearCurve(inner.to_json(), bumps, convention="act365f")

# Discount factors reflect year-end bumps
df_after_ye = toy.discount_factor(datetime.date(2026, 1, 2))
inner_df_after = inner.discount_factor(datetime.date(2026, 1, 2))

# TurnOfYear curve produces lower DFs than inner curve around year-end
assert float(df_after_ye) < float(inner_df_after)

# JSON roundtrip preserves bumps
restored = TurnOfYearCurve.from_json(toy.to_json())
df_check = restored.discount_factor(datetime.date(2026, 1, 2))
assert abs(float(df_check) - float(df_after_ye)) < 1e-12

See also: Curve Building Guide for incorporating turn-of-year effects in curve construction.


FXImpliedCurve

Proxy curve for FX-adjusted discounting. Rust-backed.

Used in cross-currency frameworks where discounting in one currency is proxied through another via FX rates and interest rate differentials.

See also: FX Rates & Forwards Guide for FX implied curve construction.

Constructor

FXImpliedCurve(cashflow_ccy, collateral_ccy, fx_rates, fx_settlements, collateral_curve, cashflow_curve, id=None)

Parameters

NameTypeDefaultDescription
cashflow_ccystrrequiredCurrency of the cashflows (e.g., "eur")
collateral_ccystrrequiredCurrency of the collateral (e.g., "usd")
fx_ratesFXRatesrequiredFX rates object for currency conversion
fx_settlementsDict[str, datetime.date]requiredSettlement dates per currency
collateral_curveDiscountCurverequiredDiscount curve in collateral currency
cashflow_curveDiscountCurverequiredDiscount curve in cashflow currency
idstr or NoneNoneCurve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2FX-adjusted discount factor at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)FXImpliedCurveParallel shift by bp basis points
.translate(days)FXImpliedCurveTranslate curve forward by N days
.to_json()strSerialize to JSON string
.from_json(s) (static)FXImpliedCurveDeserialize from JSON string

Note: FXImpliedCurve does not support .roll().

Example

import datetime
from vade import DiscountCurve, FXRates, FXImpliedCurve

usd_nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.96,
    datetime.date(2026, 1, 1): 0.92,
}
eur_nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.97,
    datetime.date(2026, 1, 1): 0.94,
}
usd_curve = DiscountCurve(usd_nodes, convention="act365f", id="usd")
eur_curve = DiscountCurve(eur_nodes, convention="act365f", id="eur")

fx = FXRates({"eurusd": 1.10}, datetime.date(2024, 1, 1))
settlements = {"usd": datetime.date(2024, 1, 3), "eur": datetime.date(2024, 1, 3)}

fx_implied = FXImpliedCurve("eur", "usd", fx, settlements, usd_curve, eur_curve)
df = fx_implied.discount_factor(datetime.date(2025, 1, 1))
assert 0.9 < float(df) < 1.0  # FX-adjusted discount factor (returns Dual due to FXRates AD)

NelsonSiegel

Nelson-Siegel parametric yield curve model. Rust-backed.

See also: Bootstrap & Parametric Guide for parametric curve fitting workflows.

Models the yield curve as a function of three factors (level, slope, curvature) with a single decay parameter tau.

Constructor

NelsonSiegel(beta0, beta1, beta2, tau, base_date, convention="act365f", id="")

Parameters

NameTypeDefaultDescription
beta0float | Dual | Dual2requiredLevel (long-term rate)
beta1float | Dual | Dual2requiredSlope (short-term component)
beta2float | Dual | Dual2requiredCurvature (medium-term hump)
taufloat | Dual | Dual2requiredDecay parameter
base_datedatetime.daterequiredBase date for the curve
conventionstr"act365f"Day count convention
idstr""Curve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)NelsonSiegelParallel shift by bp basis points
.translate(days)NelsonSiegelTranslate curve forward by N days
.roll(days)NelsonSiegelRoll curve forward (time decay)
.to_json()strSerialize to JSON string
.from_json(s) (static)NelsonSiegelDeserialize from JSON string

Example

import datetime
from vade import NelsonSiegel

ns = NelsonSiegel(
    beta0=0.05,
    beta1=-0.02,
    beta2=0.01,
    tau=1.5,
    base_date=datetime.date(2024, 1, 1),
    convention="act365f",
)

df = ns.discount_factor(datetime.date(2025, 1, 1))
assert 0.9 < df < 1.0  # discount factor from parametric model

zr = ns.zero_rate(datetime.date(2024, 1, 1), datetime.date(2034, 1, 1))
assert 0.04 < zr < 0.06  # long-term rate converges to beta0

NelsonSiegelSvensson

Nelson-Siegel-Svensson parametric yield curve model. Rust-backed.

Extends Nelson-Siegel with a second curvature term and decay parameter for more flexible curve shapes.

Constructor

NelsonSiegelSvensson(beta0, beta1, beta2, beta3, tau1, tau2, base_date, convention="act365f", id="")

Parameters

NameTypeDefaultDescription
beta0float | Dual | Dual2requiredLevel (long-term rate)
beta1float | Dual | Dual2requiredSlope (short-term component)
beta2float | Dual | Dual2requiredFirst curvature term
beta3float | Dual | Dual2requiredSecond curvature term
tau1float | Dual | Dual2requiredFirst decay parameter
tau2float | Dual | Dual2requiredSecond decay parameter
base_datedatetime.daterequiredBase date for the curve
conventionstr"act365f"Day count convention
idstr""Curve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)NelsonSiegelSvenssonParallel shift by bp basis points
.translate(days)NelsonSiegelSvenssonTranslate curve forward by N days
.roll(days)NelsonSiegelSvenssonRoll curve forward (time decay)
.to_json()strSerialize to JSON string
.from_json(s) (static)NelsonSiegelSvenssonDeserialize from JSON string

Example

import datetime
from vade import NelsonSiegelSvensson

nss = NelsonSiegelSvensson(
    beta0=0.05,
    beta1=-0.02,
    beta2=0.01,
    beta3=0.005,
    tau1=1.5,
    tau2=5.0,
    base_date=datetime.date(2024, 1, 1),
    convention="act365f",
)

df = nss.discount_factor(datetime.date(2025, 1, 1))
assert 0.9 < df < 1.0  # discount factor from parametric model

zr = nss.zero_rate(datetime.date(2024, 1, 1), datetime.date(2034, 1, 1))
assert 0.04 < zr < 0.06  # long-term rate converges to beta0

SmithWilson

Smith-Wilson parametric curve for regulatory yield curve extrapolation. Rust-backed.

Used in insurance regulation (e.g., Solvency II) for extrapolating yield curves beyond the last liquid point toward an ultimate forward rate (UFR).

Constructor

SmithWilson(dates, rates, ufr, alpha, base_date, convention="act365f", id="")

Parameters

NameTypeDefaultDescription
dateslist[datetime.date]requiredKnot dates for observed rates
rateslist[float]requiredObserved zero rates at knot dates
ufrfloatrequiredUltimate forward rate (long-term target rate)
alphafloatrequiredSpeed of convergence to UFR
base_datedatetime.daterequiredBase date for the curve
conventionstr"act365f"Day count convention
idstr""Curve identifier

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)SmithWilsonParallel shift by bp basis points
.translate(days)SmithWilsonTranslate curve forward by N days
.roll(days)SmithWilsonRoll curve forward (time decay)
.to_json()strSerialize to JSON string
.from_json(s) (static)SmithWilsonDeserialize from JSON string

Example

import datetime
from vade import SmithWilson

sw = SmithWilson(
    dates=[
        datetime.date(2025, 1, 1),
        datetime.date(2029, 1, 1),
        datetime.date(2034, 1, 1),
        datetime.date(2044, 1, 1),
    ],
    rates=[0.030, 0.032, 0.035, 0.038],
    ufr=0.035,
    alpha=0.1,
    base_date=datetime.date(2024, 1, 1),
    convention="act365f",
)

df = sw.discount_factor(datetime.date(2029, 1, 1))
assert 0.8 < df < 1.0  # discount factor from Smith-Wilson model

zr = sw.zero_rate(datetime.date(2024, 1, 1), datetime.date(2029, 1, 1))
assert 0.02 < zr < 0.05  # zero rate at 5-year point

IRImpliedCurve

Implied curve for bucket-level delta risk reporting. Rust-backed.

Constructs a curve from a source DiscountCurve with custom tenor buckets. Used to compute bucket-level risk sensitivities.

See also: Risk Guide for IRImpliedCurve usage in delta/gamma computation.

Constructor

IRImpliedCurve(source, ref_date, tenors, calendar, convention="act365f")

Parameters

NameTypeDefaultDescription
sourceDiscountCurverequiredSource discount curve to re-bucket
ref_datedatetime.daterequiredReference date for tenor resolution
tenorslist[str]requiredTenor bucket labels (e.g., ["1Y", "2Y", "5Y", "10Y"])
calendarBusinessCalendarrequiredCalendar for tenor date resolution
conventionstr"act365f"Day count convention

See Conventions for tenor string format.

Methods

MethodReturnsDescription
.discount_factor(date)float | Dual | Dual2Discount factor at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.bucket_delta(instrument)polars.DataFrameCompute bucket-level delta risk for an instrument
.tenor_labels()list[str]Return the tenor bucket labels

Note: IRImpliedCurve does not support .shift(), .translate(), .roll(), .to_json(), or .from_json().

Example

import datetime
from vade import DiscountCurve, IRImpliedCurve, BusinessCalendar

nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.97,
    datetime.date(2026, 1, 1): 0.94,
    datetime.date(2029, 1, 1): 0.85,
    datetime.date(2034, 1, 1): 0.72,
}
source = DiscountCurve(nodes, interpolation="log_linear", convention="act365f")

implied = IRImpliedCurve(
    source=source,
    ref_date=datetime.date(2024, 1, 1),
    tenors=["1Y", "2Y", "5Y", "10Y"],
    calendar=BusinessCalendar("NYC"),
)

implied.tenor_labels()  # ['1Y', '2Y', '5Y', '10Y']

df = implied.discount_factor(datetime.date(2025, 1, 1))
assert 0.96 < df < 0.98  # consistent with source curve

CreditImpliedCurve

Credit implied curve with piecewise flat hazard rates. Rust-backed.

Models credit risk through survival probabilities derived from hazard rates. Used for CDS pricing and credit risk analysis.

See also: Credit Curves & CDS Guide for credit curve calibration workflows.

Constructor

CreditImpliedCurve(nodes, convention="act360", recovery_rate=0.4, id="credit_curve")

Parameters

NameTypeDefaultDescription
nodesNodeValuesrequiredSurvival probability nodes as {date: float} dict or ([dates], [values]) tuple
conventionstr"act360"Day count convention
recovery_ratefloat0.4Recovery rate assumption (0.0 to 1.0)
idstr"credit_curve"Curve identifier

Properties

PropertyTypeDescription
.idstrCurve identifier
.recovery_ratefloatRecovery rate assumption

Methods

MethodReturnsDescription
.survival_probability(date)float | Dual | Dual2Survival probability at date
.discount_factor(date)float | Dual | Dual2Discount factor at date
.zero_rate(start, end)float | Dual | Dual2Zero rate between dates
.forward_rate(start, end)float | Dual | Dual2Forward rate between dates
.shift(bp)CreditImpliedCurveParallel shift by bp basis points
.translate(days)CreditImpliedCurveTranslate curve forward by N days
.to_json()strSerialize to JSON string
.from_json(s) (static)CreditImpliedCurveDeserialize from JSON string

Note: CreditImpliedCurve does not support .roll().

Example

import datetime
from vade import CreditImpliedCurve

nodes = {
    datetime.date(2024, 1, 1): 1.0,
    datetime.date(2025, 1, 1): 0.98,
    datetime.date(2026, 1, 1): 0.95,
    datetime.date(2029, 1, 1): 0.88,
}
credit = CreditImpliedCurve(nodes, convention="act360", recovery_rate=0.4)

sp = credit.survival_probability(datetime.date(2025, 1, 1))
assert 0.0 < sp < 1.0  # survival probability at 1 year

credit.id  # 'credit_curve'
credit.recovery_rate  # 0.4

FittedBondCurve

Parametric curve fitted to bond market prices via nonlinear least-squares. Python wrapper composing NS/NSS/SmithWilson fitting.

Fits a NelsonSiegel, NelsonSiegelSvensson, or SmithWilson curve to observed bond clean prices. Uses Levenberg-Marquardt optimization with inverse-duration weighting.

See also: Fitted Curves Guide for end-to-end fitting workflows.

Constructor

FittedBondCurve(bonds, clean_prices, settlement, model="NS", *, convention="act365f", base_date=None, weights=None, initial_params=None, max_iter=200, func_tol=1e-10, ufr=None, alpha=None, id="")

Parameters

NameTypeDefaultDescription
bondslist[FixedRateBond]requiredPortfolio of bonds to fit. Positional.
clean_priceslist[float]requiredObserved clean prices for each bond. Positional.
settlementdatetime.daterequiredSettlement/valuation date. Positional.
modelstr"NS"Model type: "NS" (Nelson-Siegel), "NSS" (Nelson-Siegel-Svensson), or "SW" (Smith-Wilson). Positional.
conventionstr"act365f"Day count convention for rate calculations
base_datedatetime.date or NoneNoneBase date for curve (defaults to settlement)
weightslist[float] or NoneNoneCustom fitting weights (overrides inverse-duration default)
initial_paramslist[float] or NoneNoneInitial parameter guess for optimizer
max_iterint200Maximum Levenberg-Marquardt iterations
func_tolfloat1e-10Function tolerance for convergence
ufrfloat or NoneNoneUltimate forward rate (required for SW model)
alphafloat or NoneNoneConvergence speed (required for SW model)
idstr""Curve identifier

Properties

PropertyTypeDescription
.rmsefloatRoot mean square pricing error
.convergedboolWhether optimization converged
.iterationsintNumber of iterations used
.objectivefloatFinal objective function value

Methods

MethodReturnsDescription
.discount_factor(date)floatDiscount factor at date
.zero_rate(start, end)floatZero rate between dates
.forward_rate(start, end)floatForward rate between dates
.pricing_errors()list[float]Per-bond pricing errors (model price - market price)
.curve()NelsonSiegel | NelsonSiegelSvensson | SmithWilsonExtract the fitted inner curve

Example

import datetime
from vade import FittedBondCurve, FixedRateBond, NelsonSiegel

settlement = datetime.date(2024, 1, 15)

# Create a portfolio of bonds with different maturities
bonds = []
for maturity_year, coupon in [(2026, 0.03), (2027, 0.035), (2029, 0.04), (2031, 0.042), (2034, 0.045)]:
    bond = FixedRateBond(
        effective=settlement,
        termination=datetime.date(maturity_year, 1, 15),
        frequency="s",
        convention="act365f",
        coupon=coupon,
        face_value=100.0,
    )
    bonds.append(bond)

# Observed clean prices
clean_prices = [99.5, 99.0, 98.5, 97.0, 95.0]

# Fit Nelson-Siegel model
fc = FittedBondCurve(bonds, clean_prices, settlement, model="NS")

assert fc.converged
assert fc.rmse < 1.0  # good fit quality

# Query the fitted curve
df = fc.discount_factor(datetime.date(2025, 1, 15))
assert 0.9 < df < 1.0  # reasonable 1Y discount factor

zr = fc.zero_rate(settlement, datetime.date(2029, 1, 15))
assert 0.0 < zr < 0.10  # positive 5Y zero rate

# Per-bond pricing errors
errors = fc.pricing_errors()
assert len(errors) == 5  # one per bond

# Extract the fitted inner curve
inner = fc.curve()
assert isinstance(inner, NelsonSiegel)

Advanced Example

Convergence diagnostics, per-bond pricing errors, and inner curve extraction:

import datetime
from vade import FittedBondCurve, FixedRateBond

bonds = [
    FixedRateBond(effective=datetime.date(2024, 6, 15), termination="2y",
                  fixed_rate=3.5, frequency="s", convention="act365f", currency="usd"),
    FixedRateBond(effective=datetime.date(2024, 6, 15), termination="3y",
                  fixed_rate=3.75, frequency="s", convention="act365f", currency="usd"),
    FixedRateBond(effective=datetime.date(2024, 6, 15), termination="5y",
                  fixed_rate=4.0, frequency="s", convention="act365f", currency="usd"),
    FixedRateBond(effective=datetime.date(2024, 6, 15), termination="7y",
                  fixed_rate=4.25, frequency="s", convention="act365f", currency="usd"),
    FixedRateBond(effective=datetime.date(2024, 6, 15), termination="10y",
                  fixed_rate=4.5, frequency="s", convention="act365f", currency="usd"),
]

clean_prices = [99.5, 99.0, 98.5, 97.5, 96.0]

fc = FittedBondCurve(
    bonds=bonds,
    clean_prices=clean_prices,
    settlement=datetime.date(2025, 6, 16),
    model="NS",
)

# Check convergence diagnostics
assert fc.converged
assert fc.iterations < 100
assert fc.rmse < 1.0  # RMSE in price terms

# pricing_errors() returns per-bond fitting errors
errors = fc.pricing_errors()
assert len(errors) == 5
for err in errors:
    assert abs(err) < 2.0  # each bond fits within 2 price points

# .curve() extracts the underlying parametric curve
inner_curve = fc.curve()
df = inner_curve.discount_factor(datetime.date(2030, 6, 16))
assert 0.70 < float(df) < 1.0

Tip: Use pricing_errors() to identify bonds that fit poorly -- these may indicate data issues or bonds with special features (e.g., on-the-run premiums). Consider excluding or down-weighting them via the weights parameter.

On this page