# Vade

Production-grade fixed income quant library. Rust core for performance, Python API via PyO3.

Rates, credit, FX, and financing instruments with automatic differentiation, curve calibration, and risk analytics.

**[vadepy.dev](https://vadepy.dev/)** | **[Documentation](https://vadepy.dev/docs/)** | **[API Reference](https://vadepy.dev/docs/api/)**

## Installation

```
pip install vade
```

Requires Python 3.11+.

### From Source

Requires the [Rust toolchain](https://rustup.rs/).

```bash
git clone https://github.com/sercanatalik/vadepy.git
cd vadepy
pip install maturin
maturin develop --release
```

Or using [uv](https://docs.astral.sh/uv/):

```bash
git clone https://github.com/sercanatalik/vadepy.git
cd vadepy
uv sync
```

## Features

### Instruments

| Category | Instruments |
|----------|------------|
| **Rates** | IRS, OIS, ZCS, SBS, XCS, FRA, Deposit, IR Future, Cap/Floor |
| **Bonds** | Fixed Rate, Floating Rate, Zero Coupon, Bill, Step-Up, Amortizing, PIK, Callable, Sub-Period FRN, Capped FRN |
| **Credit** | CDS, Asset Swap |
| **FX** | FX Forward, NDF, NDIRS, NDXCS |

### Curves

| Type | Description |
|------|------------|
| **DiscountCurve** | Discount factor curve with 12+ interpolation methods |
| **LineCurve** | Value-based curve for zero rates and spreads |
| **ForwardCurve** | Forward rate curve with flat-forward representation |
| **SpreadCurve** | Base curve with additive or multiplicative spread |
| **CreditImpliedCurve** | Piecewise-flat hazard rate curve |
| **CompositeCurve** | Combine multiple curves |
| **FittedBondCurve** | Fitted from bond prices via NLS optimization |
| **TurnOfYearCurve** | Year-end adjusted curve |
| **Nelson-Siegel / Svensson** | Parametric yield curve models |
| **Smith-Wilson** | Regulatory extrapolation model |

**Interpolation:** log-linear, linear, linear zero rate, flat forward, flat backward, cubic spline, natural cubic, log-cubic, Hermite, monotone cubic (Fritsch-Carlson), convex monotone (Hagan-West)

### Calibration and Risk

- **Solver** with Levenberg-Marquardt, Gauss-Newton, and gradient descent algorithms
- Multi-curve simultaneous calibration with pre-solver chains
- **Delta** and **gamma** risk sensitivities as Polars DataFrames
- Bootstrap for sequential curve construction

### Bond Analytics

Price, dirty price, YTM, duration (modified/Macaulay), convexity, DV01, Z-spread, asset-swap spread, CS01, accrued interest

### FX

- FX spot rates with graph-based cross-rate triangulation
- FX forwards via interest rate parity
- 4-curve cross-currency swap model
- Non-deliverable instruments (NDF, NDIRS, NDXCS)

### Market Infrastructure

- **30+ business calendars** (NYC, LDN, TGT, TYO, ZUR, and more)
- **10 day count conventions** (ACT/360, ACT/365F, ACT/ACT ISDA, 30/360, BUS/252, and more)
- **20+ interest rate indices** (SOFR, SONIA, ESTR, EURIBOR, and more)
- **RFR compounding** with payment delay, observation shift, lockout, and lookback methods
- **Automatic differentiation** (Dual and Dual2 types for first and second order)
- **Market context** for bundling curves, fixings, FX rates, and calendars
- **JSON serialization** for all curves, solver state, and market contexts
- **Polars and pandas** DataFrame integration for cashflows and risk output

## Quick Start

### Build and Calibrate a Discount Curve

```python
import datetime
from vade import DiscountCurve, IRS, FRA, Solver

effective = datetime.date(2025, 6, 16)

curve = DiscountCurve(
    {
        effective: 1.0,
        datetime.date(2025, 9, 16): 1.0,
        datetime.date(2025, 12, 16): 1.0,
        datetime.date(2026, 6, 16): 1.0,
        datetime.date(2027, 6, 16): 1.0,
        datetime.date(2028, 6, 16): 1.0,
        datetime.date(2030, 6, 16): 1.0,
        datetime.date(2035, 6, 16): 1.0,
    },
    interpolation="log_linear",
    convention="act360",
    id="sofr",
)

instruments = [
    (FRA(effective=effective, termination="3M", fixed_rate=4.25, convention="act360"),
     0.0425, 0, "3M_FRA", "USD"),
    (FRA(effective=effective, termination="6M", fixed_rate=4.15, convention="act360"),
     0.0415, 0, "6M_FRA", "USD"),
    (IRS(effective=effective, termination="1Y", frequency="a", fixed_rate=4.0,
         convention="act360", float_convention="act360"),
     4.00, 0, "1Y_IRS", "USD"),
    (IRS(effective=effective, termination="2Y", frequency="a", fixed_rate=3.85,
         convention="act360", float_convention="act360"),
     3.85, 0, "2Y_IRS", "USD"),
    (IRS(effective=effective, termination="5Y", frequency="a", fixed_rate=3.70,
         convention="act360", float_convention="act360"),
     3.70, 0, "5Y_IRS", "USD"),
    (IRS(effective=effective, termination="10Y", frequency="a", fixed_rate=3.85,
         convention="act360", float_convention="act360"),
     3.85, 0, "10Y_IRS", "USD"),
]

solver = Solver(curves=[curve], instruments=instruments)
result = solver.iterate()
print(f"Converged: {result.converged}")  # True

calibrated = solver.get_curve(0)
print(f"1Y DF: {float(calibrated.discount_factor(datetime.date(2026, 6, 16))):.6f}")
print(f"1Y zero rate: {float(calibrated.zero_rate(effective, datetime.date(2026, 6, 16))):.4%}")
```

### Price an Interest Rate Swap

```python
swap = IRS(
    effective=effective,
    termination="5Y",
    frequency="a",
    fixed_rate=3.80,
    convention="act360",
    float_convention="act360",
)

print(f"Par rate: {float(swap.rate(calibrated)):.4f}%")
print(f"NPV: {float(swap.npv(calibrated)):,.2f}")
```

### Risk Sensitivities

```python
delta = solver.delta(swap, result)
print(delta)

gamma = solver.gamma(swap, result)
```

### Fixed Rate Bonds

```python
from vade import FixedRateBond, DiscountCurve
import datetime

bond = FixedRateBond(
    effective=datetime.date(2024, 6, 15),
    termination="5Y",
    fixed_rate=4.5,
    frequency="s",
)

curve = DiscountCurve(
    {datetime.date(2024, 6, 15): 1.0, datetime.date(2029, 6, 15): 0.82},
    interpolation="log_linear",
)

print(f"Price: {float(bond.price(curve)):.4f}")
print(f"YTM: {float(bond.ytm(curve)):.4%}")
print(f"Duration: {float(bond.duration(curve)):.4f}")
```

### Credit Default Swaps

```python
from vade import CDS, DiscountCurve
import datetime

cds = CDS(
    effective=datetime.date(2024, 6, 20),
    termination="5Y",
    frequency="q",
    fixed_rate=100,  # 100bp spread
)

disc_curve = DiscountCurve(
    {datetime.date(2024, 6, 20): 1.0, datetime.date(2029, 6, 20): 0.85},
    interpolation="log_linear",
    id="usd",
)
credit_curve = DiscountCurve(
    {datetime.date(2024, 6, 20): 1.0, datetime.date(2029, 6, 20): 0.95},
    interpolation="log_linear",
    id="credit",
)

print(f"NPV: {float(cds.npv(disc_curve, credit_curve)):,.2f}")
```

## Documentation

Full documentation at **[vadepy.dev/docs](https://vadepy.dev/docs/)**.

- [Quick Start](https://vadepy.dev/docs/guides/quick-start) -- end-to-end curve building and pricing
- [API Reference](https://vadepy.dev/docs/api/) -- curves, instruments, solver, and more
- [Rates](https://vadepy.dev/docs/guides/rates/) -- curve building, pricing, risk, caps/floors
- [Credit](https://vadepy.dev/docs/guides/credit/) -- bonds, CDS, fitted curves, spread analytics
- [FX](https://vadepy.dev/docs/guides/fx/) -- FX rates, forwards, cross-currency swaps, NDFs
- [Calibration](https://vadepy.dev/docs/guides/calibration) -- multi-curve frameworks and solver algorithms
- [Market Context](https://vadepy.dev/docs/guides/market-context) -- bundling curves, fixings, and FX data
- [Serialization](https://vadepy.dev/docs/guides/serialization) -- JSON round-tripping for curves and contexts

## License

MIT -- see [LICENSE](LICENSE) for details.
