Skip to content

sujitn/convex

Repository files navigation

Convex

High-Performance Fixed Income Analytics Library in Rust

Crates.io Documentation Build Status License: MIT

Live Demo | WASM Demo - Try the interactive bond analytics calculator

Convex is a production-grade fixed income analytics library providing comprehensive bond pricing, yield curve construction, and risk analytics with industry-standard methodologies.

Features

  • Bond Pricing: All major bond types (government, corporate, callable, putable, sinking fund)
  • Yield Calculations: YTM, YTC, YTW with industry-standard methodology
  • Yield Curves: Bootstrap from market data with multiple interpolation methods
  • Spread Analytics: Z-spread, G-spread, I-spread, Asset Swap spreads, OAS
  • Risk Metrics: Duration (Macaulay, Modified, Effective, Key Rate), Convexity, DV01
  • Day Count Conventions: ACT/360, ACT/365, 30/360, ACT/ACT (ICMA, ISDA)
  • Holiday Calendars: SIFMA, TARGET2, UK, Japan with O(1) lookups + dynamic calendars
  • High Performance: Microsecond-level pricing
  • Type Safety: Leverage Rust's type system to prevent errors
  • WebAssembly: Full browser support via wasm-pack (Live Demo | WASM Demo)
  • Language Bindings: C FFI bindings available; Python, Java, C# (coming soon)

Quick Start

Installation

Add this to your Cargo.toml:

[dependencies]
convex = "0.1"

Example: Pricing a US Treasury Bond

use convex::prelude::*;
use rust_decimal_macros::dec;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a US Treasury bond
    let bond = Bond::builder()
        .isin("US912828Z229")
        .coupon_rate(dec!(2.5))
        .maturity(Date::from_ymd(2030, 5, 15))
        .frequency(Frequency::SemiAnnual)
        .day_count(DayCount::ActAct)
        .build()?;

    // Build a yield curve from market data
    let curve = YieldCurve::bootstrap()
        .add_deposit(dec!(0.015), Period::Months(3))
        .add_deposit(dec!(0.018), Period::Months(6))
        .add_bond(dec!(98.50), Date::from_ymd(2027, 5, 15))
        .add_bond(dec!(97.25), Date::from_ymd(2032, 5, 15))
        .interpolation(Interpolation::CubicSpline)
        .build()?;

    // Price the bond
    let settlement = Date::today();
    let price = bond.price(&curve, settlement)?;
    
    println!("Clean Price: {:.4}", price.clean());
    println!("Dirty Price: {:.4}", price.dirty());
    println!("Accrued Interest: {:.4}", price.accrued());

    // Calculate yield
    let ytm = bond.yield_to_maturity(price.clean(), settlement)?;
    println!("Yield to Maturity: {:.4}%", ytm.as_percentage());

    // Calculate risk metrics
    let duration = bond.modified_duration(&curve, settlement)?;
    let convexity = bond.convexity(&curve, settlement)?;
    let dv01 = bond.dv01(&curve, settlement)?;

    println!("Modified Duration: {:.4}", duration);
    println!("Convexity: {:.4}", convexity);
    println!("DV01: ${:.2}", dv01);

    Ok(())
}

Example: Z-Spread Calculation

use convex::prelude::*;
use rust_decimal_macros::dec;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bond = Bond::builder()
        .isin("US459200KJ18")  // IBM Corporate Bond
        .coupon_rate(dec!(3.75))
        .maturity(Date::from_ymd(2028, 11, 15))
        .frequency(Frequency::SemiAnnual)
        .day_count(DayCount::Thirty360)
        .build()?;

    // Government curve for discounting
    let gov_curve = YieldCurve::from_market_data(/* ... */)?;
    
    // Market price
    let market_price = Price::new(dec!(102.50), Currency::USD);
    
    // Calculate Z-spread
    let z_spread = bond.z_spread(market_price, &gov_curve, Date::today())?;
    
    println!("Z-Spread: {:.2} bps", z_spread.as_basis_points());

    Ok(())
}

Architecture

Convex is organized into several crates for modularity:

convex/
├── convex-core        # Core types (Date, Price, Yield, etc.)
├── convex-math        # Mathematical utilities and solvers
├── convex-curves      # Yield curve construction and interpolation
├── convex-bonds       # Bond instruments and definitions
├── convex-analytics   # Unified analytics (yields, spreads, risk)
├── convex-wasm        # WebAssembly bindings
└── convex-ffi         # Foreign Function Interface for language bindings

Performance

Convex is designed for production trading systems with strict performance requirements:

Operation Time Notes
Bond Price < 1 μs Single fixed-rate bond
YTM Calculation < 10 μs Newton-Raphson convergence
Bootstrap 50-point curve < 100 μs Parallel processing
Z-Spread < 50 μs Iterative solver
Holiday Lookup < 10 ns O(1) bitmap lookup
Portfolio (1000 bonds) < 10 ms Parallel pricing

Benchmarked on AMD Ryzen 9 5950X @ 3.4GHz

Day Count Conventions

Convex implements all major day count conventions with industry-standard compliance:

  • ACT/360: Actual days / 360 (Money market)
  • ACT/365: Actual days / 365 (UK Gilts)
  • 30/360 US: 30-day months, 360-day year (US Corporate bonds)
  • 30E/360: European 30/360 convention
  • ACT/ACT ICMA: Actual/Actual per period (Government bonds)
  • ACT/ACT ISDA: Actual/Actual with year convention (Swaps)

Holiday Calendars

Convex provides comprehensive holiday calendar support with O(1) bitmap-based lookups:

Built-in Calendars

Calendar Description Usage
SIFMACalendar US fixed income (bond market) Corporate bonds, Munis
USGovernmentCalendar US Treasury securities Treasuries
Target2Calendar Eurozone payments EUR swaps, Bunds
UKCalendar UK bank holidays Gilts
JapanCalendar Japan holidays JGBs

Dynamic Calendars

Load calendars from JSON or create custom calendars at runtime:

use convex_core::calendars::{DynamicCalendar, CustomCalendarBuilder, WeekendType, Calendar};

// Load from JSON
let cal = DynamicCalendar::from_json(r#"{
    "name": "My Calendar",
    "weekend": "SaturdaySunday",
    "holidays": ["2025-01-01", "2025-12-25"]
}"#)?;

// Build custom calendar
let cal = CustomCalendarBuilder::new("Trading Calendar")
    .weekend(WeekendType::SaturdaySunday)
    .add_fixed_holiday(1, 1)           // New Year's Day
    .add_nth_weekday(1, Weekday::Mon, 3) // MLK Day
    .add_good_friday()
    .add_custom(|year| fetch_holidays_from_db(year))
    .build();

// Dynamic modification
let mut cal = DynamicCalendar::new("Custom", WeekendType::SaturdaySunday);
cal.add_holiday(date);
cal.merge_from(&SIFMACalendar::new());

Yield Calculation Methodology

Convex uses industry-standard methodology for all yield calculations:

  1. Sequential Roll-Forward: Starting from settlement date, roll forward through each period
  2. Exact Day Counts: Use actual calendar days with appropriate day count convention
  3. Newton-Raphson Solver: Converge to 1e-10 tolerance within 100 iterations
  4. Compounding Frequency: Support annual, semi-annual, quarterly, monthly

This ensures accurate results matching professional trading systems.

Language Bindings

Python (PyO3)

from convex import Bond, YieldCurve, Date
from decimal import Decimal

bond = Bond(
    isin="US912828Z229",
    coupon_rate=Decimal("2.5"),
    maturity=Date(2030, 5, 15),
    frequency="semi-annual"
)

curve = YieldCurve.from_market_data(...)
price = bond.price(curve, Date.today())

print(f"Clean Price: {price.clean():.4f}")
print(f"YTM: {bond.ytm(price.clean()):.4f}%")

Java (JNI)

import com.convex.Bond;
import com.convex.YieldCurve;
import java.math.BigDecimal;

Bond bond = new Bond.Builder()
    .isin("US912828Z229")
    .couponRate(new BigDecimal("2.5"))
    .maturity(LocalDate.of(2030, 5, 15))
    .build();

YieldCurve curve = YieldCurve.fromMarketData(...);
Price price = bond.price(curve, LocalDate.now());

System.out.printf("Clean Price: %.4f%n", price.clean());

Excel (XLL Plugin)

=CONVEX.BOND.PRICE("US912828Z229", TODAY(), "CURVE_USD")
=CONVEX.BOND.YTM("US912828Z229", 98.50, TODAY())
=CONVEX.BOND.DURATION("US912828Z229", "CURVE_USD", TODAY())

Supported Bond Types

Current Support

  • ✅ Fixed-rate bonds (government, corporate)
  • ✅ Zero-coupon bonds (T-Bills, discount bonds)
  • ✅ Floating-rate notes (SOFR, SONIA, EURIBOR with caps/floors)
  • ✅ Callable bonds (American, Bermudan, European, Make-Whole)
  • ✅ Putable bonds
  • ✅ Sinking fund bonds (with average life calculations)

Future Support

  • 🔜 Convertible bonds
  • 🔜 Inflation-linked bonds (TIPS, Linkers)
  • 🔜 Asset-backed securities
  • 🔜 Mortgage-backed securities

Building from Source

# Clone the repository
git clone https://github.com/sujitn/convex.git
cd convex

# Build all crates
cargo build --release

# Run tests
cargo test --all

# Run benchmarks
cargo bench

# Generate documentation
cargo doc --open

Development

Prerequisites

  • Rust 1.75 or later
  • Cargo

Running Tests

# All tests
cargo test

# Specific crate
cargo test -p convex-core

# With output
cargo test -- --nocapture

# Integration tests
cargo test --test '*'

Code Quality

# Linting
cargo clippy -- -D warnings

# Formatting
cargo fmt --check

# Check for common mistakes
cargo audit

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

Areas for Contribution

  • Additional bond types (inflation-linked, convertibles)
  • Additional language bindings
  • Performance improvements
  • Documentation and examples
  • Bug fixes and testing

Roadmap

Completed

  • Core infrastructure (Date, Price, Yield types)
  • Day count conventions (all major conventions)
  • Yield curve construction and bootstrapping
  • Fixed-rate bond pricing with industry-standard methodology
  • Spread calculations (G-spread, Z-spread, I-spread, OAS, ASW)
  • Holiday calendars (SIFMA, TARGET2, UK, Japan)
  • Dynamic calendar system (JSON loading, custom builders)
  • Floating rate notes (SOFR, SONIA, EURIBOR)
  • Callable/putable bonds with OAS
  • Sinking fund bonds
  • Risk metrics (Duration, Convexity, DV01, VaR)
  • Multi-curve framework (OIS discounting)
  • WebAssembly support with interactive demo
  • Advanced interpolation (Nelson-Siegel, Svensson, Monotone Convex)

In Progress

  • Python bindings (PyO3)
  • Comprehensive documentation
  • Performance optimizations

Planned

  • Java and C# bindings
  • Excel plugin
  • Convertible bonds
  • Inflation-linked bonds (TIPS, Linkers)
  • REST API service

Validation

Convex is validated against:

  • Industry-standard reference implementations
  • Known academic test cases
  • Historical market data

All pricing and risk calculations are tested to match professional systems within 1e-6 tolerance.

Performance Benchmarks

Run benchmarks with:

cargo bench

Documentation

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by QuantLib design patterns
  • Industry-standard fixed income methodologies
  • Rust Financial community

Citation

If you use Convex in academic work, please cite:

@software{convex2025,
  title = {Convex: High-Performance Fixed Income Analytics Library},
  author = {Sujit Nair},
  year = {2025},
  url = {https://github.com/sujitn/convex}
}

Contact


Built with ❤️ in Rust 🦀

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors