---
title: "Handling bond coupon, principal and maturity instrument lifecycle events"
slug: "handling-bond-coupon-principal-and-maturity-instrument-lifecycle-events"
updated: 2025-09-26T08:40:54Z
published: 2025-09-26T08:40:54Z
canonical: "support.lusid.com/handling-bond-coupon-principal-and-maturity-instrument-lifecycle-events"
---

> ## 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.

# Handling bond coupon, principal and maturity instrument lifecycle events

You can model a bond as either an instrument of type `Bond`, `ComplexBond` or `InflationLinkedBond` in LUSID. [More information](/v1/docs/modelling-fixed-rate-vanilla-bonds-in-lusid).

LUSID emits the following [instrument lifecycle events](/v1/docs/understanding-instrument-lifecycle-events-emitted-by-lusid) for bonds, which you can handle to reduce workload and improve efficiency:

- `BondCouponEvent`. This event is automatically emitted by LUSID each time a coupon is due. [More information](/v1/docs/handling-bond-coupon-principal-and-maturity-instrument-lifecycle-events#handling-bond-coupons).
- `BondPrincipalEvent`. This event is automatically emitted by LUSID on the maturity date to return the principal. [More information](/v1/docs/handling-bond-coupon-principal-and-maturity-instrument-lifecycle-events#handling-return-of-principal).
- `MaturityEvent`. This event is automatically emitted by LUSID on the maturity date to zero the holding. [More information](/v1/docs/handling-bond-coupon-principal-and-maturity-instrument-lifecycle-events#handling-instrument-maturity).

## Mastering a bond instrument in LUSID and booking trades

Imagine we have a US Treasury bond paying 2.375% annually until 15 August 2026 modelled as a `Bond` as follows:

```json
{
  "instrumentType": "Bond",
  "startDate": "2016-08-15T00:00:00.0000000+00:00",
  "maturityDate": "2026-08-15T00:00:00.0000000+00:00",
  "domCcy": "USD",
  "flowConventions": {
    "currency": "USD",
    "paymentFrequency": "12M",
    "dayCountConvention": "Actual365",
    "rollConvention": "15",
    "businessDayConvention": "Following",
    "paymentCalendars": [],
    "resetCalendars": [],
    "accrualDateAdjustment": "Adjusted",
  },
  "principal": 1,
  "couponRate": 0.02375,
  "exDividendConfiguration": {
    "exDividendDays": 5
  }
}
```

For much more information on modelling instruments as type `Bond`, see [this article](/v1/docs/modelling-fixed-rate-vanilla-bonds-in-lusid#mastering-an-instrument). Note with regard to instrument events:

- The `maturityDate` field is set to the date on which the last coupon is paid and the principal returned: 15 August 2026.
- The `flowConventions.paymentFrequency` field is set to `12M` and `flowConventions.rollConvention` to `15` to determine that coupons are paid annually on 15 August each year.
- The `exDividendConfiguration.exDividendDays` field is set to `5` to specify that the ex-dividend date for the bond is 10 August each year.

For simplicity, business days and holiday calendars are ignored in this tutorial.

We have two historical transactions to [book into a suitable transaction portfolio](/v1/docs/modelling-fixed-rate-vanilla-bonds-in-lusid#booking-a-transaction-to-establish-a-position) for this bond:

- A purchase of 10,000 units on 7 August 2020, settling on 9 August 2020.
- A sale of 5,000 units on 9 August 2023, settling on 11 August 2023.

## Understanding lifecycle events LUSID emits for this bond

Given these transactions, and with respect to a date 'today' of 20 March 2024, LUSID automatically emits the following lifecycle events for this bond:

| **Date** | **Lifecycle event** | **Status with respect to 20 March 2024** | **Eligible balance (known or estimate)** | **Coupon payment (known or estimate)** | **Notes** |
| --- | --- | --- | --- | --- | --- |
| 15 August 2020 | `BondCouponEvent` | Historical | 10000 | $237.50 | We are entitled to this coupon as the **settlement date** of the purchase transaction (9 August 2020) is before the ex-dividend date (10 August 2020). |
| 15 August 2021 |  |
| 15 August 2022 |  |
| 15 August 2023 | We are entitled to the full amount of this coupon as the **settlement date** of the sell transaction (11 August 2023) is after the ex-dividend date (10 August 2023). |
| 15 August 2024 | Future | 5000 | $118.75 |  |
| 15 August 2025 |  |
| 15 August 2026 | Final coupon. |
| 15 August 2026 | `BondPrincipalEvent` | N/A |  |
| 15 August 2026 | `MaturityEvent` | N/A | N/A |  |

## Handling bond coupons

LUSID automatically emits a `BondCouponEvent` each time a coupon is due. You should handle this event to increase an appropriate cash balance in the portfolio by the coupon amount.

### Examining the default transaction template for `BondCouponEvent`

LUSID provides a default transaction template for every type of event. In this tutorial we’ll use the default template for `BondCouponEvent`, but note you can create a [custom transaction template](/v1/docs/how-do-i-create-a-custom-transaction-template) to configure the process if you wish.

We can call the [GetTransactionTemplate](https://www.lusid.com/docs/api#operation/GetTransactionTemplate) API to examine this default template, which at the time of writing is as follows:

```json
{
  "instrumentType": "Bond",
  "instrumentEventType": "BondCouponEvent",
  "description": "LUSID default template for automatically generated transactions in respect of Bond Coupon instrument events.",
  "scope": "default",
  "componentTransactions": [
    {
      "displayName": "Bond Income",
      "transactionFieldMap": {
        "transactionId": "{{instrumentEventId}}-{{holdingId}}",
        "type": "BondCoupon",
        "source": "default",
        "instrument": "{{instrument}}",
        "transactionDate": "{{BondCouponEvent.exDate}}",
        "settlementDate": "{{BondCouponEvent.paymentDate}}",
        "units": "{{eligibleBalance}}",
        "transactionPrice": {
          "price": "{{BondCouponEvent.couponPerUnit}}",
          "type": "CashFlowPerUnit"
        },
        "transactionCurrency": "{{BondCouponEvent.currency}}",
        "exchangeRate": "1",
        "totalConsideration": {
          "currency": "{{BondCouponEvent.currency}}",
          "amount": "{{BondCouponEvent.couponAmount}}"
        }
      },
      "transactionPropertyMap": []
    }
  ],
  ...
}
```

Note the following:

- This template handles instrument events of type `BondCouponEvent` emitted by instruments of type `Bond`.
- It is domiciled in the `default` (that is, system) transaction template `scope`.
- It contains instructions for automatically generating a single [output transaction](/v1/docs/input-and-output-transactions) for each portfolio with a holding in the underlying instrument. Note it is possible for a template to generate multiple output transactions.
- The generated transaction has no `condition`; that is, it is always produced when LUSID emits a bond coupon event.
- The generated transaction belongs to a `BondCoupon` transaction type grouped in the `default` transaction type `source`.
- The `transactionDate` is the ex-dividend date and the `settlementDate` is the payment date.
- The quantity held (`units`) is assessed dynamically per-portfolio and per-coupon.
- The `transactionPrice.price` is the coupon per unit, which is calculated as the annual coupon rate multiplied by the principal and divided by the number of coupons per year.
- The `transactionCurrency` is the currency specified in the bond economic definition, and an `exchangeRate` of `1` means the settlement currency is the same.
- The `totalConsideration.Amount` is the coupon per unit scaled by the quantity held.

> **Note**: This template does not add the `Transaction/default/TradeToPortfolioRate` system property to the generated transaction. If the portfolio base currency is different to the transaction currency we recommend specifying the `Txn:TradeToPortfolioRate` calculation in the transaction type to look up a spot rate dynamically in the LUSID Quote Store. [See how to do this](/v1/docs/transactions-and-exchange-rates#looking-up-exchange-rates-dynamically-using-a-recipe).

### Creating a suitable `BondCoupon` transaction type

The default transaction template mandates a `BondCoupon` 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](/v1/docs/grouping-related-transaction-types-using-scopes-and-sources).

We can call the [SetTransactionType](https://www.lusid.com/docs/api#operation/SetTransactionType) API as follows:

```json
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/BondCoupon?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "BondCoupon",
      "description": "Transaction type for bond coupon event",
      "transactionClass": "Basic",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Add coupon to separate portfolio cash holding",
      "movementTypes": "CashAccrual",
      "side": "Side2",
      "direction": 1,
      "mappings": [
        {
          "propertyKey": "Transaction/SHKs/BondCoupons",
          "setTo": "BondCoupons"
        }
      ]
    },
    {
      "name": "Report the coupon as income",
      "movementTypes": "Carry",
      "side": "Side1",
      "direction": 1
    }
  ]
}'
```

Note the following:

- The transaction type alias is `BondCoupon`, 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](/v1/docs/what-is-a-transaction-type). This one has the following two [movements](/v1/docs/what-movement-types-are-available):
  - The first is a `CashAccrual` movement that maps gross coupon amounts to a `BondCoupons` [sub-holding key](/v1/docs/what-is-a-sub-holding-key-shk) (SHK), to report accrual separately to other cash holdings in the bond currency (USD). You could omit the `mappings` array to add coupons to the main USD cash holding instead. [See how to calculate a net amount after tax](/v1/docs/introduction-to-tax-calculations-in-lusid).
  - The second is a `Carry` movement that reports the coupon as income in an [A2B report](/v1/docs/creating-an-a2b-report-to-understand-how-valuations-change-over-time).

## Handling return of principal

LUSID automatically emits a `BondPrincipalEvent` on the maturity date. You should handle this event to increase an appropriate cash balance in the portfolio by the principal amount.

### Examining the default transaction template for `BondPrincipalEvent`

We can call the [GetTransactionTemplate](https://www.lusid.com/docs/api#operation/GetTransactionTemplate) API to examine the default transaction templates for `BondPrincipalEvent`, which at the time of writing is as follows:

```json
{
  "instrumentType": "Bond",
  "instrumentEventType": "BondPrincipalEvent",
  "description": "LUSID default template for automatically generated transactions in respect of Bond Principal instrument events",
  "scope": "default",
  "componentTransactions": [
    {
      "displayName": "Bond Principal",
      "transactionFieldMap": {
        "transactionId": "{{instrumentEventId}}-{{holdingId}}",
        "type": "BondPrincipal",
        "source": "default",
        "instrument": "{{instrument}}",
        "transactionDate": "{{BondPrincipalEvent.paymentDate}}",
        "settlementDate": "{{BondPrincipalEvent.paymentDate}}",
        "units": "{{eligibleBalance}}",
        "transactionPrice": {
          "price": "{{BondPrincipalEvent.principalPerUnit}}",
          "type": "CashFlowPerUnit"
        },
        "transactionCurrency": "{{BondPrincipalEvent.currency}}",
        "exchangeRate": "1",
        "totalConsideration": {
          "currency": "{{BondPrincipalEvent.currency}}",
          "amount": "{{BondPrincipalEvent.principalAmount}}"
        }
      },
      "transactionPropertyMap": []
    }
  ],
   ...
}
```

Note the following:

- This template handles instrument events of type `BondPrincipalEvent` emitted by instruments of type `Bond`.
- 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 bond instrument.
- The generated transaction belongs to a `BondPrincipal` transaction type grouped in the `default` transaction type source.

### Creating a suitable `BondPrincipal` transaction type

The default transaction template mandates a `BondPrincipal` 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](https://www.lusid.com/docs/api#operation/SetTransactionType) API as follows:

```json
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/BondPrincipal?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "BondPrincipal",
      "description": "Transaction type for bond principal event",
      "transactionClass": "Basic",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Return principal to separate cash balance",
      "movementTypes": "CashReceivable",
      "side": "Side2",
      "direction": 1,
      "mappings": [
        {
          "propertyKey": "Transaction/SHKs/BondPrincipal",
          "setTo": "BondPrincipal"
        }
      ]
    },
    {
      "name": "Set cost to zero without reducing units",
      "movementTypes": "StockMovement",
      "side": "Side1",
      "direction": -1,
      "movementOptions": ["Virtual"]
    }
  ]
}'
```

Note the following:

- The transaction type alias is `BondPrincipal`, to comply with the default transaction template.
- The transaction type source is `default` (specified in the URL), to comply with the default transaction template.
- Our recommended transaction type has two movements:
  - The first is a `CashReceivable` movement that maps the principal amount to a `BondPrincipal` SHK, to report it separately to any other cash balance in the bond currency (USD). You could omit the `mappings` array to add the principal to the main USD cash holding instead.
  - The second is a `StockMovement` that uses the `Virtual` option to set the cost of the holding to zero without actually reducing the units (this is handled by `MaturityEvent`; see below).

## Handling instrument maturity

LUSID automatically emits a `MaturityEvent` on the maturity date. You should handle this event to set your position to zero units in the portfolio, so it drops out of holding and valuation reports.

### Examining the default transaction template for `MaturityEvent`

We can call the [GetTransactionTemplate](https://www.lusid.com/docs/api#operation/GetTransactionTemplate) API to examine the default transaction templates for `MaturityEvent`, which at the time of writing is as follows:

```json
{
  "instrumentType": "Bond",
  "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 `MaturityEvent` emitted by instruments of type `Bond`.
- 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 bond instrument.
- The generated transaction belongs to a `Maturity` transaction type grouped in the `default` transaction 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](https://www.lusid.com/docs/api#operation/SetTransactionType) API as follows:

```json
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.
- Our recommended transaction type has a single `StockMovement` to reduce the number of units to zero (redcuing the cost to zero has already been handled by `BondPrincipalEvent`; see above).

## Examining the impact of instrument lifecycle events on the portfolio

### 9 August 2020

Calling the [GetHoldings](https://www.lusid.com/docs/api#operation/GetHoldings) API before the first coupon payment reveals one holding in the portfolio, for 10,000 settled units of the bond instrument:

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

We can call the [BuildTransactions](https://www.lusid.com/docs/api#operation/BuildTransactions) API with a suitable window to examine the single output transaction that has contributed to this position:

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

### 20 March 2024

Calling the `GetHoldings` API again 'today' reveals we now have two holdings:

- A holding in the bond instrument for 5000 settled units, reflecting the sale of half the units in August 2023.
- A USD cash holding categorized by a `BondCoupons` SHK, representing coupon accrual to date:

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

We can call the `BuildTransactions` API with a suitable window to examine the output transactions that have contributed to these positions:

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

### 1 January 2030

We can fast-forward LUSID and call the `GetHoldings` API again after the bond instrument has matured, at which point (and assuming no other activity) we will have two holdings in our portfolio:

- A USD cash holding categorized by a `BondCoupons` SHK, representing total coupon accrual.
- A USD cash holding categorized by a `BondPrincipal` SHK, representing the return of remaining principal.

Note we no longer have a holding in the bond instrument:

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

We can also fast-forward the `BuildTransactions` API to examine the output transactions that have contributed to these positions:

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