--- 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://.lusid.com/api/api/transactionconfiguration/types/default/BondCoupon?scope=default'   -H 'Content-Type: application/json-patch+json'   -H 'Authorization: Bearer '   -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://.lusid.com/api/api/transactionconfiguration/types/default/BondPrincipal?scope=default'  -H 'Content-Type: application/json-patch+json'  -H 'Authorization: Bearer '  -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://.lusid.com/api/api/transactionconfiguration/types/default/Maturity?scope=default'  -H 'Content-Type: application/json-patch+json'  -H 'Authorization: Bearer '  -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?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A28Z&se=2026-11-09T07%3A00%3A28Z&sr=c&sp=r&sig=EJqZELfy0pN5F%2BoeS8%2B2RXMFQadMvEI%2FXaL0h5mK%2B0M%3D) 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?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A28Z&se=2026-11-09T07%3A00%3A28Z&sr=c&sp=r&sig=EJqZELfy0pN5F%2BoeS8%2B2RXMFQadMvEI%2FXaL0h5mK%2B0M%3D) ### 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?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A28Z&se=2026-11-09T07%3A00%3A28Z&sr=c&sp=r&sig=EJqZELfy0pN5F%2BoeS8%2B2RXMFQadMvEI%2FXaL0h5mK%2B0M%3D) 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?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A28Z&se=2026-11-09T07%3A00%3A28Z&sr=c&sp=r&sig=EJqZELfy0pN5F%2BoeS8%2B2RXMFQadMvEI%2FXaL0h5mK%2B0M%3D) ### 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?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A28Z&se=2026-11-09T07%3A00%3A28Z&sr=c&sp=r&sig=EJqZELfy0pN5F%2BoeS8%2B2RXMFQadMvEI%2FXaL0h5mK%2B0M%3D) 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?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A28Z&se=2026-11-09T07%3A00%3A28Z&sr=c&sp=r&sig=EJqZELfy0pN5F%2BoeS8%2B2RXMFQadMvEI%2FXaL0h5mK%2B0M%3D)