---
title: "Handling exercise and expiry events for option instruments"
slug: "handling-lifecycle-events-for-exchangetradedoption-instruments"
updated: 2026-06-17T13:56:56Z
published: 2026-06-17T13:56:56Z
canonical: "support.lusid.com/handling-lifecycle-events-for-exchangetradedoption-instruments"
---

> ## 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 exercise and expiry events for option instruments

You can model:

- An exchange-traded options contract as an instrument of type `ExchangeTradedOption` in LUSID. [See how to do this](/v1/docs/modelling-exchange-traded-options-in-lusid). Note instrument events are only available for ETOs with an underlying of `Equity` or `Future`. Other underlyings do not support instrument events.
- An OTC equity options contract as an instrument of type `EquityOption`. [See how to do this](/v1/docs/modelling-equity-options-in-lusid).

> **Note**: This tutorial uses an `ExchangeTradedOption` instrument as an example but the information applies equally to `EquityOption`.

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

- `OptionExercisePhysicalEvent`. This event is **not automatically emitted** by LUSID, but can be manually triggered to exercise an in-the-money physically-settled option at the strike price. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#exercising-a-physicallysettled-option).
- `OptionExerciseCashEvent`. This event is **not automatically emitted** by LUSID, but can be manually triggered to exercise an in-the-money cash-settled option, providing an exercise price for the underlying has been loaded into the LUSID Quote Store. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#exercising-a-cashsettled-option).
- `ExpiryEvent`. This event is automatically emitted by LUSID on the expiry date, but only if you have chosen **not to exercise**. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#expiring-an-unexercised-option).

## Mastering instruments and establishing positions

Imagine we have a options contract on BMW shares trading on the Eurex exchange with the following characteristics. [See how to set this scenario up](/v1/docs/modelling-exchange-traded-options-in-lusid).

| `ExchangeTradedOption` instrument | Purchase transaction |
| --- | --- |
| - Contract size: 100 - Contracts: 1 - Strike price: 80 - Start date: 15 Jan 2025 - Maturity date: 21 Mar 2025 | - Units: 1000 - Price (of option): 3.13 - Fees: 0.17 1000 = 170 - Cost: (1000 3.13 * 100) + 170 = 313,170 - Transaction date: 13 Jan 2025 - Settlement date: 16 Jan 2025 |

## Exercising a physically-settled option

If the `deliveryType` of the `ExchangeTradedOption` is `Physical`, we can choose to exercise an in-the-money option by triggering LUSID to emit `OptionExercisePhysicalEvent`.

> **Note**: No market data is required to exercise a physically-settled option. LUSID exercises at the strike price specified in the instrument definition.

To do this:

1. Create a corporate action source and subscribe the portfolio to it. [See how to do this](/v1/docs/handling-a-cash-dividend-corporate-action-event#creating-a-corporate-action-source).
2. Create transaction types for the transactions automatically generated by `OptionExercisePhysicalEvent`. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#creating-a-suitable-physicallysettledoptionexercise-transaction-type).
3. Load an **event instruction** (not the event itself) into the portfolio to trigger `OptionExercisePhysicalEvent` on a particular date. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#loading-an-event-instruction-to-trigger-optionexercisephysicalevent).

> **Note**: For an implementation using the Python SDK, see [this Jupyter Notebook](https://github.com/finbourne/finbourne-notebooks/blob/main/V3/features/instrument-events/ExchangeTradedOption-(physical-settlement)-and-instrument-events.ipynb).

### Creating suitable transaction types

To handle `OptionExercisePhysicalEvent` we must create at least two transaction types:

- For any `ExchangeTradedOption`, we must create `PhysicallySettledOptionExercise` to reduce the units and cost of the exercised instrument down to zero, so it drops out of holding and valuation reports. [See our recommendation](/v1/docs/recommended-transaction-types-for-instrument-lifecycle-events#optionexercisephysicalevent).
- If the `optionType` of the `ExchangeTradedOption` is `Call`, we must create `CallOptionPhysicalExercise` to buy the underlying instrument at the strike price. [See our recommendation](/v1/docs/recommended-transaction-types-for-instrument-lifecycle-events#calloptionphysicalexercise-transaction-type).
- If the `optionType` of the `ExchangeTradedOption` is `Put`, we must create `PutOptionPhysicalExercise` to sell the underlying instrument at the strike price. [See our recommendation](/v1/docs/recommended-transaction-types-for-instrument-lifecycle-events#putoptionphysicalexercise-transaction-type).

### Loading an event instruction to trigger `OptionExercisePhysicalEvent`

We can call the [UpsertInstrumentEventInstructions](https://www.lusid.com/docs/api/lusid/endpoints/portfolios/UpsertInstrumentEventInstructions/) API to load an **event instruction** (not the event itself) into the portfolio and trigger `OptionExercisePhysicalEvent`:

- If the `exerciseType` of our option is `American`, we can exercise earlier than the expiry date of the option (21 March 2025) by specifying the `entitlementDateInstructed` field with an exercise date of (for example) 28 February 2025.
- If the `exerciseType` is `European`, we can only exercise on the expiry date so the `entitlementDateInstructed` field is disabled.

```json
{
    "instrumentEventInstructionId": "ExerciseAmericanCallOptionOnBMW-2025-02-28",
    "instrumentEventId": "LUID_00003EB8_OptionExercisePhysicalEvent_American",
    "instructionType": "ElectForHolding",
    "holdingId": 75498862,
    "electionKey": "exercise",
    "entitlementDateInstructed": "2025-02-28T00:00:00.0000000+00:00"
}
```

For more information on event instructions, see [this article](/v1/docs/loading-an-event-instruction-to-override-an-instrument-event-for-a-particular-portfolio). Note the following:

- The `instrumentEventInstructionId` can be any intuitive string that uniquely identifies this event instruction in this portfolio.
- The `instrumentEventId` must be the unique identifier of the `OptionExercisePhysicalEvent` (see below for how to find this out).
- The `instructionType` is `ElectForHolding` to apply the event to our option holding in the portfolio.
- The `holdingId` must be the unique identifier for this holding (see below).
- The `electionKey` must be `exercise` to trigger LUSID to emit the event.
- The `entitlementDateInstructed` field is set to the date we wish to exercise (American options only).

To discover the `instrumentEventId` and `holdingId`, call the [QueryApplicableInstrumentEvents](https://www.lusid.com/docs/api#operation/QueryApplicableInstrumentEvents) API for the portfolio, for example:

```json
{
  "values": [
    {
      "portfolioId": {"scope": "UKEquities", "code": "MyPortfolio"},
      "lusidInstrumentId": "LUID_00003EB8",
      "instrumentType": "ExchangeTradedOption",
      "instrumentEventType": "OptionExercisePhysicalEvent",
      "instrumentEventId": "LUID_00003EB8_OptionExercisePhysicalEvent_American"
      "holdingId": 75498862,
      ...
```

### Examining the impact of `OptionExercisePhysicalEvent` on the portfolio

This example demonstrates exercising an in-the-money American call option early.

#### 15 January

We can use the **Portfolio Management > Holdings** dashboard 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 of the option purchase to see that we start with:

- An option holding for 1000 units at a cost of 313,710
- A currency holding for -€313,710:

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

#### 28 February

On 28 February we load the event instruction to exercise our option early and then examine holdings again:

- The option holding has been removed since units and cost are now zero. Note there is no P&L associated with this movement.
- A holding in the underlying BMW equity instrument has been established, with the units set to the number of BMW shares purchased (`1000 × 100 = 100,000`) and the cost to those shares at the strike price plus the cost of the option: `(100,000 × 80) + 313,170 = 8,313,170`.
- The currency holding reflects the total cost of establishing the BMW holding: -€8,313,710:

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

We can use the **Portfolio Management > Transactions** dashboard 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 transactions generated by this event:

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

## Exercising a cash-settled option

If the `deliveryType` of the `ExchangeTradedOption` is `Cash`, we can choose to exercise an in-the-money option by triggering LUSID to emit `OptionExerciseCashEvent`. To do this:

1. Create a corporate action source and subscribe the portfolio to it. [See how to do this](/v1/docs/handling-a-cash-dividend-corporate-action-event#creating-a-corporate-action-source).
2. Create a `CashSettledOptionExercise` transaction type for the transaction automatically generated by `OptionExerciseCashEvent` to reduce the position of the option instrument down to zero and increase cash. [See our recommendation](/v1/docs/recommended-transaction-types-for-instrument-lifecycle-events#optionexercisecashevent).
3. Load an **event instruction** (not the event itself) into the portfolio to trigger `OptionExerciseCashEvent` on a particular date. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#loading-an-event-instruction-to-trigger-optionexercisecashevent).
4. Load an exercise price for the underlying instrument on that date into the LUSID Quote Store. [More information](/v1/docs/handling-lifecycle-events-for-exchangetradedoption-instruments#loading-an-exercise-price-for-the-underlying-instrument-on-the-exercise-date).

> **Note**: For an implementation using the Python SDK, see [this Jupyter Notebook](https://github.com/finbourne/finbourne-notebooks/blob/main/V3/features/instrument-events/ExchangeTradedOption-(cash-settlement)-and-instrument-events.ipynb).

### Loading an event instruction to trigger `OptionExerciseCashEvent`

We can call the [UpsertInstrumentEventInstructions](https://www.lusid.com/docs/api/lusid/endpoints/portfolios/UpsertInstrumentEventInstructions/) API to load an **event instruction** (not the event itself) into the portfolio and trigger `OptionExerciseCashEvent`:

- If the `exerciseType` of our option is `American`, we can exercise earlier than the expiry date of the option (21 March 2025) by specifying the `entitlementDateInstructed` field with an exercise date of (for example) 28 February 2025.
- If the `exerciseType` is `European`, we can only exercise on the expiry date so the `entitlementDateInstructed` field is disabled.

```json
{
    "instrumentEventInstructionId": "ExerciseAmericanCallOptionOnBMW-2025-02-28",
    "instrumentEventId": "LUID_00003EB8_OptionExerciseCashEvent_American",
    "instructionType": "ElectForHolding",
    "holdingId": 75498862,
    "electionKey": "exercise",
    "entitlementDateInstructed": "2025-02-28T00:00:00.0000000+00:00"
}
```

For more information on event instructions, see [this article](/v1/docs/loading-an-event-instruction-to-override-an-instrument-event-for-a-particular-portfolio). Note the following:

- The `instrumentEventInstructionId` can be any intuitive string that uniquely identifies this event instruction in this portfolio.
- The `instrumentEventId` must be the unique identifier of the `OptionExerciseCashEvent` (see below for how to find this out).
- The `instructionType` is `ElectForHolding` to apply the event to our option holding in the portfolio.
- The `holdingId` must be the unique identifier for this holding (see below).
- The `electionKey` must be `exercise` to trigger LUSID to emit the event.
- The `entitlementDateInstructed` field is set to the date we wish to exercise (American options only).

To discover the `instrumentEventId` and `holdingId`, call the [QueryApplicableInstrumentEvents](https://www.lusid.com/docs/api#operation/QueryApplicableInstrumentEvents) API for the portfolio, for example:

```json
{
  "values": [
    {
      "portfolioId": {"scope": "UKEquities", "code": "MyPortfolio"},
      "lusidInstrumentId": "LUID_00003EB8",
      "instrumentType": "ExchangeTradedOption",
      "instrumentEventType": "OptionExerciseCashEvent",
      "instrumentEventId": "LUID_00003EB8_OptionExerciseCashEvent_American"
      "holdingId": 75498862,
      ...
```

### Loading an exercise price for the underlying instrument on the exercise date

We must call the [UpsertQuotes](https://www.lusid.com/docs/api/lusid/endpoints/quotes/UpsertQuotes/) API to load an exercise price for the underlying BMW equity instrument into the LUSID Quote Store:

- If the `optionType` of our option is `Call`, we must load an exercise price greater than the strike price specified in the option instrument definition (in our case 80), for example 85.
- If the `optionType` is `Put`, we must load an exercise price lower than the strike price.

```json
curl -X POST 'https://<your-domain>.lusid.com/api/api/quotes/MyOptionExercisePricesScope'
  -H 'Authorization: Bearer <your-API-access-token>'
  -H 'Content-Type: application/json-patch+json'
  -d '{
  "Quote-0001": {
    "quoteId": {
      "quoteSeriesId": {
        "provider": "Lusid",
        "instrumentIdType": "Isin",
        "instrumentId": "DE0005190003",
        "quoteType": "Price",
        "field": "mid"
      },
      "effectiveAt": "2025-02-28T00:00:00Z"
    },
    "metricValue": {
      "value": 85, "unit": "EUR"
    }
  },
```

Note the following:

- We recommend exercise prices are loaded into a dedicated quote scope, for example `MyOptionExercisePricesScope` (specified in the URL).
- The `instrumentIdType` must be `Isin`.
- The `instrumentId` must be registered as an ISIN [identifier](/v1/docs/understanding-instrument-identifiers) for the underlying instrument.
- The `effectiveAt` must be the exercise date, so 28 February 2025 for our American option. Note this must be the expiry date for a European option.

In order to locate this exercise price, the [portfolio recipe](/v1/docs/setting-a-portfolio-recipe) must have a market rule with:

- The `key` field set to `Quote.Isin.*` to look up quotes loaded with an ISIN identifier.
- The `dataScope` field set to `MyOptionExercisePricesScope` to search the correct quote scope, for example:

```json
"market": {
  "marketRules": [
    {
      "key": "Quote.Isin.*",
      "supplier": "Lusid",
      "dataScope": "MyOptionExercisePricesScope",
      "quoteType": "Price",
      "field": "mid",
      "quoteInterval": "1D.0D"
    },
    ...
  ]
}
```

### Examining the impact of `OptionExerciseCashEvent` on the portfolio

This example demonstrates exercising an in-the-money American call option early.

#### 15 January

We can use the **Portfolio Management > Holdings** dashboard 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 of the option purchase to see that we start with:

- An option holding for 1000 units at a cost of 313,710
- A currency holding of -€313,710:

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

#### 28 February

On 28 February we load the event instruction to exercise our option early and then examine holdings again:

- The option holding has been removed since units are now zero.
- The currency holding reflects the total consideration (`1000 × 100 × 5 = 500000`) added to the original negative cost:

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

We can use the **Portfolio Management > Transactions** dashboard 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 generated by this event:

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

To audit P&L associated with this transaction, click the button at the end of the row (highlighted in yellow above):

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

## Expiring an unexercised option

If we do not exercise an option before the maturity date specified in the instrument definition, LUSID automatically emits an `ExpiryEvent`. Note this event is **not** emitted if we do exercise.

To handle this event, we must create an `Expiry` transaction type. [See our recommendation](/v1/docs/recommended-transaction-types-for-instrument-lifecycle-events#expiryevent).

### Examining the impact of `ExpiryEvent` on the portfolio

#### 15 January

We can use the **Portfolio Management > Holdings** dashboard 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 of the option purchase transaction to see that we start with:

- An option holding for 1000 units at a cost of 313,710
- A currency holding for -€313,710:

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

#### 21 March

If we fast-forward to the expiry date we can see that the option holding has been removed (units set to zero) and the currency holding is unchanged:

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

We can use the **Portfolio Management > Transactions** dashboard 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 generated by this event:

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

To audit P&L associated with this transaction, click the button at the end of the row (highlighted in yellow above):

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