You can model a credit default swap index (CDX) contract as an instrument of type CdsIndex in LUSID. See how to do this.
LUSID emits the following instrument lifecycle events for a CdsIndex, which you can handle to reduce workload and improve efficiency:
CreditPremiumCashFlowEvent. This event is automatically emitted by LUSID each time a premium payment is due. More information.ProtectionPayoutCashFlowEvent. This event is not automatically emitted by LUSID, but can be manually triggered if you are informed that a credit event has occurred. More information.MaturityEvent. This event is automatically emitted by LUSID on the maturity date in the instrument definition. More information.
Note: The information in this article also applies to a single name CDS contract mastered as an instrument of type
CreditDefaultSwap.
Mastering an instrument and establishing a position in a portfolio
Imagine we have a Markit-iTraxx-Crossover contract modelled as a CdsIndex with the following economic definition:
"definition": {
"instrumentType": "CdsIndex",
"startDate": "2024-03-20T00:00:00.0000000+00:00",
"maturityDate": "2029-06-20T00:00:00.0000000+00:00",
"notional": 1,
"couponRate": 0.05,
"identifiers": {},
"flowConventions": {
"currency": "EUR",
"paymentFrequency": "6M",
"dayCountConvention": "Actual360",
"rollConvention": "20",
"businessDayConvention": "F",
"paymentCalendars": ["EUR"]
}
}For much more information on modelling instruments of type CdsIndex, see this article. Note with regard to instrument events:
The
maturityDateof 20 June 2029 andpaymentFrequencyof6Mcombine to mean premium payments are due on 20 June and 20 December each year.The
rollConventionis20, which means premium payments are taken on the 20th day of the month.The
businessDayConventionisF, so the premium payment is taken on the following day if the 20th is not a good business day.The
paymentCalendarsarray specifies that good business days are determined by theEURCopp Clark holiday calendar.
We can now establish a position by booking a transaction in this instrument in a suitable portfolio, in this case trading on 20 September 2024 and settling 5 days later:
{
"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": -0.02,
"type": "Price"
},
"totalConsideration": {
"currency": "EUR",
"amount": -2000
},
"properties": {
"Transaction/default/BondInterest": {
"key": "Transaction/default/BondInterest",
"value": {
"metricValue": {
"value": -1270.00,
"unit": "EUR"
}
}
}
}
}For much more information on booking transactions in CdsIndex instruments, including details of a BuyProtection transaction type, how to record accrued interest using the Transaction/default/BondInterest system property, specifying prices and total consideration, and how LUSID calculates holding cost, see this article.
Handling premium payments
LUSID automatically emits a CreditPremiumCashFlowEvent each time a premium payment is due. You should handle this event to reduce an appropriate cash balance in a portfolio by the premium amount.
Examining the default transaction template for CreditPremiumCashFlowEvent
LUSID provides a default transaction template for every type of event. In this tutorial we’ll use the default template for CreditPremiumCashFlowEvent, but note you can create a custom transaction template to configure the process if you wish.
We can call the GetTransactionTemplate API to examine this default template, which at the time of writing is as follows:
{
"instrumentType": "CdsIndex",
"instrumentEventType": "CreditPremiumCashFlowEvent",
"description": "LUSID default template for automatically generated transactions in respect of CreditDefaultSwapIndex Cashflow instrument events.",
"scope": "default",
"componentTransactions": [
{
"displayName": "Credit Premium",
"transactionFieldMap": {
"transactionId": "{{instrumentEventId}}-{{holdingId}}",
"type": "CreditPremiumCashFlow",
"source": "default",
"instrument": "{{instrument}}",
"transactionDate": "{{CreditPremiumCashFlowEvent.exDate}}",
"settlementDate": "{{CreditPremiumCashFlowEvent.paymentDate}}",
"units": "{{eligibleBalance}}",
"transactionPrice": {
"price": "{{CreditPremiumCashFlowEvent.cashFlowPerUnit}}",
"type": "CashFlowPerUnit"
},
"transactionCurrency": "{{CreditPremiumCashFlowEvent.currency}}",
"exchangeRate": "1",
"totalConsideration": {
"currency": "{{CreditPremiumCashFlowEvent.currency}}",
"amount": "{{CreditPremiumCashFlowEvent.cashFlowAmount}}"
}
},
"transactionPropertyMap": []
}
],
...
}Note the following:
This template handles instrument events of type
CreditPremiumCashFlowEventemitted by instruments of typeCdsIndex.It is domiciled in the
default(that is, system) transaction template scope.It contains instructions for automatically generating a single output transaction in every portfolio with a holding in the CDX instrument.
The generated transaction belongs to a
CreditPremiumCashFlowtransaction type grouped in thedefaulttransaction type source.
Note: This template does not add the
Transaction/default/TradeToPortfolioRatesystem property to the generated transaction. If the portfolio base currency is different to the transaction currency we recommend specifying theTxn:TradeToPortfolioRatecalculation in the transaction type to look up a spot rate dynamically in the LUSID Quote Store. See how to do this.
Creating a suitable CreditPremiumCashFlow transaction type
The default transaction template mandates a CreditPremiumCashFlow transaction type grouped in the default transaction type source. We must create this transaction type if it does not exist.
Note: Transaction types are grouped in sources and reside in scopes. For more information on the difference, see this article.
We can call the SetTransactionType API as follows:
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/CreditPremiumCashFlow?scope=default'
-H 'Content-Type: application/json-patch+json'
-H 'Authorization: Bearer <your-API-access-token>'
-d '{
"aliases": [
{
"type": "CreditPremiumCashFlow",
"description": "Transaction type for credit premium cash flow event",
"transactionClass": "Basic",
"transactionRoles": "AllRoles",
"isDefault": false
}
],
"movements": [
{
"name": "Premium payments",
"movementTypes": "CashCommitment",
"side": "Side2",
"direction": 1,
"mappings": [
{
"propertyKey": "Transaction/SHKs/CdxPremiumPayments",
"setTo": "Premium payments"
}
],
},
{
"name": "Record as a flow of value out of the security",
"movementTypes": "Carry",
"side": "Side1",
"direction": 1,
}
]
}'Note the following:
The transaction type alias is
CreditPremiumCashFlow, to comply with the default transaction template.The transaction type source is
default(specified in the URL), to comply with the default transaction template.You can design a transaction type to have any economic impact you like. This recommendation has:
A
CashCommitmentmovement that increases a currency holding by the premium amount. Note the direction is positive but premium payment amounts are signed negative. This is mapped to a sub-holding key (SHK) to report this currency holding separately.A
Carrymovement reporting a flow of value out of the security in an A2B report.
Handling credit events
You can trigger LUSID to emit a ProtectionPayoutCashFlowEvent if you are notified that a credit event has occured (note this event is not emitted automatically). You can handle this event to increase an appropriate cash balance in a portfolio by the protection payout amount.
To do this:
If a portfolio does not already have a corporate action source (CAS), create one and subscribe the portfolio to it. See how to do this.
Create a transaction type to determine the economic impact of protection payout transactions automatically generated by
ProtectionPayoutCashFlowEvent. More information.Load a
CdxCreditEventinto the CAS to triggerProtectionPayoutCashFlowEventon a particular date. More information.
Examining the default transaction template for ProtectionPayoutCashFlowEvent
We can call the GetTransactionTemplate API to examine the default transaction template for ProtectionPayoutCashFlowEvent, which at the time of writing is as follows:
{
"instrumentType": "CdsIndex",
"instrumentEventType": "ProtectionPayoutCashFlowEvent",
"description": "LUSID default template for automatically generated transactions in respect of CDX Protection Payout Cashflow instrument events.",
"scope": "default",
"componentTransactions": [
{
"displayName": "Protection Payout",
"transactionFieldMap": {
"transactionId": "{{instrumentEventId}}-{{holdingId}}",
"type": "ProtectionPayoutCashFlow",
"source": "default",
"instrument": "{{instrument}}",
"transactionDate": "{{ProtectionPayoutCashFlowEvent.exDate}}",
"settlementDate": "{{ProtectionPayoutCashFlowEvent.paymentDate}}",
"units": "{{eligibleBalance}}",
"transactionPrice": {
"price": "{{ProtectionPayoutCashFlowEvent.cashFlowPerUnit}}",
"type": "CashFlowPerUnit"
},
"transactionCurrency": "{{ProtectionPayoutCashFlowEvent.currency}}",
"exchangeRate": "1",
"totalConsideration": {
"currency": "{{ProtectionPayoutCashFlowEvent.currency}}",
"amount": "{{ProtectionPayoutCashFlowEvent.cashFlowAmount}}"
}
},
"transactionPropertyMap": []
}
],
...
}Note the following:
This template handles instrument events of type
ProtectionPayoutCashFlowEventemitted by instruments of typeCdsIndex.It is domiciled in the
default(that is, system) transaction template scope.It contains instructions for automatically generating a single output transaction in every portfolio with a holding in the CDX instrument.
The generated transaction belongs to a
ProtectionPayoutCashFlowtransaction type grouped in thedefaulttransaction type source.
Creating a suitable ProtectionPayoutCashFlow transaction type
The default transaction template mandates a ProtectionPayoutCashFlow transaction type grouped in the default transaction type source. We must create this transaction type if it does not exist, for example by calling the SetTransactionType API as follows:
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/ProtectionPayoutCashFlow?scope=default'
-H 'Content-Type: application/json-patch+json'
-H 'Authorization: Bearer <your-API-access-token>'
-d '{
"aliases": [
{
"type": "ProtectionPayoutCashFlow",
"description": "Transaction type for protection payout cash flow event",
"transactionClass": "Basic",
"transactionRoles": "AllRoles",
"isDefault": false
}
],
"movements": [
{
"name": "Protection payouts",
"movementTypes": "CashReceivable",
"side": "Side2",
"direction": 1,
"mappings": [
{
"propertyKey": "Transaction/SHKs/CdxProtectionPayouts",
"setTo": "Protection payouts"
}
],
}
]
}'Note the following:
The transaction type alias is
ProtectionPayoutCashFlow, to comply with the default transaction template.The transaction type source is
default(specified in the URL), to comply with the default transaction template.You can design a transaction type to have any economic impact you like. This recommendation has a single
CashReceivablemovement that increases a currency holding by the protection payout amount. This is mapped to a SHK to report this currency holding separately.
Loading a CdxCreditEvent to trigger LUSID to emit ProtectionPayoutCashFlowEvent
We must manually load a CdxCreditEvent into a CAS in order to trigger LUSID to emit a ProtectionPayoutCashFlowEvent on a particular date.
We can call the UpsertInstrumentEvents API and supply the scope and code of the CAS in the URL as follows:
curl -X POST 'https://<your-domain>.lusid.com/api/api/corporateactionsources/my-CAS-scope/my-CAS-code/instrumentevents'
-H 'Content-Type: application/json-patch+json'
-H 'Authorization: Bearer <your-API-access-token>'
-d '[
{
"instrumentEventId": "CdxCreditEvent2025-02-15",
"instrumentIdentifiers": {"Instrument/default/ClientInternal": "MarkitiTraxxCrossoverSeries415Y"},
"description": "Credit event 15 Feb 2025",
"instrumentEvent": {
"instrumentEventType": "CdxCreditEvent",
"effectiveDate": "2025-02-15T00:00:00.0000000+00:00",
"auctionDate": "2025-03-20T00:00:00.0000000+00:00",
"paymentDate": "2025-03-25T00:00:00.0000000+00:00",
"recoveryRate": 0.75,
"constituentWeight": 0.01333,
"constituentReference": "Intram"
}
}
]'Note the following:
The
instrumentEventIdis a free string field that must uniquely identify this corporate action in the corporate action source.The
instrumentIdentifiersfield uses aClientInternalidentifier to resolve to the correct CDX instrument in the LUSID Security Master, but you could specify the LUID.If you do not yet know the
auctionDateit defaults to seven weeks aftereffectiveDate.If you do not yet know the
paymentDatethen the transaction automatically generated byProtectionPayoutCashFlowEventtrades and settles the day afterauctionDate.If you do not yet know the
recoveryRateit defaults to1.The
constituentWeightmust be a number between0and1.The
constituentReferenceis a free string field enabling you to record the defaulting constituent.
Note you can call the UpsertInstrumentEvents API as many times as you like to update the event as information about the auction date, recovery rate and constituent weight becomes available.
Handling instrument maturity
LUSID automatically emits a MaturityEvent on the date specified in the instrument definition. You should handle this event to set your position to zero units, so it drops out of holding and valuation reports.
Examining the default transaction template for MaturityEvent
We can call the GetTransactionTemplate API to examine the default transaction template for MaturityEvent, which at the time of writing is as follows:
{
"instrumentType": "CdsIndex",
"instrumentEventType": "MaturityEvent",
"description": "LUSID default template for automatically generated transactions in respect of instrument maturity events.",
"scope": "default",
"componentTransactions": [
{
"displayName": "Maturity",
"transactionFieldMap": {
"transactionId": "{{instrumentEventId}}-{{holdingId}}",
"type": "Maturity",
"source": "default",
"instrument": "{{instrument}}",
"transactionDate": "{{MaturityEvent.maturityDate}}",
"settlementDate": "{{MaturityEvent.maturityDate}}",
"units": "{{eligibleBalance}}",
"transactionPrice": {
"price": "0",
"type": "Price"
},
"transactionCurrency": "{{holdingCurrency}}",
"exchangeRate": "0",
"totalConsideration": {
"currency": "{{holdingCurrency}}",
"amount": "0"
}
},
"transactionPropertyMap": []
}
],
...
}Note the following:
This template handles instrument events of type
MaturityEventemitted by instruments of typeCdsIndex.It is domiciled in the
default(that is, system) transaction template scope.It contains instructions for automatically generating a single output transaction in every portfolio with a holding in the CDX instrument.
The generated transaction belongs to a
Maturitytransaction type grouped in thedefaulttransaction type source.
Creating a suitable Maturity transaction type
The default transaction template mandates a Maturity transaction type grouped in the default transaction type source. We must create this transaction type if it does not exist, for example by calling the SetTransactionType API as follows:
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/Maturity?scope=default'
-H 'Content-Type: application/json-patch+json'
-H 'Authorization: Bearer <your-API-access-token>'
-d '{
"aliases": [
{
"type": "Maturity",
"description": "Transaction type for instrument maturity event",
"transactionClass": "Basic",
"transactionRoles": "AllRoles",
"isDefault": false
}
],
"movements": [
"name": "Set units to zero",
"movementTypes": "StockMovement",
"side": "Side1",
"direction": -1
]
}'Note the following:
The transaction type alias is
Maturity, to comply with the default transaction template.The transaction type source is
default(specified in the URL), to comply with the default transaction template.You can design a transaction type to have any economic impact you like. This recommendation reduces the number of units to zero.
Examining the impact of instrument lifecycle events on the portfolio
25 September 2024
We can use Portfolio Management > Holdings in the LUSID web app to call the GetHoldings API on the settlement date and see that we have:
100,000 units of the CDX instrument holding with a negative cost of -730 (see this article for the calculation)
A EUR currency holding with a positive amount reflecting cash received (because we purchased above par):
.png?sv=2022-11-02&spr=https&st=2025-10-29T03%3A24%3A56Z&se=2025-10-29T03%3A46%3A56Z&sr=c&sp=r&sig=j5nSW5mLMNlLVwFrDQVRDitDIUI4exLknBdEzAJap0Y%3D)
20 December 2024
If we move the Effective date to the first premium payment date we see that CreditPremiumCashFlowEvent has posted a negative amount to a separate EUR currency holding:
.png?sv=2022-11-02&spr=https&st=2025-10-29T03%3A24%3A56Z&se=2025-10-29T03%3A46%3A56Z&sr=c&sp=r&sig=j5nSW5mLMNlLVwFrDQVRDitDIUI4exLknBdEzAJap0Y%3D)
25 March 2025
If we move the Effective date to the payment date of the credit event we can see that ProtectionPayoutCashFlowEvent has posted a positive amount to a separate EUR currency holding:
.png?sv=2022-11-02&spr=https&st=2025-10-29T03%3A24%3A56Z&se=2025-10-29T03%3A46%3A56Z&sr=c&sp=r&sig=j5nSW5mLMNlLVwFrDQVRDitDIUI4exLknBdEzAJap0Y%3D)
20 June 2029
If we move the Effective date to the maturity date of the instrument we can see that MaturityEvent has removed the CDX instrument position (set units to zero):
.png?sv=2022-11-02&spr=https&st=2025-10-29T03%3A24%3A56Z&se=2025-10-29T03%3A46%3A56Z&sr=c&sp=r&sig=j5nSW5mLMNlLVwFrDQVRDitDIUI4exLknBdEzAJap0Y%3D)
Auditing output transactions generated by instrument events
We can use Portfolio Management > Transactions in Output mode to call the BuildTransactions API with a suitable window to examine the record of output transactions generated over the lifetime of the instrument:
.png?sv=2022-11-02&spr=https&st=2025-10-29T03%3A24%3A56Z&se=2025-10-29T03%3A46%3A56Z&sr=c&sp=r&sig=j5nSW5mLMNlLVwFrDQVRDitDIUI4exLknBdEzAJap0Y%3D)