High-Performance Fixed Income Analytics Library in Rust
Live Demo | Convex Terminal - bond yield, spread, curve and risk analytics in the browser on free public market data (www/)
Convex is a fixed income analytics library providing bond pricing, yield curve construction and risk analytics. Full mandatory library and production certification remain open; see current API capabilities and gaps.
- 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
- Hedge Advisor: AI-friendly proposal layer — DV01-neutral hedges via bond futures or IRS, with structured tradeoffs and a deterministic narrator (research tool, not an execution recommender)
- 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: the full supplied-input
library()API via wasm-pack; the Convex Terminal runs it in a Web Worker against live Treasury, NY Fed, ECB and Bank of Canada data (www/) - Language Bindings: C FFI and Java (published to Maven Central) available; Python and C# planned
The core library crates are published to crates.io. Most
users only need convex-analytics, which re-exports the lower layers (core,
math, curves, bonds):
[dependencies]
convex-analytics = "0.13"The full set of published crates: convex-core, convex-math,
convex-curves, convex-bonds, convex-analytics.
The new workspace convex-rates crate provides supplied IRS/OIS contracts and native multi-curve valuation; analytics composes full-contract curve fitting. Ten supplied cases have executed QuantLib 1.40 comparison evidence at the declared bounds. These workspace additions are not yet a published release or an independent market/model certificate.
The workspace convex-credit crate provides single-name CDS valuation and running/upfront conversion, exposed as convex::credit, with all 7,164 original USD SOFR ISDA RFR grid cases checked offline. Credit calibration and risk inputs compose full quotes, signed rate/CS01/recovery sensitivities, immediate default scenarios and checked bond/CDS mappings. Lifecycle and host certificates remain owning work.
This application is based on the ISDA CDS Standard Model (version 1.8.3), developed and supported in collaboration with Markit Group Ltd. The separate ISDA public license applies to that standard-model route.
Note: the
convexumbrella crate is not on crates.io — that name belongs to an unrelated project (convex.dev). The umbrella facade, along with the FFI, WASM, MCP and pricing-server crates, ships in-repo only. Depend on them via git or a path dependency:convex = { git = "https://github.com/sujitn/convex.git" }
The two snippets below are mirrored by compile-checked examples — run them with
cargo run -p convex-analytics --example readme_quickstartand--example readme_zspread.
use convex_analytics::functions::yield_to_maturity;
use convex_bonds::instruments::FixedRateBond;
use convex_core::types::{Date, Frequency};
use rust_decimal_macros::dec;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// A 5% semi-annual bond. Coupon is a decimal (0.05 == 5%); day count and
// calendar default to 30/360 US and SIFMA.
let bond = FixedRateBond::builder()
.cusip_unchecked("912828Z29")
.coupon_rate(dec!(0.05))
.issue_date(Date::from_ymd(2020, 5, 15)?)
.maturity(Date::from_ymd(2030, 5, 15)?)
.frequency(Frequency::SemiAnnual)
.build()?;
// Yield to maturity from a clean price of 98.50 (per 100 face).
let settlement = Date::from_ymd(2025, 5, 15)?;
let ytm = yield_to_maturity(&bond, settlement, dec!(98.50), Frequency::SemiAnnual)?;
println!("Yield to Maturity: {:.4}%", ytm.yield_percent()?);
Ok(())
}use convex_analytics::spreads::z_spread;
use convex_bonds::instruments::FixedRateBond;
use convex_core::types::{Date, Frequency};
use convex_curves::curves::DiscountCurveBuilder;
use rust_decimal_macros::dec;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 3.75% semi-annual corporate bond.
let bond = FixedRateBond::builder()
.cusip_unchecked("459200KJ1")
.coupon_rate(dec!(0.0375))
.issue_date(Date::from_ymd(2018, 11, 15)?)
.maturity(Date::from_ymd(2028, 11, 15)?)
.frequency(Frequency::SemiAnnual)
.build()?;
// A flat 4% continuously-compounded discount curve to spread against.
let settlement = Date::from_ymd(2025, 1, 15)?;
let rate = 0.04_f64;
let curve = DiscountCurveBuilder::new(settlement)
.add_pillar(1.0, (-rate * 1.0).exp())
.add_pillar(2.0, (-rate * 2.0).exp())
.add_pillar(5.0, (-rate * 5.0).exp())
.add_pillar(10.0, (-rate * 10.0).exp())
.with_extrapolation()
.build()?;
// Z-spread that reprices the bond to a dirty price of 102.50.
let spread = z_spread(&bond, dec!(102.50), &curve, settlement)?;
println!("Z-Spread: {:.2} bps", spread.as_bps());
Ok(())
}Research tool, not an execution recommender. Costs come from a labeled
heuristic_v1table; futures use a synthetic 6%-coupon deliverable (no live CTD basket). Every output stampsprovenance.cost_modelandComparisonRow.cost_source.
DV01-neutral hedge proposals with structured tradeoffs. Strategies:
DurationFutures, BarbellFutures, KeyRateFutures, CashBondPair,
InterestRateSwap.
compute_position_risk(bond, settlement, mark, notional_face, curve, [key_rate_tenors])
-> RiskProfile { dv01, modified_duration, key_rate_buckets, …, provenance }
aggregate_book_risk(positions, [book_id])
-> RiskProfile # net book DV01, KRD union, DV01-weighted durations
propose_hedges(risk, curve, [constraints], [basket_overrides])
-> { proposals: HedgeProposal[…], skipped_strategies: [{strategy, reason}] }
propose_book_hedges(groups: BookGroup[…])
-> { groups: [{ group_name, aggregate_risk, contributions, proposals,
skipped_strategies }] }
compare_hedges(position, proposals, [constraints])
-> ComparisonReport { rows, recommendation }
narrate_recommendation(comparison)
-> { text } # deterministic template; no LLM call
propose_book_hedges hedges multiple sleeves with per-group policy —
each BookGroup carries its own positions, curve, constraints, and
basket overrides. Useful when a rates sleeve and a credit sleeve need
different allowed_strategies / cost caps in one call. The output's
contributions field decomposes each group's aggregate DV01 by
position (signed DV01 + share of gross), so traders can see who's
driving the book.
End-to-end test:
cargo run -p convex-mcp --bin convex-mcp-server
cargo test -p convex-mcp --lib hedge_advisor_e2eSee docs/hedge-advisor-{investigation,gaps,plan}.md for design and
docs/perf-baselines.md for current benchmark numbers.
CTD live basket feed (heuristic synthetic deliverable in place); live cost feed (heuristic table only); FX delta / cross-currency hedging; LLM narrator (deterministic template only); CDS / credit DV01; inflation-linked instruments; ETF-proxy strategy; per-benchmark partial spread DV01.
Convex is organized into focused crates. The five library crates are published to crates.io; the rest are internal (the facade, language bindings, and the pricing-engine/server stack) and ship in-repo only.
convex/
├── convex-core # Core types (Date, Price, Yield, calendars, day counts) [published]
├── convex-math # Solvers and interpolators (Brent, Newton, LM) [published]
├── convex-curves # Yield/credit curves, bootstrapping, multi-curve [published]
├── convex-bonds # Bond instruments (fixed, FRN, callable, zero, sinker) [published]
├── convex-rates # Supplied IRS/OIS terms, expected cash and valuation [new workspace crate]
├── convex-analytics # Unified analytics: pricing, yields, spreads, risk [published]
├── convex # Single-import facade re-exporting the public API (internal)
├── convex-portfolio # Portfolio and ETF analytics (internal)
├── convex-ffi # C-ABI FFI for language bindings (Java, Excel) (internal)
├── convex-wasm # WebAssembly bindings for the browser demo (internal)
├── convex-mcp # MCP server for tool/agent integration (internal)
├── convex-ports # Hexagonal port traits (market/reference data, storage) (internal)
├── convex-engine # Reactive pricing engine with a calculation graph (internal)
├── convex-ext-file # File-backed market/reference data adapter (internal)
├── convex-ext-redb # redb embedded-storage adapter (internal)
└── convex-server # REST + WebSocket pricing server (deployed to Fly.io) (internal)
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
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)
Convex provides comprehensive holiday calendar support with O(1) bitmap-based lookups:
| 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 |
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());Convex uses industry-standard methodology for all yield calculations:
- Sequential Roll-Forward: Starting from settlement date, roll forward through each period
- Exact Day Counts: Use actual calendar days with appropriate day count convention
- Newton-Raphson Solver: Converge to 1e-10 tolerance within 100 iterations
- Compounding Frequency: Support annual, semi-annual, quarterly, monthly
This ensures accurate results matching professional trading systems.
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}%")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());=CONVEX.BOND.PRICE("US912828Z229", TODAY(), "CURVE_USD")
=CONVEX.BOND.YTM("US912828Z229", 98.50, TODAY())
=CONVEX.BOND.DURATION("US912828Z229", "CURVE_USD", TODAY())
- ✅ 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)
- 🔜 Convertible bonds
- 🔜 Inflation-linked bonds (TIPS, Linkers)
- 🔜 Asset-backed securities
- 🔜 Mortgage-backed securities
# Clone the repository
git clone https://github.com/sujitn/convex.git
cd convex
# Unpack the compressed inputs needed by the full regression suite
python3 tools/fixtures.py materialize
# Build all crates, including the host ABI with panic containment
cargo build --locked --profile excel
# Run tests
cargo test --all
# Run benchmarks
cargo bench
# Generate documentation
cargo doc --open- Rust 1.95 or later; validation uses the pinned toolchain in
rust-toolchain.toml - Cargo
- Python 3 to unpack the full regression suite's inputs; see test data
# All tests
cargo test
# Specific crate
cargo test -p convex-core
# With output
cargo test -- --nocapture
# Integration tests
cargo test --test '*'# Linting
cargo clippy -- -D warnings
# Formatting
cargo fmt --check
# Check for common mistakes
cargo auditContributions are welcome! Please open an issue or submit a pull request on GitHub.
- Additional bond types (inflation-linked, convertibles)
- Additional language bindings
- Performance improvements
- Documentation and examples
- Bug fixes and testing
- 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)
- Python bindings (PyO3)
- Comprehensive documentation
- Performance optimizations
- Java and C# bindings
- Excel plugin
- Convertible bonds
- Inflation-linked bonds (TIPS, Linkers)
- REST API service
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.
Run benchmarks with:
cargo bench- API Documentation — generate locally with
cargo doc --no-deps --workspace --open - Dated futures and cash hedge reference inputs
- Supplied futures and cash hedge valuation and risk
- Complete supplied mixed rate calibration and tenor basis
- Supplied government, issuer basis and repo cash curves
- Signed quote risk, full rebuilding and portfolio coverage
- Standalone valuation, inverse and mixed-book workflows
- Live Demo
- WASM Demo
This project is licensed under the MIT License - see the LICENSE file for details.
- Inspired by QuantLib design patterns
- Industry-standard fixed income methodologies
- Rust Financial community
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}
}- GitHub Issues: Bug reports and feature requests
Built with ❤️ in Rust 🦀
Pure supplied lifecycle is available through convex::lifecycle; see events, cash and pending settlement.
Full supplied terms and resources can also use convex::library and the shared
convex_library JSON/C ABI route. See API, clients and explicit remaining gaps.