# How to Price a Swaption Using the API

This guide walks you through pricing European interest rate swaptions using the BlueGamma API. The endpoint returns the option's net present value, DV01, and vega using a Bachelier (normal) volatility model with live yield curves.

This example uses **SOFR swaptions**.

***

### Before You Start

To follow this guide, make sure you have:

* An active BlueGamma API key
* Python 3.x with the `requests` library installed

If you don't have an API key yet, see [Authentication](/documentation/integrations/api/authentication.md) or contact <support@bluegamma.io>.

***

### Overview: What Is a Swaption?

A **swaption** (swap option) is an option granting the holder the right, but not the obligation, to enter into an interest rate swap at a future date.

* A **payer swaption** gives the right to **pay fixed** and receive floating — it benefits when rates rise above the strike.
* A **receiver swaption** gives the right to **receive fixed** and pay floating — it benefits when rates fall below the strike.

BlueGamma prices **European swaptions**, where the holder can only exercise on a single date (the swap start date). The option exercise date always equals the swap start date.

**Bachelier (Normal) Pricing Model**

The API uses the Bachelier model, which prices swaptions in terms of normal (absolute) volatility rather than lognormal (Black) volatility. This avoids issues with log-based models when rates are low or negative.

$$
NPV\_{\text{payer}} = N \times A \times \left\[ (F - K) , \Phi(d) + \sigma\_N \sqrt{T} , \phi(d) \right]
$$

Where:

* **N** = Notional amount
* **A** = Annuity factor (sum of discounted day count fractions)
* **F** = Forward swap rate
* **K** = Strike rate
* **σ**<sub>**N**</sub> = Normal (Bachelier) volatility
* **T** = Time to expiry in years
* **d** = (F − K) / (σ<sub>N</sub> √T)
* **Φ(d)** = Cumulative standard normal distribution
* **φ(d)** = Standard normal probability density

For the underlying swap rate calculation, see [How to Price a Swap Using the API](/documentation/integrations/api/how-to-guides/how-to-price-a-swap-using-the-api.md).

***

### The /swaption\_price Endpoint

```
GET https://api.bluegamma.io/v1/swaption_price
x-api-key: your_api_key_here
```

See the [interactive API reference](https://www.bluegamma.io/interest-rate-api#tag/swaptions/GET/swaption_price) for the full request/response schema.

#### Request Parameters

| Field            | Required | Description                                                                                    |
| ---------------- | -------- | ---------------------------------------------------------------------------------------------- |
| `index`          | Yes      | Reference rate index (e.g., "SOFR", "SONIA", "3M EURIBOR")                                     |
| `start_date`     | Yes      | Exercise / swap start date. Date (YYYY-MM-DD) or tenor (e.g., "2Y")                            |
| `maturity_date`  | Yes      | Swap end date. Date (YYYY-MM-DD) or tenor from start date (e.g., "5Y")                         |
| `strike_rate`    | No       | Strike rate as percentage (e.g., 3.5 for 3.5%). If omitted, priced at-the-money (forward rate) |
| `notional`       | No       | Notional amount. Defaults to 10,000,000                                                        |
| `swaption_type`  | No       | `"payer"` or `"receiver"`. Defaults to `"payer"`                                               |
| `valuation_time` | No       | ISO 8601 timestamp (UTC). Defaults to current time                                             |

For a full list of supported indices, see [Available Indices](/documentation/integrations/available-indices.md).

{% hint style="info" %}
**Swaption-supported indices:** Not all API indices support swaption pricing — volatility data must be available for the currency. Currently supported: SOFR, SONIA, 1M EURIBOR, 3M EURIBOR, 6M EURIBOR, SARON, AONIA, 3M CDOR, NOWA, SWESTR, STINA, DESTR, CITA, 3M JIBAR, ZARONIA, 3M HIBOR, HONIA, 3M KLIBOR, OCR, NZONIA.
{% endhint %}

#### Response Fields

| Field                   | Description                                                               |
| ----------------------- | ------------------------------------------------------------------------- |
| `index`                 | The reference rate index                                                  |
| `currency`              | Derived currency (e.g., "USD" for SOFR)                                   |
| `swaption_type`         | `"payer"` or `"receiver"`                                                 |
| `start_date`            | Swap start date (YYYY-MM-DD)                                              |
| `maturity_date`         | Swap end date (YYYY-MM-DD)                                                |
| `exercise_date`         | Option exercise date (= start\_date for European swaptions)               |
| `valuation_time`        | Valuation timestamp (ISO 8601)                                            |
| `notional`              | Notional amount                                                           |
| `forward_rate`          | ATM forward swap rate (%)                                                 |
| `strike_rate`           | Strike rate used for pricing (%)                                          |
| `normal_volatility_bps` | Normal (Bachelier) volatility in **basis points**                         |
| `npv`                   | Net present value of the swaption in currency units                       |
| `premium_pct`           | Swaption premium as a percentage of notional                              |
| `dv01`                  | NPV sensitivity to a 1bp parallel shift in the swap rate (currency units) |
| `vega`                  | NPV sensitivity to a 1bp shift in normal volatility (currency units)      |

***

### Example 1: Price an ATM Payer Swaption

The simplest case — price a 2-year into 5-year (2Yx5Y) SOFR payer swaption at-the-money. Omit `strike_rate` and the API prices at the forward swap rate.

```python
import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://api.bluegamma.io/v1"
headers = {
    "x-api-key": API_KEY,
}

# Price a 2Yx5Y ATM payer swaption on SOFR
response = requests.get(
    f"{BASE_URL}/swaption_price",
    headers=headers,
    params={
        "index": "SOFR",
        "start_date": "2Y",
        "maturity_date": "5Y",
        "notional": 10000000
    }
)

data = response.json()
print(f"Forward Rate: {data['forward_rate']:.4f}%")
print(f"Strike Rate:  {data['strike_rate']:.4f}%")
print(f"Normal Vol:   {data['normal_volatility_bps']:.1f} bps")
print(f"NPV:          ${data['npv']:,.2f}")
print(f"Premium:      {data['premium_pct']:.3f}%")
print(f"DV01:         ${data['dv01']:,.2f}")
print(f"Vega:         ${data['vega']:,.2f}")
```

```bash
curl -X GET "https://api.bluegamma.io/v1/swaption_price?index=SOFR&start_date=2Y&maturity_date=5Y&notional=10000000" \
  -H "x-api-key: your_api_key_here"
```

**Example Response:**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "swaption_type": "payer",
  "start_date": "2028-02-23",
  "maturity_date": "2033-02-23",
  "exercise_date": "2028-02-23",
  "valuation_time": "2026-02-23T15:30:00Z",
  "notional": 10000000,
  "forward_rate": 3.30,
  "strike_rate": 3.30,
  "normal_volatility_bps": 76.1,
  "npv": 96709.00,
  "premium_pct": 0.967,
  "dv01": 2850.00,
  "vega": 1271.60
}
```

**Key Points:**

* Since no `strike_rate` was provided, the swaption is priced **at-the-money** — strike equals the forward swap rate (3.30%)
* `npv` is the premium — the price you would pay for this option
* `premium_pct` expresses the NPV as a percentage of notional (0.967% of $10M = $96,709)
* `dv01` tells you the NPV sensitivity to a 1bp move in the underlying swap rate — directly comparable to the `pv01` on the swap endpoint
* The forward rate is the par swap rate for the underlying 5Y swap starting in 2Y — see [How to Price a Swap Using the API](/documentation/integrations/api/how-to-guides/how-to-price-a-swap-using-the-api.md) for more on swap pricing

{% hint style="success" %}
**Want help integrating swaption pricing into your workflow?** Book a 15-minute call and we'll walk you through your first API integration.

[Book a demo →](https://app.lemcal.com/@alivohra/website-demo?back=1)
{% endhint %}

***

### Example 2: Price an OTM Receiver Swaption

Specify a `strike_rate` and change `swaption_type` to price an out-of-the-money receiver swaption.

```python
# Price a 2Yx5Y receiver swaption with a 3.0% strike
response = requests.get(
    f"{BASE_URL}/swaption_price",
    headers=headers,
    params={
        "index": "SOFR",
        "start_date": "2Y",
        "maturity_date": "5Y",
        "strike_rate": 3.0,
        "swaption_type": "receiver",
        "notional": 10000000
    }
)

data = response.json()
print(f"Forward Rate: {data['forward_rate']:.4f}%")
print(f"Strike Rate:  {data['strike_rate']:.4f}%")
print(f"NPV:          ${data['npv']:,.2f}")
print(f"DV01:         ${data['dv01']:,.2f}")
```

```bash
curl -X GET "https://api.bluegamma.io/v1/swaption_price?index=SOFR&start_date=2Y&maturity_date=5Y&strike_rate=3.0&swaption_type=receiver&notional=10000000" \
  -H "x-api-key: your_api_key_here"
```

**Example Response:**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "swaption_type": "receiver",
  "start_date": "2028-02-23",
  "maturity_date": "2033-02-23",
  "exercise_date": "2028-02-23",
  "valuation_time": "2026-02-23T15:30:00Z",
  "notional": 10000000,
  "forward_rate": 3.30,
  "strike_rate": 3.0,
  "normal_volatility_bps": 76.1,
  "npv": 85000.00,
  "premium_pct": 0.85,
  "dv01": -1710.00,
  "vega": 1100.00
}
```

**Interpretation:**

* The strike (3.0%) is **below** the forward rate (3.30%), making this receiver swaption **out-of-the-money**
* A receiver swaption benefits if rates fall — the holder would receive 3.0% fixed when the market expects \~3.30%
* `dv01` is **negative** for receiver swaptions — the option gains value when rates fall
* The NPV is lower than the ATM case because the option is less likely to be exercised

{% hint style="info" %}
**Pro Tip:** For a payer swaption, strikes **above** the forward rate are OTM. For a receiver swaption, strikes **below** the forward rate are OTM.
{% endhint %}

***

### Example 3: Price a EURIBOR Swaption

The endpoint supports multiple currencies. Here's a 1-year into 10-year EURIBOR payer swaption.

```python
# Price a 1Yx10Y ATM payer swaption on 3M EURIBOR
response = requests.get(
    f"{BASE_URL}/swaption_price",
    headers=headers,
    params={
        "index": "3M EURIBOR",
        "start_date": "1Y",
        "maturity_date": "10Y",
        "swaption_type": "payer"
    }
)

data = response.json()
print(f"Currency:     {data['currency']}")
print(f"Forward Rate: {data['forward_rate']:.4f}%")
print(f"Normal Vol:   {data['normal_volatility_bps']:.1f} bps")
print(f"NPV:          €{data['npv']:,.2f}")
```

```bash
curl -X GET "https://api.bluegamma.io/v1/swaption_price?index=3M%20EURIBOR&start_date=1Y&maturity_date=10Y&swaption_type=payer" \
  -H "x-api-key: your_api_key_here"
```

**Example Response:**

```json
{
  "index": "3M EURIBOR",
  "currency": "EUR",
  "swaption_type": "payer",
  "start_date": "2027-02-23",
  "maturity_date": "2037-02-23",
  "exercise_date": "2027-02-23",
  "valuation_time": "2026-02-23T15:30:00Z",
  "notional": 10000000,
  "forward_rate": 2.45,
  "strike_rate": 2.45,
  "normal_volatility_bps": 65.3,
  "npv": 185000.00,
  "premium_pct": 1.85,
  "dv01": 4250.00,
  "vega": 3400.00
}
```

**Key Points:**

* The `currency` is automatically derived from the index — "3M EURIBOR" maps to EUR
* Tenor inputs work the same way: "1Y" start + "10Y" maturity = 1Y into 10Y swaption
* The API handles the underlying swap construction automatically — EURIBOR uses a different swap convention to SOFR, but you don't need to specify this
* For a full list of supported indices, see [Available Indices](/documentation/integrations/available-indices.md)

***

### Example 4: Historical Swaption Valuation

Add `valuation_time` to price using the yield curve and volatility surface as of a specific date and time.

```python
# Price a swaption using historical market data
response = requests.get(
    f"{BASE_URL}/swaption_price",
    headers=headers,
    params={
        "index": "SOFR",
        "start_date": "2Y",
        "maturity_date": "5Y",
        "swaption_type": "payer",
        "valuation_time": "2026-01-15T16:00:00Z"
    }
)

data = response.json()
print(f"Valuation Time: {data['valuation_time']}")
print(f"Forward Rate:   {data['forward_rate']:.4f}%")
print(f"NPV:            ${data['npv']:,.2f}")
```

```bash
curl -X GET "https://api.bluegamma.io/v1/swaption_price?index=SOFR&start_date=2Y&maturity_date=5Y&swaption_type=payer&valuation_time=2026-01-15T16%3A00%3A00Z" \
  -H "x-api-key: your_api_key_here"
```

**Key Points:**

* The API uses the yield curve and volatility surface as of the specified `valuation_time`
* Timestamps are interpreted as UTC — pass ISO 8601 format (e.g., `"2026-01-15T16:00:00Z"`)
* Useful for back-testing, P\&L attribution, and audit trails
* For historical swap rate analysis, see [https://github.com/Blue-Gamma/BlueGammaUI/blob/development/bluegamma-docs/integrations/api/how-to-guides/fetching-historical-swap-rates.md](https://github.com/Blue-Gamma/BlueGammaUI/blob/development/bluegamma-docs/integrations/api/how-to-guides/fetching-historical-swap-rates.md "mention")

By looping `valuation_time` over a date range, you can track how a swaption's value evolves. The chart below shows a 2Y×5Y ATM SOFR payer swaption priced weekly over the past six months:

<figure><img src="/files/midsCnzpeyp7XXScFfkX" alt="Historical 2Yx5Y ATM payer swaption NPV, forward rate, and normal volatility over six months for SOFR with $10M notional"><figcaption><p>2Y×5Y ATM payer swaption (SOFR, $10M notional) — NPV tracks both the forward rate and volatility regime</p></figcaption></figure>

***

### Understanding DV01 and Vega

The API returns two risk sensitivities alongside the NPV.

**DV01**

DV01 measures how much the swaption NPV changes for a 1 basis point parallel shift in the underlying swap rate. It is directly comparable to the `pv01` returned by the swap pricing endpoint.

* **Payer swaption:** DV01 is **positive** — the option gains value when rates rise.
* **Receiver swaption:** DV01 is **negative** — the option gains value when rates fall.
* At-the-money, the swaption DV01 is approximately **half** of the underlying swap's PV01.

DV01 is useful for hedging — to delta-hedge a swaption, you would enter into a swap with notional sized so that the swap PV01 offsets the swaption DV01.

**Vega**

Vega measures the NPV change per **1 basis point** shift in normal volatility.

* A vega of 1,270 means a 1bp increase in vol increases the swaption NPV by approximately $1,270
* Vega is highest at-the-money and decreases for deep ITM or OTM swaptions

| Greek  | Meaning                     | Units          | ATM Payer (10M, 6Mx5Y SOFR) |
| ------ | --------------------------- | -------------- | --------------------------- |
| `dv01` | Swap rate sensitivity / 1bp | Currency units | \~2,850                     |
| `vega` | Vol sensitivity / 1bp       | Currency units | \~1,270                     |

***

### How Volatility Works

The `normal_volatility_bps` field in the response is **normal (Bachelier) volatility in basis points**. This is the market-standard convention for quoting rates swaption volatility — it represents the expected absolute move in the swap rate, not a percentage move.

Normal vol is sourced directly from market data and used in the Bachelier model without conversion.

{% hint style="info" %}
**Note:** The volatility surface currently uses ATM normal vol for all strikes. Smile and skew adjustments are not yet modelled. For highly ITM or OTM swaptions, the NPV may differ from smile-adjusted market quotes.
{% endhint %}

***

### Error Handling

Always handle potential API errors. For rate limit details, see [Rate Limits & Best Practices](/documentation/integrations/api/rate-limits.md).

```python
response = requests.get(f"{BASE_URL}/swaption_price", headers=headers, params=params)

if response.status_code == 200:
    data = response.json()
    print(f"NPV:  ${data['npv']:,.2f}")
    print(f"DV01: ${data['dv01']:,.2f}")
elif response.status_code == 403:
    print("Error: Invalid API key")
elif response.status_code == 422:
    print(f"Validation error: {response.json()}")
elif response.status_code == 429:
    print("Rate limit exceeded — please wait and retry")
else:
    print(f"Error: {response.status_code} - {response.text}")
```

**Common 422 Errors:**

| Error                       | Cause                                                       |
| --------------------------- | ----------------------------------------------------------- |
| Unsupported index           | The index does not have swaption vol data available         |
| Invalid swaption type       | `swaption_type` must be `"payer"` or `"receiver"`           |
| Maturity before start date  | `maturity_date` must be after `start_date`                  |
| Dates before valuation time | Both dates must be in the future relative to valuation time |

***

### Summary: Payer vs Receiver Swaptions

| Scenario                | `swaption_type` | Right Granted               | Benefits When...            |
| ----------------------- | --------------- | --------------------------- | --------------------------- |
| **Hedge rising rates**  | `"payer"`       | Pay fixed, receive floating | Rates rise above the strike |
| **Hedge falling rates** | `"receiver"`    | Receive fixed, pay floating | Rates fall below the strike |

| Use Case          | `strike_rate` Parameter | What You Get                                    |
| ----------------- | ----------------------- | ----------------------------------------------- |
| **ATM option**    | Omit                    | Strike = forward rate, DV01 ≈ half of swap PV01 |
| **Custom strike** | Provide (e.g., 3.5)     | OTM/ITM pricing, DV01 reflects moneyness        |

For comparison with vanilla swap valuation, see [How to Price a Swap Using the API](/documentation/integrations/api/how-to-guides/how-to-price-a-swap-using-the-api.md).

***

### API Endpoint Reference

| Endpoint          | Method | Use Case                               |
| ----------------- | ------ | -------------------------------------- |
| `/swaption_price` | GET    | European swaption pricing with Greeks  |
| `/swap_pricer`    | POST   | Full swap pricing with cashflows       |
| `/swap_rate`      | GET    | Quick par rate for the underlying swap |
| `/forward_rate`   | GET    | Forward rate between any two dates     |

For the complete API specification, see the [interactive API reference](https://www.bluegamma.io/interest-rate-api#tag/swaptions/GET/swaption_price).

***

### Related Guides

* [How to Price a Swap Using the API](/documentation/integrations/api/how-to-guides/how-to-price-a-swap-using-the-api.md) — Full swap pricing (the underlying instrument)
* [Fetching a Swap Rate](/documentation/integrations/api/how-to-guides/fetching-a-swap-rate.md) — Quick par rate lookup
* [Fetching a Swap Curve](/documentation/integrations/api/how-to-guides/fetching-a-swap-curve.md) — Get rates for all tenors
* [Getting Forward Rates](/documentation/integrations/api/how-to-guides/getting-forward-rates.md) — Forward rates for custom periods
* [Getting Discount Factors](/documentation/integrations/api/how-to-guides/getting-discount-factors.md) — Discount factors for PV calculations
* [Validating BlueGamma API Data Against Bloomberg or Other Platforms](/documentation/integrations/api/how-to-guides/validating-bluegamma-api-data-against-bloomberg-or-other-platforms.md) — Compare with Bloomberg

***

**Need help?** 📩 <support@bluegamma.io> | 📅 [Book a call](https://app.lemcal.com/@alivohra/website-demo?back=1)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bluegamma.io/documentation/integrations/api/how-to-guides/how-to-price-a-swaption-using-the-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
