Skip to content

Fixed Income API Reference

financelib.quant.fixed_income.present_value(cash_flows: List[float], discount_rate: float, periods: Optional[List[float]] = None) -> float

Calculate present value of a stream of cash flows.

PV = sum(CF_t / (1 + r)^t)

Parameters:

Name Type Description Default
cash_flows List[float]

List of future cash flows.

required
discount_rate float

Discount rate per period.

required
periods Optional[List[float]]

Custom period timings. If None, uses 1, 2, 3, ...

None

Returns:

Type Description
float

Present value.

Example

present_value([100, 100, 1100], 0.05) 1136.16...

Source code in financelib/quant/fixed_income.py
def present_value(
    cash_flows: List[float],
    discount_rate: float,
    periods: Optional[List[float]] = None,
) -> float:
    """Calculate present value of a stream of cash flows.

    PV = sum(CF_t / (1 + r)^t)

    Args:
        cash_flows: List of future cash flows.
        discount_rate: Discount rate per period.
        periods: Custom period timings. If None, uses 1, 2, 3, ...

    Returns:
        Present value.

    Example:
        >>> present_value([100, 100, 1100], 0.05)
        1136.16...
    """
    if periods is None:
        periods = list(range(1, len(cash_flows) + 1))

    pv = sum(cf / (1 + discount_rate) ** t for cf, t in zip(cash_flows, periods))
    return float(pv)

financelib.quant.fixed_income.bond_price(face_value: float, coupon_rate: float, ytm: float, periods: int, frequency: int = 2) -> float

Calculate the clean price of a fixed-rate bond.

Parameters:

Name Type Description Default
face_value float

Par/face value of the bond.

required
coupon_rate float

Annual coupon rate (e.g., 0.05 for 5%).

required
ytm float

Yield to maturity (annualized).

required
periods int

Number of years to maturity.

required
frequency int

Coupon payments per year (1=annual, 2=semi-annual).

2

Returns:

Type Description
float

Bond price.

Source code in financelib/quant/fixed_income.py
def bond_price(
    face_value: float,
    coupon_rate: float,
    ytm: float,
    periods: int,
    frequency: int = 2,
) -> float:
    """Calculate the clean price of a fixed-rate bond.

    Args:
        face_value: Par/face value of the bond.
        coupon_rate: Annual coupon rate (e.g., 0.05 for 5%).
        ytm: Yield to maturity (annualized).
        periods: Number of years to maturity.
        frequency: Coupon payments per year (1=annual, 2=semi-annual).

    Returns:
        Bond price.
    """
    n = periods * frequency
    coupon = face_value * coupon_rate / frequency
    r = ytm / frequency

    if r == 0:
        return coupon * n + face_value

    pv_coupons = coupon * (1 - (1 + r) ** (-n)) / r
    pv_face = face_value / (1 + r) ** n

    return float(pv_coupons + pv_face)

financelib.quant.fixed_income.yield_to_maturity(price: float, face_value: float, coupon_rate: float, periods: int, frequency: int = 2, tol: float = 1e-08, max_iter: int = 200) -> float

Calculate yield to maturity using Newton-Raphson method.

Parameters:

Name Type Description Default
price float

Current market price.

required
face_value float

Par/face value.

required
coupon_rate float

Annual coupon rate.

required
periods int

Years to maturity.

required
frequency int

Coupon payments per year.

2
tol float

Convergence tolerance.

1e-08
max_iter int

Maximum iterations.

200

Returns:

Type Description
float

Annualized yield to maturity.

Source code in financelib/quant/fixed_income.py
def yield_to_maturity(
    price: float,
    face_value: float,
    coupon_rate: float,
    periods: int,
    frequency: int = 2,
    tol: float = 1e-8,
    max_iter: int = 200,
) -> float:
    """Calculate yield to maturity using Newton-Raphson method.

    Args:
        price: Current market price.
        face_value: Par/face value.
        coupon_rate: Annual coupon rate.
        periods: Years to maturity.
        frequency: Coupon payments per year.
        tol: Convergence tolerance.
        max_iter: Maximum iterations.

    Returns:
        Annualized yield to maturity.
    """
    # Initial guess
    ytm_guess = coupon_rate + (face_value - price) / (price * periods)
    ytm_guess = max(ytm_guess, 0.001)

    for _ in range(max_iter):
        p = bond_price(face_value, coupon_rate, ytm_guess, periods, frequency)
        diff = p - price

        if abs(diff) < tol:
            return ytm_guess

        # Numerical derivative
        dp = bond_price(face_value, coupon_rate, ytm_guess + 0.0001, periods, frequency)
        derivative = (dp - p) / 0.0001

        if abs(derivative) < 1e-12:
            break

        ytm_guess -= diff / derivative
        ytm_guess = max(ytm_guess, 0.0001)

    return float(ytm_guess)

financelib.quant.fixed_income.duration(face_value: float, coupon_rate: float, ytm: float, periods: int, frequency: int = 2, modified: bool = True) -> float

Calculate Macaulay or modified duration of a bond.

Macaulay duration measures the weighted average time to receive cash flows. Modified duration measures price sensitivity to yield changes.

Parameters:

Name Type Description Default
face_value float

Par/face value.

required
coupon_rate float

Annual coupon rate.

required
ytm float

Yield to maturity.

required
periods int

Years to maturity.

required
frequency int

Coupon payments per year.

2
modified bool

If True, return modified duration.

True

Returns:

Type Description
float

Duration in years.

Source code in financelib/quant/fixed_income.py
def duration(
    face_value: float,
    coupon_rate: float,
    ytm: float,
    periods: int,
    frequency: int = 2,
    modified: bool = True,
) -> float:
    """Calculate Macaulay or modified duration of a bond.

    Macaulay duration measures the weighted average time to receive cash flows.
    Modified duration measures price sensitivity to yield changes.

    Args:
        face_value: Par/face value.
        coupon_rate: Annual coupon rate.
        ytm: Yield to maturity.
        periods: Years to maturity.
        frequency: Coupon payments per year.
        modified: If True, return modified duration.

    Returns:
        Duration in years.
    """
    n = periods * frequency
    coupon = face_value * coupon_rate / frequency
    r = ytm / frequency
    price = bond_price(face_value, coupon_rate, ytm, periods, frequency)

    if price == 0:
        return 0.0

    # Macaulay duration
    mac_dur = 0.0
    for t in range(1, n + 1):
        cf = coupon if t < n else coupon + face_value
        mac_dur += t * cf / (1 + r) ** t

    mac_dur = mac_dur / (price * frequency)

    if modified:
        return float(mac_dur / (1 + r))
    return float(mac_dur)

financelib.quant.fixed_income.convexity(face_value: float, coupon_rate: float, ytm: float, periods: int, frequency: int = 2) -> float

Calculate the convexity of a bond.

Convexity measures the curvature of the price-yield relationship, providing a second-order correction to duration.

Parameters:

Name Type Description Default
face_value float

Par/face value.

required
coupon_rate float

Annual coupon rate.

required
ytm float

Yield to maturity.

required
periods int

Years to maturity.

required
frequency int

Coupon payments per year.

2

Returns:

Type Description
float

Convexity value.

Source code in financelib/quant/fixed_income.py
def convexity(
    face_value: float,
    coupon_rate: float,
    ytm: float,
    periods: int,
    frequency: int = 2,
) -> float:
    """Calculate the convexity of a bond.

    Convexity measures the curvature of the price-yield relationship,
    providing a second-order correction to duration.

    Args:
        face_value: Par/face value.
        coupon_rate: Annual coupon rate.
        ytm: Yield to maturity.
        periods: Years to maturity.
        frequency: Coupon payments per year.

    Returns:
        Convexity value.
    """
    n = periods * frequency
    coupon = face_value * coupon_rate / frequency
    r = ytm / frequency
    price = bond_price(face_value, coupon_rate, ytm, periods, frequency)

    if price == 0:
        return 0.0

    conv = 0.0
    for t in range(1, n + 1):
        cf = coupon if t < n else coupon + face_value
        conv += t * (t + 1) * cf / (1 + r) ** (t + 2)

    return float(conv / (price * frequency**2))