Modelling exchange-traded options in LUSID


You can model an exchange-traded options contract as an instrument of type ExchangeTradedOption. See all supported instruments.

Mastering an instrument

There are numerous tools you can use to master an ExchangeTradedOption 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 of identifiers, and the facility to store extra information as properties.

Fields in the economic definition object are specific to ExchangeTradedOption. For more information on these fields, select ExchangeTradedOption from the definition dropdown in the UpsertInstruments API reference:

Specifying an underlying instrument

If the asset underlying an ExchangeTradedOption is:

  • An equity or an exchange-traded future, the recommended approach is to master it as a separate instrument in LUSID and provide a reference to a MasteredInstrument. If you do this, instrument events are available. See below for more information.

  • A bond, interest rate, index, commodity or any other type of asset, the only option is to provide an inline definition as part of the ExchangeTradedOption. Instrument events are not available.

Mastering an ExchangeTradedOption instrument

The following example masters an options contract on AAPL that is already mastered as an instrument of type Equity in LUSID:

curl -X POST 'https://mydomain.lusid.com/api/api/instruments?scope=MyCustomInstrScope'
   -H 'Content-Type: application/json-patch+json'
   -H 'Authorization: Bearer <my-API-access-token>'
   -d '{"upsert-request-1": {
    "name": "OptionOnAPPL",
    "identifiers": {"ClientInternal": {"value": "OptionOnAPPL"}},
    "definition": {
      "instrumentType": "ExchangeTradedOption",
      "startDate": "2024-09-21T00:00:00.0000000+00:00",
      "contractDetails": {
        "domCcy": "USD",
        "strike": 250,
        "contractSize": 100,
        "country": "US",
        "deliveryType": "Physical",
        "description": "Option on APPL equity",
        "exchangeCode": "CME",
        "exerciseDate": "2024-12-21T00:00:00.0000000+00:00",
        "exerciseType": "American",
        "optionCode": "ZQF4C",
        "optionType": "Call",
        "underlying": {
          "instrumentType": "MasteredInstrument",
          "identifiers": {"Instrument/default/Figi": "US0378331005"}
        },
        "underlyingCode": "MyIDForAPPLQuotes"
      },
      "contracts": 1,
      "refSpotPrice": 0
    }
  }
}'

Note the following:

  • The ExchangeTradedOption instrument is mastered in a custom instrument scope (specified in the URL).

  • The identifiers object references a ClientInternal unique identifier.

  • startDate is a mandatory field but note it is not subsequently used by LUSID.

  • deliveryType can be Physical (if you intend to take delivery of the underlying) or Cash.

  • exerciseType can be American, European or Bermudan.

  • optionType can be Put or Call.

  • The underlying object must either:

    • Have the underlying.instrumentType field set to MasteredInstrument if the underlying is already mastered as an Equity or Future in LUSID, and the underlying.identifiers object set to a unique identifier for that instrument, in this case a FIGI. Note the underlying must reside in the same instrument scope as the ExchangeTradedOption, or else in the default instrument scope.

    • Be populated with a full inline economic definition if the underlying is any other type of instrument.

  • underlyingCode can be set to any intuitive string that represents a market data identifier for the underlying instrument loaded into the LUSID Quote Store.

  • contracts should be set to 1 and the amount bought or sold specified on the transaction.

Providing the request is successful, the response:

  • Confirms the globally-unique LUID of the ExchangeTradedOption instrument (in this case LUID_00003E8D) and also that of the MasteredInstrument if LUSID is able to resolve it correctly (in this case LUID_00003E8E). If not, the unknown instrument is returned.

  • Generates extra fields that are stored as part of the instrument definition and can be filtered on.

  • Supplies default values for fields not explicitly specified in the request:

{
  "values": {
    "upsert-request-1": {
      "scope": "MyCustomInstrScope",
      "lusidInstrumentId": "LUID_00003E8D",
      "name": "OptionOnAPPL",
      "identifiers": {
        "ClientInternal": "OptionOnAPPL",
        "LusidInstrumentId": "LUID_00003E8D"
      },
      "properties": [],
      "instrumentDefinition": {
        "startDate": "2024-09-21T00:00:00.0000000+00:00",
        "contractDetails": {
          "domCcy": "USD",
          "strike": 250,
          "contractSize": 100,
          "country": "US",
          "deliveryType": "Physical",
          "description": "Option on APPL",
          "exchangeCode": "CME",
          "exerciseDate": "2024-12-21T00:00:00.0000000+00:00",
          "exerciseType": "American",
          "optionCode": "ZQF4C",
          "optionType": "Call",
          "underlying": {
            "identifiers": {
              "Instrument/default/Figi": "US0378331005"
            },
            "masteredDomCcy": "USD",
            "masteredInstrumentType": "Equity",
            "masteredLusidInstrumentId": "LUID_00003E8E",
            "masteredName": "Apple",
            "masteredScope": "MyCustomInstrScope",
            "masteredAssetClass": "Equities",
            "instrumentType": "MasteredInstrument"
          },
          "underlyingCode": "MyIDForAPPLQuotes",
          "deliveryDays": 0,
          "businessDayConvention": "F",
          "settlementCalendars": []
        },
        "contracts": 1,
        "refSpotPrice": 0,
        "tradingConventions": {
          "priceScaleFactor": 1,
          "minimumOrderSize": 0,
          "minimumOrderIncrement": 0
        },
        "instrumentType": "ExchangeTradedOption"
      },
      "state": "Active",
      "assetClass": "Unknown",
      "domCcy": "USD",
      "relationships": []
    }
  },
  ...
}

Booking a transaction to establish a position

Once an instrument is mastered, you can book a transaction in an ExchangeTradedOption instrument to record the acquisition of a quantity in a particular transaction portfolio, for example:

curl -X POST 'https://mydomain.lusid.com/api/api/transactionportfolios/MyPortfolioScope/MyPortfolioCode/transactions/$batchUpsert?successMode=Partial&preserveProperties=true'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <API-access-token>'
  -d '{
  "transactionRequest-1": {
    "transactionId": "my_option_purchase_001",
    "type": "BuyETO",
    "instrumentIdentifiers": {"Instrument/default/LusidInstrumentId": "LUID_00003E8D"},
    "transactionDate": "2024-10-01T09:00:00.0000000+00:00",
    "settlementDate": "2024-10-03T09:00:00.0000000+00:00",
    "units": 1,
    "transactionPrice": {
      "price": 100,
      "type": "Price"
    },
    "totalConsideration": {
      "amount": 0,
      "currency": "USD"
    },
    "properties": {
      "Transaction/MyProperties/TradeCommission": {
        "key": "Transaction/MyProperties/TradeCommission",
        "value": {
          "metricValue": {
            "value": 50,
            "unit": "USD"
          }
        }
      }
    }
  }
}'

Note the following:

  • The type field invokes a custom BuyETO transaction type to confer a particular economic impact (see below).

  • The units field specifies the number of contracts.

  • The transactionPrice object records the market price of the options contract (not the underlying). This is used by LUSID to automatically calculate gross consideration (see below).

  • The totalConsideration object:

    • Sets the settlement currency to USD.

    • Specifies a cost of 0 to enable LUSID to automatically derive total consideration (see below).

  • The cost of entering into the contract is recorded as a custom property.

Note: This example assumes the transaction, settlement and portfolio currencies are all the same. If not, you can specify exchange rates.

You might create a BuyETO transaction type as follows:

curl -X PUT 'https://mydomain.lusid.com/api/api/transactionconfiguration/types/default/BuyETO?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "BuyETO",
      "description": "Transaction type for option purchases",
      "transactionClass": "Basic",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Increase units by number purchased",
      "movementTypes": "StockMovement",
      "side": "Side1",
      "direction": 1
    },
    {
      "name": "Decrease cash by cost of trade commission",
      "movementTypes": "CashCommitment",
      "side": "BuyETOCashCustomSide",
      "direction": -1
    }
  ],
  "calculations": [
    {
      "type": "Txn:GrossConsideration"
    },
    {
      "type": "DeriveTotalConsideration",
      "formula": "Txn:GrossConsideration + Properties[Transaction/MyProperties/TradeCommission]"
    }
  ]
}'

Note the following:

  • The StockMovement movement sets the units of the holding to the number purchased in the transaction.

  • The CashCommitment movement decreases a cash balance by the trade commission (see the custom side below).

  • The Txn:GrossConsideration transaction type calculation automatically calculates gross consideration (amount before fees) as price * units * contractSize, and stores the result in the Transaction/default/GrossConsideration system property.

  • The DeriveTotalConsideration transaction type calculation automatically calculates the totalConsideration.amount field according to the given formula, which in this case sums gross consideration and commission.

You might create a MyBuyETOCashCustomSide as follows:

curl -X PUT 'https://mydomain.lusid.com/api/api/transactionconfiguration/sides/MyBuyCashETOCustomSide?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <my-API-access-token>'
  -d '{
  "security": "Txn:SettleCcy",
  "currency": "Txn:SettlementCurrency",
  "rate": "SettledToPortfolioRate",
  "units": "Transaction/MyProperties/TotalCapitalisedFees",
  "amount": "Transaction/MyProperties/TotalCapitalisedFees"
}'

Confirming positions

You can generate a holdings report to see the impact of the upserted transaction on security and cash holdings, for example:

Auditing LUSID’s transaction type calculations

You can examine the output transaction generated by LUSID in reponse to the upserted input transaction, for example: