---
title: "Modelling interest rate swaps in LUSID"
slug: "modelling-interest-rate-swaps-in-lusid"
updated: 2026-06-26T06:55:25Z
published: 2026-06-26T06:55:25Z
canonical: "support.lusid.com/modelling-interest-rate-swaps-in-lusid"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://support.lusid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Modelling interest rate swaps in LUSID

You can model certain interest rate swap contracts as instruments of type `InterestRateSwap` in LUSID. [See all supported instruments](/v1/docs/what-instruments-does-lusid-support).

- Vanilla swaps with a fixed and a floating leg, or two fixed or two floating legs if required.
- Cross-currency swaps with any combination of fixed/floating legs and notional exchange.
- Basis swaps with floating legs referencing different indices or tenors.
- Amortising swaps with any combination of fixed/floating legs and decreasing notionals.

This article explains how to use the LUSID API to first master an instrument and then load a transaction:

- You can simplify setup by loading a transaction in the web app and have LUSID [master the instrument for you](/v1/docs/modelling-interest-rate-swaps-in-lusid#appendix-using-the-lusid-web-app-to-simplify-repurchase-agreements).
- If you enable instrument events you must create transaction types to [handle those events](/v1/docs/handling-instrument-events-for-interest-rate-swaps).
- For an implementation using the Python SDK see [this Jupyter Notebook](https://github.com/finbourne/finbourne-notebooks/blob/main/V3/features/instrument-events/Interest-rate-swap-and-instrument-events.ipynb).

## Mastering an instrument

There are [numerous tools](/v1/docs/how-do-i-master-an-instrument) you can use to master an `InterestRateSwap` in the LUSID Security Master.

Some fields are common to all types of instrument, such as an intuitive `name`, the [requirement to specify a set](/v1/docs/understanding-instrument-identifiers) of `identifiers`, and the facility to [store extra information](/v1/docs/properties) as `properties`:

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-UC6SW9YY.png)

### Understanding the economic definition of an interest rate swap

Fields in the economic `definition` object are specific to an `InterestRateSwap`.

The composition of this object is dependent on the kind of swap you want to master. Consider the following call to the [UpsertInstruments](https://www.lusid.com/docs/api/lusid/endpoints/instruments/UpsertInstruments) API; note this is actually a no-op request, since the `legs` array must be populated:

REST APIPython SDK

```json
curl -X POST "https://<your-domain>.lusid.com/api/api/instruments?scope=mycustominstrscope"
   -H "Content-Type: application/json-patch+json"
   -H "Authorization: Bearer <your-API-access-token>"
   -d '{
  "upsert_request_1": {
    "name": "IRS-15Jan30",
    "identifiers": {
      "ClientInternal": {"value": "IRS-15Jan30"}
    },
    "definition": {
      "instrumentType": "InterestRateSwap",
      "startDate": "2025-01-15T00:00:00Z",
      "maturityDate": "2030-01-15T00:00:00Z",
      "legs": [],
      "additionalPayments": []
    }
  }
}'
```

The economic definition of the entire swap in this article is given in the example below, since it is not always clear how API schemas map to SDK models:

```python
instruments_api = lusid_api_factory.build(lusid.api.InstrumentsApi)
instrument_request = {
    "upsert_request_1": lusid.models.InstrumentDefinition(
        name = "IRS-15Jan30",
        identifiers = {"ClientInternal": lusid.models.InstrumentIdValue(value = "IRS-15Jan30")},
        definition = lusid.models.InterestRateSwap(
            instrumentType = "InterestRateSwap",
            startDate = "2025-01-15T00:00:00Z",
            maturityDate = "2030-01-15T00:00:00Z",
            legs = [
                lusid.models.FixedLeg(
                    instrumentType = "FixedLeg",
                    startDate = "2025-01-15T00:00:00Z",
                    maturityDate = "2030-01-15T00:00:00Z",
                    notional = 1000000,
                    legDefinition = lusid.models.LegDefinition(
                        notionalExchangeType = "None",
                        payReceive = "Receive",
                        rateOrSpread = 0.05,
                        stubType = "None",
                        conventions=lm.FlowConventions(
                            currency = "USD",
                            payment_frequency = "12M",
                            day_count_convention = "Actual365",
                            roll_convention = "15",
                            business_day_convention = "Following",
                            payment_calendars = [],
                            reset_calendars = []
                        )
                    )
                ),
                lusid.models.FloatingLeg(
                    instrumentType = "FloatingLeg",
                    startDate = "2025-01-15T00:00:00Z",
                    maturityDate = "2030-01-15T00:00:00Z",
                    notional = 1000000,
                    legDefinition = lusid.models.LegDefinition(
                        notionalExchangeType = "None",
                        payReceive = "Pay",
                        rateOrSpread = 0,
                        stubType = "None",
                        conventions=lusid.models.FlowConventions(
                            currency = "USD",
                            payment_frequency = "12M",
                            day_count_convention = "Actual365",
                            roll_convention = "15",
                            business_day_convention = "Following",
                            payment_calendars = [],
                            reset_calendars = []
                        ),
                        index_convention = lusid.models.IndexConvention(
                            fixing_reference = "USD-SOFR-COMPOUNDED-INDEX",
                            publication_day_lag = 0,
                            payment_tenor = '1D',
                            day_count_convention= 'Actual365',
                            currency = 'USD', 
                            index_name = 'SOFRINDEX'
                        ),
                        resetConvention="InArrears",
                        compounding=lusid.models.Compounding(
                            compoundingMethod="CompoundedIndex",
                            spreadCompoundingMethod="SpreadExclusive",
                            resetFrequency="1D"
                        )
                    )
                )
            ]
        )
    )
}
try:
    instrument_response = instruments_api.upsert_instruments(
        request_body = instrument_request,
        scope = "mycustominstrscope"
    )
except lusid.ApiException as e:
    print(e)
```

For information on every field, examine the [InterestRateSwap](https://www.lusid.com/docs/api/lusid/schemas/InterestRateSwap/) schema. Note in particular the following:

- The `instrumentType` must be `InterestRateSwap`.
- The `startDate` is typically the transaction date but can be before or after if required.
- The `legs` array **must** contain two legs, one with `payReceive` set to `Pay` and the other to `Receive`. These can both be a fixed leg, both be a [floating leg](/v1/docs/modelling-interest-rate-swaps-in-lusid#specifying-a-floating-leg), or one of each. The order does not matter.
- You can record `additionalPayments` if you wish but this has no downstream impact at present.

### Specifying a fixed leg

Consider the following example of a fixed leg set to receive 5% on a £100,000 notional once a year on the 15th:

```json
{
  "instrumentType": "FixedLeg",
  "startDate": "2025-01-15T00:00:00Z",
  "maturityDate": "2030-01-15T00:00:00Z",
  "notional": 100000,
  "legDefinition": {
    "notionalExchangeType": "None",
    "payReceive": "Receive",
    "rateOrSpread": 0.05,
    "stubType": "None",
    "conventions": {
      "currency": "USD",
      "paymentFrequency": "12M",
      "dayCountConvention": "Actual365",
      "rollConvention": "15",
      "businessDayConvention": "Following",
      "paymentCalendars": [],
      "resetCalendars": []
    }
  }
}
```

For information on all fields, examine the [FixedLeg](https://www.lusid.com/docs/api/lusid/schemas/FixedLeg/) schema. Note in particular the following:

- `payReceive` is set to `Receive`. One leg **must** receive payment.
- For a fixed leg, `rateOrSpread` refers to the fixed interest rate expressed as a decimal rather than a percentage, so:
  - 10% should be specified as `0.1`
  - 2.5% should be specified as `0.02`
  - 0.375% should be specified as `0.00375`.
- `startDate` and `maturityDate` are typically the same as the instrument itself.
- `notional` is set to the full amount and subsequent [transactions](/v1/docs/modelling-interest-rate-swaps-in-lusid#booking-a-transaction-to-establish-a-position) are for a single unit, but you can reverse this if desired.
- `notionalExchangeType` is set to `None` to *not* swap notionals, but this could be `Initial`, `Final` or `Both` for a cross-currency swap.
- `conventions` specifies all the information necessary to determine [payment schedules](/v1/docs/flow-conventions-and-index-conventions#specifying-a-flow-convention). In particular, `rollConvention` specifies the payment day of the month.

### Specifying a floating leg

You must first decide which category of reference index the floating leg should observe:

| Category | Explanation | Example index |
| --- | --- | --- |
| A | The reference rate is observed once per interest rate period. The observation can be made in advance of a period, or towards the end 'in arrears'. | LIBOR |
| B | The reference rate is observed more than once per period (up to daily for overnight indices), with the implication that the final payment amount can be calculated only at the end of a period | SOFR, SONIA |
| C | The reference rate is a compounded index. These indices are published daily and they remove the necessity to capture daily fixings needed for a calculation. The compounding indices are built from daily fixings so the final payment amount can only be calculated at the end of a period. | SOFRINDEX |

Consider the following example of a floating leg observing the SOFR compounded index that pays once a year on the 15th:

```json
{
  "instrumentType": "FloatingLeg",
  "startDate": "2025-01-15T00:00:00Z",
  "maturityDate": "2030-01-15T00:00:00Z",
  "notional": 100000,
  "legDefinition": {
    "notionalExchangeType": "None",
    "payReceive": "Pay",
    "rateOrSpread": 0,
    "stubType": "None",
    "conventions": {
      "currency": "USD",
      "paymentFrequency": "12M",
      "dayCountConvention": "Actual365",
      "rollConvention": "15",
      "businessDayConvention": "Following",
      "paymentCalendars": [],
      "resetCalendars": []
    },
    "indexConvention": {
      "fixingReference": "USD-SOFR-COMPOUNDED-INDEX",
      "publicationDayLag": 0,
      "paymentTenor": "1D",
      "dayCountConvention": "Actual365",
      "currency": "USD",
      "indexName": "SOFRINDEX"
    },
    "resetConvention": "InArrears",
    "compounding": {
      "compoundingMethod": "CompoundedIndex",
      "spreadCompoundingMethod": "SpreadExclusive",
      "resetFrequency": "1D"
    }
  }
}
```

For information on all fields, examine the [FloatingLeg](https://www.lusid.com/docs/api/lusid/schemas/FloatingLeg/) schema. Some fields are common to all swaps; note in particular the following:

- `payReceive` is set to `Pay`. One leg in a swap **must** pay out.
- For a floating leg, `rateOrSpread` refers to a spread on the index, if any. For example, a spread of 50bps should be specified as `0.005`.
- For a vanilla swap, `notional`, `notionalExchangeType`, `stubType` and `conventions` are typically the same as the fixed leg, but can have different values if required (ie. for a cross-currency swap).
- `indexConventions` specifies all the information necessary to calculate [accrued interest amounts](/v1/docs/flow-conventions-and-index-conventions#specifying-an-index-convention) from observed rates in a reference index.

Other fields in a floating leg definition are dependent on the category of the reference index chosen:

| [LegDefinition](https://www.lusid.com/docs/api/lusid/schemas/LegDefinition/) field | **Category A** | **Category B** | **Category C** |
| --- | --- | --- | --- |
| `resetConvention` | Can be `InAdvance` (the default) or `InArrears`. | Must be `InArrears`. | Must be `InArrears`. |
| `indexConvention.paymentTenor` | Can be any [tenor](/v1/docs/specifying-tenors-in-lusid). | Must be `1D`. | Must be `1D`. |
| `compounding.compoundingMethod` ([more information](/v1/docs/how-does-lusid-calculate-compound-interest)) | Do not set. | Can be `Averaging` or `Compounding`. | Must be `CompoundedIndex`. |
| `compounding.spreadCompoundingMethod` | Can be `Straight`, `Flat` or `SpreadExclusive` for `Compounding`. Do not set for `Averaging`. | Must be `SpreadExclusive`. |
| `compounding.averagingMethod` | Can be `Weighted` (the default) or `Unweighted` for `Averaging`. Do not set for `Compounding`. | Do not set. |
| `compounding.resetFrequency` | Can be any [tenor](/v1/docs/specifying-tenors-in-lusid). | Must be `1D`. |
| `compounding.calculationShiftMethod` | Can be `Lookback`, `NoShift`, `ObservationPeriodShift` or `Lockout`. | Can be `NoShift`or `ObservationPeriodShift`. |

### Examining the response

Providing the request is successful, the response:

- Confirms the globally-unique [LUID](/v1/docs/what-is-a-lusid-instrument-id-or-luid) for the instrument;
- Provides version information;
- Generates extra fields that are stored as part of the instrument definition and can be [filtered on](/v1/docs/filtering-information-retrieved-from-lusid);
- Supplies default values for fields not explicitly specified in the request:

```json
{
  "values": {
    "upsert_request_1": {
      "scope": "mycustominstrumentscope",
      "lusidInstrumentId": "LUID_00003H0L",
      "version": {
        "effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
        "asAtDate": "2026-05-13T11:17:30.4381300+00:00",
        "asAtCreated": "2026-05-13T11:17:30.4381300+00:00",
        "userIdCreated": "00u91lo2d7X42sdse2p7",
        "requestIdCreated": "2026051311-1544deac41e442849923be5091f8a00d",
        "reasonCreated": "",
        "asAtModified": "2026-05-13T11:17:30.4381300+00:00",
        "userIdModified": "00u91lo2d7X42sdse2p7",
        "requestIdModified": "2026051311-1544deac41e442849923be5091f8a00d",
        "reasonModified": "",
        "asAtVersionNumber": 1,
        "entityUniqueId": "60a46c85-58cb-40cc-9840-affb724dc72d"
      },
      "name": "IRS-15Jan30",
      "identifiers": {
        "ClientInternal": "IRS-15Jan30",
        "LusidInstrumentId": "LUID_00003H0L"
      },
      "properties": [],
      "instrumentDefinition": {
        "startDate": "2025-01-15T00:00:00.0000000+00:00",
        "maturityDate": "2030-01-15T00:00:00.0000000+00:00",
        "isNonDeliverable": false,
        "legs": [
          {
            "startDate": "2025-01-15T00:00:00.0000000+00:00",
            "maturityDate": "2030-01-15T00:00:00.0000000+00:00",
            "legDefinition": {
              "conventions": {
                "currency": "USD",
                "paymentFrequency": "12M",
                "dayCountConvention": "Actual365",
                "rollConvention": "15",
                "paymentCalendars": [],
                "resetCalendars": [],
                "settleDays": 0,
                "resetDays": 0,
                "leapDaysIncluded": true,
                "accrualDateAdjustment": "Adjusted",
                "businessDayConvention": "F",
                "accrualDayCountConvention": "Actual365"
              },
              "notionalExchangeType": "None",
              "payReceive": "Receive",
              "rateOrSpread": 0.05,
              "resetConvention": "InAdvance",
              "stubType": "None",
              "firstCouponType": "ProRata",
              "lastCouponType": "ProRata",
              "intermediateNotionalExchange": false
            },
            "notional": 100000,
            "overrides": {},
            "instrumentType": "FixedLeg"
          },
          {
            "startDate": "2025-01-15T00:00:00.0000000+00:00",
            "maturityDate": "2030-01-15T00:00:00.0000000+00:00",
            "legDefinition": {
              "conventions": {
                "currency": "USD",
                "paymentFrequency": "12M",
                "dayCountConvention": "Actual365",
                "rollConvention": "15",
                "paymentCalendars": [],
                "resetCalendars": [],
                "settleDays": 0,
                "resetDays": 0,
                "leapDaysIncluded": true,
                "accrualDateAdjustment": "Adjusted",
                "businessDayConvention": "F",
                "accrualDayCountConvention": "Actual365"
              },
              "indexConvention": {
                "fixingReference": "USD-SOFR-COMPOUNDED-INDEX",
                "publicationDayLag": 0,
                "paymentTenor": "1D",
                "dayCountConvention": "Actual365",
                "currency": "USD",
                "indexName": "SOFRINDEX"
              },
              "notionalExchangeType": "None",
              "payReceive": "Pay",
              "rateOrSpread": 0,
              "resetConvention": "InArrears",
              "stubType": "None",
              "compounding": {
                "calculationShiftMethod": "NoShift",
                "compoundingMethod": "CompoundedIndex",
                "resetFrequency": "1D",
                "shift": 0,
                "spreadCompoundingMethod": "SpreadExclusive"
              },
              "firstCouponType": "ProRata",
              "lastCouponType": "ProRata",
              "intermediateNotionalExchange": false
            },
            "notional": 100000,
            "overrides": {},
            "instrumentType": "FloatingLeg"
          }
        ],
        "additionalPayments": [],
        "instrumentType": "InterestRateSwap"
      },
      "state": "Active",
      "assetClass": "InterestRates",
      "domCcy": "USD",
      "relationships": [],
      "dataModelMembership": {
        "membership": []
      }
    }
  },
  "staged": {},
  "failed": {},
  ... 
}
```

## Providing interest rate fixings

If an `InterestRateSwap` has a floating leg, you must [load the correct number of fixings](/v1/docs/how-do-i-load-an-interest-rate-fixing-into-the-lusid-quote-store) into the Quote Store and provide a recipe that enables LUSID to locate them when an accrued interest calculation is required (which is every time you ask LUSID to value a holding or generate cashflows):

| **Category** | **Number of fixings to load** |
| --- | --- |
| A | One per interest rate period. This should be at the start if `resetConvention` is set to `InAdvance`, or at the end if `InArrears`. |
| B | One per day. |
| C | Two per *calculation* period; one at the start of the interest rate period and one at the effective datetime of the valuation or cashflow generation request. Note this means if you make such a request every day you will need to load a fixing every day. |

Consider the example of a Category C swap with the following `fixingReference`:

```json
"indexConvention": {
  "fixingReference": "USD-SOFR-COMPOUNDED-INDEX",
  ...
}
```

The following call to the [UpsertQuotes](https://www.lusid.com/docs/api#operation/UpsertQuotes) API loads two fixings for this index into a particular quote scope:

```json
curl -X POST "https://<your-domain>.lusid.com/api/api/quotes/MySOFRFixings"
  -H "Authorization: Bearer <your-API-access-token>"
  -H "Content-Type: application/json-patch+json"
  -d '{
    "Quote-0001": {
      "quoteId": {
        "quoteSeriesId": {
          "provider": "Lusid",
          "instrumentIdType": "RIC",
          "instrumentId": "USD-SOFR-COMPOUNDED-INDEX",
          "quoteType": "Index",
          "field": "mid"
        },
        "effectiveAt": "2025-01-15"
      },
      "metricValue": {
        "value": 1.17692687, "unit": "none"
      },
      "scaleFactor": 100
    },
    "Quote-0002": {
      "quoteId": {
        "quoteSeriesId": {
          "provider": "Lusid",
          "instrumentIdType": "RIC",
          "instrumentId": "USD-SOFR-COMPOUNDED-INDEX",
          "quoteType": "Index",
          "field": "mid"
        },
        "effectiveAt": "2026-01-15"
      },
      "metricValue": {
        "value": 1.22834029, "unit": "none"
      },
      "scaleFactor": 100
    }
  }'
```

For general information on loading fixings into the Quote Store, see [this article](/v1/docs/how-do-i-load-an-interest-rate-fixing-into-the-lusid-quote-store). Note the following about this example:

- Both fixings are loaded into a `MySOFRFixings` quote scope (specified in the URL) that is only used for fixings, to avoid clashes.
- The `instrumentIdType` of each fixing must be `RIC` or `ClientInternal`.
- The `instrumentId` must be the `fixingReference` specified in the index convention, in this case `USD-SOFR-COMPOUNDED-INDEX`.
- The `provider` is set to `Lusid` and the `field` to `mid`, to avoid validation errors.
- The `quoteType` must be either `Index` or `Rate`.
- The `scaleFactor` is set to `100` to scale the rate down but you could omit this and specify `metricValue.value` as a decimal rather than a percentage, for example `0.0122834029`.

### Creating a suitable recipe

Your recipe must have a [market data rule](/v1/docs/recipes-locating-market-data) able to locate these fixings, for example:

```json
"market": {
  "marketRules": [
    {
      "key": "Quote.RIC.USD-SOFR-COMPOUNDED-INDEX",
      "dataScope": "MySOFRFixings",
      "supplier": "Lusid",
      "quoteType": "Index",
      "field": "mid"
    },
    ...
  ]
},
```

For general information on recipes, start with [this article](/v1/docs/what-is-a-recipe). Note the following:

- The `key` should be constructed as follows: `Quote.&lt;instrumentIdType&gt;.&lt;instrumentId&gt;`.
- The `dataScope` must match the quote scope into which fixings were loaded.
- The other fields must match their respective quote fields exactly (values are case-sensitive).

### Registering the recipe with portfolios

You must register the recipe with every portfolio in which you intend to hold an `InterestRateSwap`. [See how to do this](/v1/docs/setting-a-portfolio-recipe).

You can use the same recipe for valuation operations if you wish.

## Booking a transaction to establish a position

Once an `InterestRateSwap` instrument is mastered, you can [book a transaction](/v1/docs/how-do-i-create-or-update-a-transaction) in a particular portfolio, for example using the [BatchUpsertTransactions](https://www.lusid.com/docs/api/lusid/endpoints/transaction-portfolios/BatchUpsertTransactions/) API:

```json
curl -X POST 'https://mydomain.lusid.com/api/api/transactionportfolios/MyPortfolioScope/MyPortfolioCode/transactions/$batchUpsert?successMode=Partial&preserveProperties=true'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer myAPIAccessToken'
  -d '{
  "transactionRequest-1": {
    "transactionId": "Txn01",
    "type": "EnterIRS",
    "instrumentIdentifiers": {"Instrument/default/ClientInternal": "IRS-15Jan30"},
    "transactionDate": "2025-01-15T00:00:00.0000000+00:00",
    "settlementDate": "2025-01-15T00:00:00.0000000+00:00",
    "units": 1,
    "transactionPrice": {
      "price": 0,
      "type": "Price"
    },
    "totalConsideration": {
      "amount": 0,
      "currency": "GBP"
    }
  }
}'
```

Note the following about this example, which demonstrates an OTC contract with no broker or exchange fees:

- The `type` field invokes a custom `EnterIRS` [transaction type](/v1/docs/what-is-a-transaction-type) to enter into a position without a cost (see below).
- The `transactionDate` and `settlementDate` match the `startDate` in the instrument definition, but can be before or after if required.
- `units` is `1` because `notional` is recorded in the instrument definition. You can reverse this by setting `notional` to `1` and recording the number of units in the transaction if you wish.
- The `transactionPrice.price` and `totalConsideration.amount` (cost) are set to `0` to infer that this contract has no current market value, but you can specify a clean or dirty price if buying or selling a live swap.

> **Note**: This example assumes the transaction, settlement and portfolio currencies are all the same. If not, you can [specify exchange rates](/v1/docs/transactions-and-exchange-rates).

We might create a custom `EnterIRS` transaction type as follows:

```json
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/EnterIRS?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "EnterIRS",
      "description": "Transaction type for entering into an IRS",
      "transactionClass": "Basic",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Increase units of security",
      "movementTypes": "StockMovement",
      "side": "Side1",
      "direction": 1
    }
  ]
}'
```

### Confirming positions

We can [generate a holdings report](/v1/docs/how-do-i-generate-a-holdings-report) on the transaction date to see that we hold one unit at no cost:

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-2326X3T8.png)

### Auditing LUSID’s automatically-generated transactions

We can examine the [output transaction](/v1/docs/input-and-output-transactions) that generates this holding:

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-6TECBOVU.png)

## Valuing your position

To value a position in an `InterestRateSwap` in a portfolio, work through our [valuation checklist](/v1/docs/valuation-checklist).

> **Note**: You can override LUSID’s calculation of cashflows or PV by loading pre-determined structured result data. For more information, see [this article](/v1/docs/what-is-structured-result-data) and [this Jupyter Notebook](https://github.com/finbourne/finbourne-notebooks/blob/main/V1/features/instruments/Interest%20Rate%20Swap.ipynb).

| Available pricing model ([see how to change](/v1/docs/recipes-changing-the-default-pricing-models-for-instrument-types)) | Market data required | Notes |
| --- | --- | --- |
| `SimpleStatic` (default) | 1. Fixings for floating leg in Quote Store 2. Market price for instrument in Quote Store | Cannot split by legs. |
| `Discounting` | 1. Fixings for floating leg in Quote Store 2. Discount curve in CMD Store 3. Interest rate projection curve in CMD Store | Can split by legs if `produceSeparateResultForLinearOtcLegs=True` in recipe. For a demonstration of loading the reqiuired complex market data, see [this Jupyter Notebook](https://github.com/finbourne/finbourne-notebooks/blob/main/V1/features/instruments/Interest%20Rate%20Swap.ipynb). |
| `ConstantTimeValueOfMoney` | Fixings for floating leg in Quote Store | Note PV is simply a sum of projected cashflows. Can split by legs if `produceSeparateResultForLinearOtcLegs=True` in recipe. |

For example, to value the portfolio above on 13 May 2026 using `SimpleStatic`:

1. Make sure fixings for a floating leg are [loaded into the Quote Store](/v1/docs/modelling-interest-rate-swaps-in-lusid#providing-interest-rate-fixings).
2. [Load market prices](/v1/docs/how-do-i-upload-a-market-price-or-fx-spot-rate-to-the-quote-store) for the valuation date as either `CleanPrice` or `DirtyPrice` into a particular quote scope in the Quote Store, for example:

```json
curl -X POST "https://<your-domain>.lusid.com/api/api/quotes/MyIRSPrices"
  -H "Authorization: Bearer <your-API-access-token>"
  -H "Content-Type: application/json-patch+json"
  -d '{
    "Quote-0001": {
      "quoteId": {
        "quoteSeriesId": {
          "provider": "Lusid",
          "instrumentIdType": "ClientInternal",
          "instrumentId": "IRS-15Jan30",
          "quoteType": "DirtyPrice",
          "field": "mid"
        },
        "effectiveAt": "2026-05-13"
      },
      "metricValue": {
        "value": 0.09787, "unit": "USD"
      }
    },
  }'
```
3. Make sure the recipe you use has a [market data rule](/v1/docs/recipes-locating-market-data) able to locate these market prices, for example:

```json
"market": {
  "marketRules": [
    {
      "key": "Quote.ClientInternal.*",
      "dataScope": "MyIRSPrices",
      "supplier": "Lusid",
      "quoteType": "DirtyPrice",
      "field": "mid"
    },
    ...
  ]
},
```
4. [Generate a valuation report](/v1/docs/how-do-i-perform-a-valuation) with appropriate metrics, for example: ![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-YJEZ57T6.png)

## Handling the lifecycle of the instrument

An `InterestRateSwap` is tightly integrated into LUSID’s [instrument event framework](/v1/docs/understanding-instrument-lifecycle-events-emitted-by-lusid). To enable this for your domain, you must:

1. Register a recipe with every portfolio holding an `InterestRateSwap`.
2. Create transaction types to determine the economic impact of the transactions automatically generated by `InterestRateSwap` events.

For much more information, see how to [handle instrument events for interest rate swaps](/v1/docs/handling-instrument-events-for-interest-rate-swaps).

| **Instrument event** | Event emission criteria | **If emitted, effect of LUSID default transaction template** |
| --- | --- | --- |
| `SwapCashFlowEvent` | This event is automatically emitted by LUSID for each leg on each payment date to exchange cashflows. Note market data is required for a floating leg. | One transaction for a cash amount is automatically generated for each leg. |
| `SwapPrincipalEvent` | This event is automatically emitted by LUSID for each leg where `notionalExchangeType` is not `None` in the instrument definition, to exchange notionals. | One transaction for a cash amount is automatically generated for each leg. |
| `MaturityEvent` | This event is automatically emitted by LUSID on the maturity date to zero the holding. | One transaction for all units at zero cost is automatically generated. |

## Appendix: Using the LUSID web app to simplify setup

A dashboard is available in the LUSID web app to both book a trade and simultaneously master an `InterestRateSwap` instrument, which may be a simpler user experience. To enable this:

1. Contact [Technical Support](/v1/docs/how-do-i-use-the-support-centre) for the required license.
2. In the transaction type you use to [enter into a swap](/v1/docs/modelling-interest-rate-swaps-in-lusid#booking-a-transaction-to-establish-a-position), add the `TransactionConfiguration/default/UIClass` system property and set the value to `PMS - IRS`.
3. Navigate to **Portfolio Management > Transactions**
4. Click the **Create transaction** button and open the **IRS** tab.
