---
title: "Modelling credit default swap indexes (CDX) in LUSID"
slug: "modelling-cds-index-instruments-in-lusid"
updated: 2026-02-16T11:08:17Z
published: 2026-02-16T11:08:17Z
canonical: "support.lusid.com/modelling-cds-index-instruments-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 credit default swap indexes (CDX) in LUSID

You can model an exchange-traded credit default swap index (CDX) contract as an instrument of type `CdsIndex` in LUSID. [See all supported instruments](/v1/docs/what-instruments-does-lusid-support).

> **Note**: Most of the information in this article also applies to a single name CDS contract, except the LUSID instrument type is `CreditDefaultSwap`.

## Mastering an instrument

There are [numerous tools](/v1/docs/how-do-i-master-an-instrument) you can use to master a `CdsIndex` 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`.

Fields in the economic `definition` object are specific to `CdsIndex`. For more information on these fields, select **CdsIndex** from the **definition** dropdown in the [UpsertInstruments](https://www.lusid.com/docs/api/lusid/endpoints/instruments/UpsertInstruments) API reference:

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

In this tutorial, we’ll master a [Markit-iTraxx-Crossover](https://www.ice.com/products/28687613/Markit-iTraxx-Crossover) contract by calling the `UpsertInstruments` API as follows:

```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 '{
  "request_id_1": {
    "name": "Markit iTraxx Crossover Series 41 5Y",
    "identifiers": {
      "ClientInternal": {"value": "MarkitiTraxxCrossoverSeries415Y"}
    },
    "definition": {
      "instrumentType": "CdsIndex",
      "identifiers": {},
      "startDate": "2024-03-20T00:00:00.0000000+00:00",
      "maturityDate": "2029-06-20T00:00:00.0000000+00:00",
      "notional": 1,
      "couponRate": 0.05,
      "flowConventions": {
        "currency": "EUR",
        "paymentFrequency": "6M",
        "dayCountConvention": "Actual360",
        "rollConvention": "20",
        "businessDayConvention": "F",
        "paymentCalendars": ["EUR"]
      }
    }
  }
}'
```

Note the following:

- We’ve chosen to master this instrument in a [custom instrument scope](/v1/docs/understanding-instrument-scopes) (specified in the URL).
- The `identifiers` field uniquely identifies the instrument using a `ClientInternal` [identifier](/v1/docs/what-are-unique-and-non-unique-identifiers).
- In the economic `definition` object:
  - The `instrumentType` must be `CdsIndex`.
  - The nested `identifiers` object should be empty: `{}`.
  - The `notional` should be unitised (set to `1`) and the amount bought or sold specified on the transaction.
  - The `couponRate` representing the premium payment should be expressed as a decimal rather than a percentage, so:
    - 5% should have a `couponRate` of `0.05`
    - 1% should have a `couponRate` of `0.01`, and so on.
  - The `flowConventions` field must reference a `CdsFlowConventions` object storing all the information necessary to determine [premium payment periods and dates](/v1/docs/flow-conventions-and-index-conventions):
    - The `paymentFrequency` field can be any [tenor](/v1/docs/specifying-tenors-in-lusid), in this case `6M` to signify twice yearly. [Supported day count conventions](/v1/docs/day-count-conventions-supported-by-lusid).
    - The `rollConvention` field can specify a fixed day (for example `IMM` or `EndOfMonth`) or alternatively a number representing a day of the month. We also recommend setting a `businessDayConvention` to determine what should happen if this is not a good business day. [More information on roll and business day conventions](/v1/docs/roll-conventions-and-business-day-conventions). Note good business days in LUSID are determined by [holiday calendars](/v1/docs/using-calendars-in-lusid).
    - The `settleDays` and `resetDays` fields are optional. The `scope` and `code` fields can be ignored unless you are loading a CDS flow convention from a library.
  - The `basket` field is now optional and there is no need to identity the underlying CDS trades in the index.

> **Note**: LUSID implicitly creates [protection and payment legs](/v1/docs/how-does-lusid-handle-instrument-legs) for a CDX instrument but note the recommended `CdsLookupPricer` pricing model does not yet value legs separately.

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.
- 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": {
    "request_id_1": {
      "scope": "MyCustomInstrScope",
      "lusidInstrumentId": "LUID_00003EDB",
      "name": "Markit iTraxx Crossover Series 41 5Y",
      "identifiers": {
        "LusidInstrumentId": "LUID_00003EDB",
        "ClientInternal": "MarkitiTraxxCrossoverSeries415Y"
      },
      "properties": [],
      "instrumentDefinition": {
        "startDate": "2024-03-20T00:00:00.0000000+00:00",
        "maturityDate": "2029-06-20T00:00:00.0000000+00:00",
        "flowConventions": {
          "rollFrequency": "6M",
          "currency": "EUR",
          "paymentFrequency": "6M",
          "dayCountConvention": "Actual360",
          "rollConvention": "20",
          "paymentCalendars": ["EUR"],
          "resetCalendars": [],
          "settleDays": 0,
          "resetDays": 0,
          "businessDayConvention": "F"
        },
        "couponRate": 0.05,
        "identifiers": {},
        "basket": {
          "basketName": {
            "index": "unknown",
            "name": "unknown",
            "region": "unknown",
            "seriesId": 10000000
          },
          "basketType": "Credits",
          "weightedInstruments": {
            "instruments": []
          },
          "instrumentType": "Basket"
        },
        "notional": 1,
        "additionalPayments": [],
        "instrumentType": "CdsIndex"
      },
      "state": "Active",
      "assetClass": "Credit",
      "domCcy": "EUR",
      "relationships": []
    }
  }
  ...
}
```

## Booking a transaction to establish a position

Once an instrument is mastered, we can [book a transaction](/v1/docs/how-do-i-create-or-update-a-transaction) to record the acquisition of a quantity in a suitable portfolio, for example by calling the `BatchUpsertTransactions` API as follows:

```json
curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/FixedIncome/EMEA/transactions/$batchUpsert?successMode=Partial&preserveProperties=true'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "transactionRequest-1": {
    "transactionId": "cdx_purchase_001",
    "type": "BuyProtection",
    "instrumentIdentifiers": {"Instrument/default/ClientInternal": "MarkitiTraxxCrossoverSeries415Y"},
    "transactionDate": "2024-09-20T00:00:00.0000000+00:00",
    "settlementDate": "2024-09-25T00:00:00.0000000+00:00",
    "units": 100000,
    "transactionPrice": {
      "price": 102,
      "type": "Price"
    },
    "totalConsideration": {
      "currency": "EUR",
      "amount": -2000
    },
    "properties": {
      "Transaction/default/BondInterest": {
        "key": "Transaction/default/BondInterest",
        "value": {
          "metricValue": {
            "value": -1270.00,
            "unit": "EUR"
          }
        }
      }
    }
  }
}'
```

Note the following:

- The `instrumentIdentifiers` field uses the `ClientInternal` identifier to resolve the transaction to the correct CDX instrument (but it could use the LUID).
- The `type` field invokes a custom `BuyProtection` [transaction type](/v1/docs/what-is-a-transaction-type) to confer a particular economic impact on the transaction (see below).
- The `units` field specifies the purchase amount, in this case `100000`.
- The `transactionPrice` object records the market price as a par-like Markit price of `102`. LUSID converts this to a rate using `(100 - price) / 100`, so `(100 - 102) / 100 = -0.02`. Note you can enter the rate explicitly if you want but the `transactionPrice.type` should still be `Price`. Note also:
  - The impact of a transaction for an above-par price such as `102` is to both receive cash *and* accrued interest (that is, a rebate on the premium for purchasing part-way through a period).
  - The impact of a transaction for a below par price such as `98` (which as a rate is `(100 - 98) / 100 = 0.02`) is to *pay* cash but receive accrued interest.
- The `totalConsideration` object:
  - Sets the settlement currency to `EUR`.
  - Records a total consideration for the transaction of `100000 * ((100 - 102) / 100) = -2000`. LUSID uses this amount in the calculation of [holding cost](/v1/docs/how-is-cost-calculated-in-lusid).
- Currently, we must calculate the accrued interest manually and record a negative amount using the `Transaction/default/BondInterest` system property, in this case `-1270`. In future, LUSID may automate this calculation.

> **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 can call the [SetTransactionType](https://www.lusid.com/docs/api#operation/SetTransactionType) API to create a `BuyProtection` transaction type as follows:

```json
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/BuyProtection?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "BuyProtection",
      "description": "Transaction type for CDX purchases",
      "transactionClass": "Basic",
      "transactionRoles": "Longer",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Increase units of security",
      "movementTypes": "StockMovement",
      "side": "Protection",
      "direction": 1
    },
    {
      "name": "Decrease cash balance",
      "movementTypes": "CashCommitment",
      "side": "Side2",
      "direction": -1
    },
    {
      "name": "Report as a flow of value out of the security",
      "movementTypes": "Carry",
      "side": "Side1",
      "direction": 1
    }
  ]
}'
```

Note the following:

- The `StockMovement` uses a `Protection` custom side (see below) to establish a holding in the CDX instrument with a number of units at a particular cost.
- The `CashCommitment` movement uses the [built-in](https://support.lusid.com/docs/what-built-in-transaction-types-and-sides-are-provided-with-lusid#builtin-sides) `Side2` to decrease a currency holding by the total consideration.
- The `Carry` movement uses the built-in `Side1` to record a flow of value out of the CDX instrument in an [A2B report](/v1/docs/creating-an-a2b-report-to-understand-how-valuations-change-over-time).

We can call the [SetSideDefinition](https://www.lusid.com/docs/api/lusid/endpoints/transaction-configuration/SetSideDefinition/) API to create a `Protection` custom side as follows:

```json
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/sides/Protection?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "security": "Txn:LusidInstrumentId",
  "currency": "Txn:TradeCurrency",
  "rate": "Txn:TradeToPortfolioRate",
  "units": "Txn:Units",
  "amount": "BaseOnSeparateBondInterest"
}'
```

This is the same as the [built-in](https://support.lusid.com/docs/what-built-in-transaction-types-and-sides-are-provided-with-lusid#builtin-sides) `Side1` except the `amount` field is set to `BaseOnSeparateBondInterest` instead of `Txn:TradeAmount`.

Note this means that LUSID calculates holding cost as total consideration minus `Transaction/default/BondInterest`. If this latter amount is signed negative then LUSID *decreases* the cost of the CDX instrument, to reflect the recipt of accrued interest.

### Confirming positions on the settlement date

We can navigate to **Portfolio Management > Holdings** in the LUSID web app to call the [GetHoldings](https://www.lusid.com/docs/api/lusid/endpoints/transaction-portfolios/GetHoldings/) API on the settlement date and, since we bought for an above-par price of 102, see that we have:

- 100,000 units of the CDX instrument holding with a negative cost calculated as total consideration minus accrued interest: `-2000 - (-1270) = -730`
- A EUR currency holding with a positive amount reflecting cash received (because we bought above par):

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

If instead we had bought at a below-par price of 98, we would have:

- 100,000 units of the CDX instrument holding with a positive cost: `2000 - (-1270) = 3270`
- A EUR currency holding with a negative amount reflecting cash paid (because we bought below par):

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

### Auditing LUSID’s calculations of transaction amounts

We can navigate to **Portfolio Management > Transactions** in **Output** mode to call the [BuildTransactions](https://www.lusid.com/docs/api/lusid/endpoints/transaction-portfolios/BuildTransactions/) API with a suitable window to examine the output transaction that generated the above-par holdings, for example:

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

## Valuing your position

To value your position, work through our [valuation checklist](/v1/docs/valuation-checklist).

The following [pricing models](/v1/docs/what-pricing-models-can-i-use-in-my-valuation) are available for instruments of type `CdsIndex`. Note your choice impacts the market data required and the composition of your recipe.

| **Pricing model** | **Notes** |
| --- | --- |
| `CdsLookupPricer` | **Recommended**. This pricing model extends `SimpleStatic` to consume either a price or a rate, and also projects cashflows. You can load a quotes as either: - A par-like Markit price of (for example) `102` or `98` using a `quoteType` of `Price`. LUSID calculates clean PV as `(units * notional * ((100 - price) / 100)) / scale factor`. - As a rate of (for example) `-0.02` or `0.02` using a `quoteType` of `Rate`. LUSID calculates clean PV as `(units * notional * rate) / scale factor`. In either case, LUSID calculates PV as `clean PV + accrued interest`. |
| `SimpleStatic` | This is currently the default. We recommend changing it to `CdsLookupPricer` in your recipe. [See how to do this](/v1/docs/recipes-changing-the-default-pricing-models-for-instrument-types). |

For example, to value our holding using `CdsLookupPricer` on 1 October 2024 using a par-like Markit price:

1. [Load a quote](/v1/docs/how-do-i-upload-a-market-price-or-fx-spot-rate-to-the-quote-store) into a particular scope (specified in the URL) with `effectiveAt` as the valuation date and a `scaleFactor` of `1`:

```json
curl -X POST 'https://mydomain.lusid.com/api/api/quotes/MyCdxQuotes'
  -H 'Authorization: Bearer myAPIAccessToken'
  -H 'Content-Type: application/json-patch+json'
  -d '{
    "Quote-0001": {
      "quoteId": {
        "quoteSeriesId": {
          "provider": "Lusid",
          "instrumentIdType": "ClientInternal",
          "instrumentId": "MarkitiTraxxCrossoverSeries415Y",
          "quoteType": "Price",
          "field": "mid"
        },
        "effectiveAt": "2024-10-01T00:00:00Z"
      },
      "metricValue": {"value": 104, "unit": "EUR"},
      "scaleFactor": 1
    }
  }'
```
2. [Create a recipe](/v1/docs/how-do-i-create-or-generate-a-recipe) to locate this market data and change the pricing model, for example:

```json
curl -X POST 'https://mydomain.lusid.com/api/api/recipes'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer myAPIAccessToken'
  -d '{
  "configurationRecipe": {
    "scope": "MyRecipes",
    "code": "MyBasicRecipe",
    "market": {
      "marketRules": [
        {
          "key": "Quote.ClientInternal.*",
          "dataScope": "MyCdxQuotes",
          "supplier": "Lusid",
          "quoteType": "Price",
          "field": "mid"
        }
      ]
    },
    "pricing": {
      "modelRules": [
        {
          "instrumentType": "CdsIndex",
          "modelName": "CdsLookupPricer"
        }
      ]
    }
  }
}'
```
3. [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(673).png)

## Assessing risk

For more on how LUSID calculates exposure, see [this article](/v1/docs/how-does-lusid-calculate-exposure).

LUSID supports both analytic and bump and valuation mechanisms for assessing risk; [contact Technical Support](https://www.finbourne.com/contact) if you need more information.

## Monitoring the lifecycle of the instrument

A `CdsIndex` ‘expires’ on the maturity date specified in the instrument economic definition.

> **Note**: An instrument in LUSID is still available post-expiry, although the valuation is zero. If you set your holding to zero it no longer appears in reports unless you are deliberately backdating.

### Handling automatic lifecycle events

LUSID is transitioning to a system where it automatically emits [lifecycle events for supported instruments](/v1/docs/understanding-instrument-lifecycle-events-emitted-by-lusid). We provide *default transaction templates* that you can use as-is to automatically generate transactions in portfolios with holdings, and recommendations for *transaction types* that deliver appropriate economic impacts for those generated transactions.

The following events are available for `CdsIndex`:

| **Instrument event type** | Event emission criteria | **If emitted, default transaction template generates…** | **Recommendations for transaction types** |
| --- | --- | --- | --- |
| `CreditPremiumCashFlowEvent` | This event is automatically emitted by LUSID each time a premium is due. | A transaction for the premium payment amount. | [See this tutorial](/v1/docs/handling-premium-and-credit-events-for-cdx-instruments) |
| `ProtectionPayoutCashFlowEvent` | This event is **not automatically emitted** by LUSID. It can be triggered by manually loading a `CdxCreditEvent` into a suitable corporate action source. | A transaction for the protection payout amount. |
| `MaturityEvent` | This event is automatically emitted by LUSID on the maturity date of the instrument. | A transaction for all the units in the holding at a cost of zero. |

### Manually loading settlement transactions

If you do not want to turn on automatic instrument lifecycle events you can continue to monitor upcoming cashflows using **Portfolio Management > CashLadder** in the LUSID web app, or by calling the [GetPortfolioCashLadder](https://www.lusid.com/docs/api/lusid/endpoints/transaction-portfolios/GetPortfolioCashLadder) API directly.

You can call the [GetUpsertablePortfolioCashFlows](https://www.lusid.com/docs/api/lusid/endpoints/transaction-portfolios/GetUpsertablePortfolioCashFlows) API to return imminent cashflows as upsertable DTOs ready to manually load into LUSID as input transactions.
