> For the complete documentation index, see [llms.txt](https://www.bluegamma.io/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.bluegamma.io/documentation/integrations/api/how-to-guides/pricing-an-interest-rate-cap.md).

# Pricing an Interest Rate Cap

Price interest rate caps with caplet-level breakdown, SABR volatility smile, and full Greeks using the BlueGamma API.

The `/cap_floor_price` endpoint prices interest rate caps (and floors) with a full caplet-level breakdown. Use this when you need to **price caps programmatically**, run **strike/tenor scenarios**, or feed cap valuations into a **risk or advisory workflow**.

***

## Basic Example: ATM Cap

Price a 3Y ATM SOFR cap on $10M notional with quarterly caplets:

```python
import requests

url = "https://api.bluegamma.io/v1/cap_floor_price"
headers = {"x-api-key": "your_api_key"}

params = {
    "index": "SOFR",
    "start_date": "0D",
    "maturity_date": "3Y",
    "cap_or_floor": "cap",
    "notional": 10000000,
    "frequency": "3M"
}

response = requests.get(url, headers=headers, params=params)
data = response.json()

print(f"Strike: {data['strike_rate']:.2f}% (ATM)")
print(f"NPV: ${data['npv']:,.2f}")
print(f"Premium: {data['premium_pct']:.2f}% of notional")
print(f"Delta: {data['delta']:.2f}")
print(f"Vega: {data['vega']:.2f}")
```

```bash
curl -X GET "https://api.bluegamma.io/v1/cap_floor_price?index=SOFR&start_date=0D&maturity_date=3Y&cap_or_floor=cap&notional=10000000&frequency=3M" \
  -H "x-api-key: your_api_key_here"
```

**Response (April 2026):**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "type": "cap",
  "start_date": "2026-04-16",
  "maturity_date": "2029-04-16",
  "frequency": "3M",
  "notional": 10000000.0,
  "forward_rate": 3.4954,
  "strike_rate": 3.4954,
  "npv": 103164.16,
  "premium_pct": 1.0316,
  "delta": 5.6768,
  "vega": 1215.31,
  "num_caplets": 11,
  "vol_type": "sabr_calibrated",
  "sabr_rho": -0.433,
  "sabr_nu": 1.3622,
  "caplets": [
    {
      "accrual_start": "2026-07-16",
      "accrual_end": "2026-10-16",
      "forward_rate": 3.6645,
      "strike": 3.4954,
      "notional": 10000000.0,
      "normal_vol_bps": 75.67,
      "npv": 6298.32,
      "delta": 0.6717,
      "vega": 45.64,
      "discount_factor": 0.9816,
      "accrual_fraction": 0.2556
    }
  ],
  "timestamp": "2026-04-16T14:25:57"
}
```

{% hint style="info" %}
**ATM strike:** When no `strike_rate` is provided, the API uses the ATM forward rate. The caplets array above shows 1 of 11 caplets for brevity.
{% endhint %}

| Field         | Description                                                                                                                                                |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `npv`         | Net present value of the cap in the notional currency                                                                                                      |
| `premium_pct` | NPV as a percentage of notional                                                                                                                            |
| `strike_rate` | The cap strike (ATM forward if omitted)                                                                                                                    |
| `delta`       | Rate sensitivity (sum across all caplets)                                                                                                                  |
| `vega`        | Volatility sensitivity (sum across all caplets)                                                                                                            |
| `vol_type`    | Volatility model used: `sabr_calibrated` for SOFR and `flat` for others with the default `vol_smile=auto`, or `sabr_manual` when you pass `vol_smile=sabr` |
| `caplets`     | Array of per-caplet pricing detail                                                                                                                         |

***

## Use Case: OTM Cap with Custom Strike

Price the same cap with a 4.50% strike (out-of-the-money):

```python
params = {
    "index": "SOFR",
    "start_date": "0D",
    "maturity_date": "3Y",
    "strike_rate": 4.5,
    "cap_or_floor": "cap",
    "notional": 10000000,
    "frequency": "3M"
}

response = requests.get(url, headers=headers, params=params)
data = response.json()
```

```bash
curl -X GET "https://api.bluegamma.io/v1/cap_floor_price?index=SOFR&start_date=0D&maturity_date=3Y&strike_rate=4.5&cap_or_floor=cap&notional=10000000&frequency=3M" \
  -H "x-api-key: your_api_key_here"
```

**Output (April 2026):**

```
Strike: 4.50%
NPV: $32,025.49
Premium: 0.32% of notional
```

The 4.50% cap costs $32k vs $103k for ATM -- reflecting the lower probability of SOFR exceeding 4.50%.

***

## Use Case: Amortising Cap with a Notional Schedule

To price a cap on an amortising loan, send a `POST` request with `notional` as a list: one amount per caplet, in order. This example prices a 3Y quarterly SOFR cap starting in 3 months at a 4.00% strike, on $10M paying down $500k a quarter:

```python
import requests

url = "https://api.bluegamma.io/v1/cap_floor_price"
headers = {"x-api-key": "your_api_key"}

payload = {
    "index": "SOFR",
    "start_date": "3M",
    "maturity_date": "3Y",
    "strike_rate": 4.0,
    "cap_or_floor": "cap",
    "frequency": "3M",
    "notional": [10_000_000 - 500_000 * i for i in range(12)]
}

response = requests.post(url, headers=headers, json=payload)
data = response.json()

print(f"Caplets: {data['num_caplets']}")
print(f"NPV: ${data['npv']:,.2f}")
```

```bash
curl -X POST "https://api.bluegamma.io/v1/cap_floor_price" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"index": "SOFR", "start_date": "3M", "maturity_date": "3Y", "strike_rate": 4.0, "cap_or_floor": "cap", "frequency": "3M", "notional": [10000000, 9500000, 9000000, 8500000, 8000000, 7500000, 7000000, 6500000, 6000000, 5500000, 5000000, 4500000]}'
```

**Response (October 2026):**

```json
{
  "index": "SOFR",
  "currency": "USD",
  "type": "cap",
  "start_date": "2027-01-06",
  "maturity_date": "2030-01-07",
  "frequency": "3M",
  "notional": [10000000.0, 9500000.0, 9000000.0, 8500000.0, 8000000.0, 7500000.0, 7000000.0, 6500000.0, 6000000.0, 5500000.0, 5000000.0, 4500000.0],
  "forward_rate": 4.69905,
  "strike_rate": 4.0,
  "npv": 191471.57,
  "premium_pct": 1.9147,
  "delta": 8.338844,
  "vega": 831.7,
  "num_caplets": 12,
  "caplets": [
    {
      "accrual_start": "2027-01-06",
      "accrual_end": "2027-04-06",
      "forward_rate": 4.30722,
      "strike": 4.0,
      "notional": 10000000.0,
      "normal_vol_bps": 125.35,
      "npv": 11510.09,
      "delta": 0.66313,
      "vega": 52.07,
      "discount_factor": 0.979287,
      "accrual_fraction": 0.25
    },
    {
      "accrual_start": "2027-04-06",
      "accrual_end": "2027-07-06",
      "forward_rate": 4.57401,
      "strike": 4.0,
      "notional": 9500000.0,
      "normal_vol_bps": 124.23,
      "npv": 17075.97,
      "delta": 0.726287,
      "vega": 59.52,
      "discount_factor": 0.968094,
      "accrual_fraction": 0.252778
    }
  ],
  "vol_type": "sabr_calibrated",
  "timestamp": "2026-10-06T08:36:17",
  "sabr_rho": 0.6568,
  "sabr_nu": 0.4468
}
```

Each caplet carries its own `notional`, and `premium_pct` is measured against the first amount in the list. The caplets array above shows 2 of 12 for brevity. To check how many amounts the schedule needs, price it once with a single notional and read `num_caplets`.

{% hint style="info" %}
**Mid-market price:** The API returns the mid-market price, with no bank charge. A short or long first period (set by a first interest payment date) and the bank charge are available in the web app's [Cap Pricer](/documentation/pricers/pricing-a-cap.md).
{% endhint %}

***

## Use Case: Visualising the Caplet Breakdown

Each caplet represents one reset period. Plotting NPVs and forward rates shows where value concentrates:

```python
import requests
import matplotlib.pyplot as plt
from datetime import datetime

url = "https://api.bluegamma.io/v1/cap_floor_price"
headers = {"x-api-key": "your_api_key"}

data = requests.get(url, headers=headers, params={
    "index": "SOFR", "start_date": "0D", "maturity_date": "3Y",
    "cap_or_floor": "cap", "notional": 10000000, "frequency": "3M"
}).json()

dates = [datetime.strptime(c["accrual_start"], "%Y-%m-%d") for c in data["caplets"]]
npvs = [c["npv"] for c in data["caplets"]]
forwards = [c["forward_rate"] for c in data["caplets"]]

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 7), sharex=True)

ax1.bar(dates, npvs, width=25, color="#2563eb", alpha=0.8)
ax1.set_ylabel("Caplet NPV ($)")
ax1.set_title(f"3Y ATM SOFR Cap: {data['num_caplets']} Caplets, Total NPV ${data['npv']:,.0f}")

ax2.plot(dates, forwards, "o-", color="#2563eb", label="Forward Rate")
ax2.axhline(y=data["strike_rate"], color="#ef4444", linestyle="--", label=f"Strike ({data['strike_rate']:.2f}%)")
ax2.set_ylabel("Rate (%)")
ax2.legend()

plt.tight_layout()
plt.show()
```

<figure><img src="https://3184259219-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmmQPefoflG1RwUnUKKBR%2Fuploads%2Fgit-blob-1d84e60e6bf41adf19d75bc1962397229a3d5566%2Fcap-pricing-caplet-breakdown.png?alt=media" alt="3Y ATM SOFR cap caplet NPV breakdown and forward rates vs strike"><figcaption><p>3Y ATM SOFR cap: caplet NPVs (top) and forward rates vs strike (bottom) -- April 2026</p></figcaption></figure>

Near-term caplets (where forwards exceed the strike) carry more intrinsic value. Later caplets derive value from time value as forwards converge toward the strike.

***

## Caplet Response Fields

| Caplet Field                    | Description                                           |
| ------------------------------- | ----------------------------------------------------- |
| `accrual_start` / `accrual_end` | The period the caplet covers                          |
| `forward_rate`                  | Implied forward rate for that period (%)              |
| `strike`                        | The strike rate (%)                                   |
| `normal_vol_bps`                | Normal (Bachelier) implied volatility in basis points |
| `npv`                           | Present value of this caplet                          |
| `delta`                         | Rate sensitivity of this caplet                       |
| `vega`                          | Volatility sensitivity of this caplet                 |
| `discount_factor`               | Discount factor to the payment date                   |
| `accrual_fraction`              | Year fraction for the accrual period                  |

**First 4 caplets of the 3Y ATM SOFR cap (April 2026):**

| Period             | Forward | Vol (bps) | NPV    | Delta |
| ------------------ | ------- | --------- | ------ | ----- |
| Jul--Oct 2026      | 3.66%   | 75.67     | $6,298 | 0.672 |
| Oct 2026--Jan 2027 | 3.63%   | 81.89     | $7,891 | 0.592 |
| Jan--Apr 2027      | 3.59%   | 83.68     | $7,969 | 0.550 |
| Apr--Jul 2027      | 3.55%   | 85.85     | $9,002 | 0.525 |

***

## Volatility Smile Models

The `vol_smile` parameter controls how implied volatility varies with strike:

| Mode             | Behaviour                                                                  |
| ---------------- | -------------------------------------------------------------------------- |
| `auto` (default) | SABR smile for SOFR (calibrated from market data), flat ATM vol for others |
| `flat`           | ATM swaption vol for all strikes -- simpler, no skew                       |
| `sabr`           | User-provided SABR parameters. Requires `sabr_rho` and `sabr_nu`           |

{% hint style="info" %}
With `auto`, the response includes `sabr_rho` and `sabr_nu` so you can see the calibration used.
{% endhint %}

***

## Parameters

| Parameter        | Required | Description                                                                          |
| ---------------- | -------- | ------------------------------------------------------------------------------------ |
| `index`          | Yes      | Rate index (e.g., `SOFR`, `SONIA`, `3M EURIBOR`)                                     |
| `start_date`     | Yes      | Cap start date (`0D` for spot, or `YYYY-MM-DD`)                                      |
| `maturity_date`  | Yes      | Cap maturity (`3Y`, `5Y`, or `YYYY-MM-DD`)                                           |
| `strike_rate`    | No       | Strike as percentage (e.g., `4.5`). Omit for ATM                                     |
| `cap_or_floor`   | No       | `cap` (default) or `floor`                                                           |
| `notional`       | No       | Notional amount. Default: 10,000,000. With `POST`, a list of amounts, one per caplet |
| `frequency`      | No       | Caplet frequency (`1M`, `3M`, `6M`). Default: `3M`                                   |
| `valuation_time` | No       | Historical timestamp (ISO 8601) for reproducibility                                  |
| `vol_smile`      | No       | `auto` (default), `flat`, or `sabr`                                                  |
| `sabr_rho`       | No       | SABR correlation (-1 to 1). Required for `vol_smile=sabr`                            |
| `sabr_nu`        | No       | SABR vol-of-vol (> 0). Required for `vol_smile=sabr`                                 |

***

## Related Endpoints

| If you need...                   | Use                                                                                             |
| -------------------------------- | ----------------------------------------------------------------------------------------------- |
| The underlying swap rate         | [`/swap_rate`](/documentation/integrations/api/how-to-guides/fetching-a-swap-rate.md)           |
| Forward rates for the cap period | [`/forward_curve`](/documentation/integrations/api/how-to-guides/getting-a-forward-curve.md)    |
| Discount factors                 | [`/discount_factor`](/documentation/integrations/api/how-to-guides/getting-discount-factors.md) |
| The full swap curve              | [`/get_swap_curve`](/documentation/integrations/api/how-to-guides/fetching-a-swap-curve.md)     |

***

Create a key under **API Keys** in the app sidebar. See [Authentication](/documentation/integrations/api/authentication.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://www.bluegamma.io/documentation/integrations/api/how-to-guides/pricing-an-interest-rate-cap.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
