Related resources:



How-to guides

Providing you are a LUSID user with sufficient access control permissions, you can create an instrument to model a FX option in the LUSID instrument master. You can then:

Note: If you are the LUSID domain owner, you are automatically assigned the built-in lusid-administrator role, which has all the permissions necessary to perform the operations in this article. If you are informed you do not have a license to perform a particular operation, contact support.

Note there is an accompanying Jupyter Notebook that demonstrates many of the operations and concepts in this article. The Notebook contains two examples with different settlement types; this article concentrates on the one that settles with FX delivery (option 1).

Creating a FX option instrument

Unlike equity options, where you must first create an underlying equity instrument, you do not need to create an underlying FX forward instrument to master a FX option in LUSID. In the FX option instrument definition, you specify:

  • The start date.
  • Whether to call or put the foreign or domestic currency.
  • The strike price.
  • An optional premium amount, currency, and settlement date. Note we recommend booking the premium on the transaction instead.
  • The option maturity date.
  • The option settlement date.

You can also specify whether the option settles with physical delivery or netted cash, and has a digital payoff. The exercise type is European by default.

To create an instrument modelling a FX option, call the LUSID UpsertInstruments API and specify a definition with an instrumentType of FxOption, supplying the mandatory instrument details above.  For more information on constructing a suitable economic definition, examine the API documentation and choose FxOption from the drop-down box:

For example, providing you have a valid API access token, you could run the following command in your LUSID domain to create a FX option instrument for a call on the EUR domestic currency, a strike of 1.205, and with a 30D maturity that settles with FX delivery and a non-digital payoff:

curl -X POST "https://<your-domain>"
   -H "Authorization: Bearer <your-API-access-token"
   -H "Content-Type: application/json-patch+json"
   -d '{
  "request_id_1": {
    "name": "EUR/USD FX Option",
    "identifiers": {
      "ClientInternal": {
        "value": "EURUSD FX Option",
    "definition": {
      "instrumentType": "FxOption",
      "startDate": "2021-01-20T00:00:00.0000000+00:00",
      "domCcy": "EUR",
      "fgnCcy": "USD",
      "strike": 1.205,
      "isCallNotPut": "true",
      "isDeliveryNotCash": "true",
      "isPayoffDigital": "false",
      "optionMaturityDate": "2021-02-19T00:00:00.0000000+00:00",
      "optionSettlementDate": "2021-02-21T00:00:00.0000000+00:00",

Note the following:

  • The FX option instrument is unitised; this means that the principal is set to 1 in the instrument definition and the quantity of contracts purchased is determined when you book a transaction (see below).
  • For a call option, the strike is the EUR/USD exchange rate that must be exceeded (1.205 in this example) in order to profit. For a put option, the EUR/USD exchange rate must fall below the strike in order to profit.
  • The premium is not booked on this instrument but rather on the transaction instead.

Providing the request is valid, the response contains an automatically-generated LUID (in this case, LUID_00003DGB) that is guaranteed to be unique and never change. You can use this LUID to reference the FX option instrument in subsequent API calls:

  "values": {
    "request_id_1": {
      "href": "https://<your-domain>",
      "scope": "default",
      "lusidInstrumentId": "LUID_00003DGB",
      "version": {
        "effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
        "asAtDate": "2022-12-09T12:31:22.0330580+00:00"
      "name": "EUR/USD FX Option",
      "identifiers": {
        "ClientInternal": "EURUSD FX Option",
        "LusidInstrumentId": "LUID_00003DGB"
      "properties": [],
      "instrumentDefinition": {
        "startDate": "2021-01-20T00:00:00.0000000+00:00",
        "domCcy": "EUR",
        "fgnCcy": "USD",
        "strike": 1.205,
        "barriers": [],
        "exerciseType": "European",
        "isCallNotPut": true,
        "isDeliveryNotCash": true,
        "isPayoffDigital": false,
        "optionMaturityDate": "2021-02-19T00:00:00.0000000+00:00",
        "optionSettlementDate": "2021-02-21T00:00:00.0000000+00:00",
        "payoutStyle": "None",
        "touches": [],
        "instrumentType": "FxOption"
      "state": "Active",
      "assetClass": "FX",
      "domCcy": "EUR",
      "relationships": []

Booking a transaction to establish a position

Once the instrument is mastered, you can call the LUSID UpsertTransactions API to purchase a number of FX option contracts in a particular portfolio.

As discussed above, you can book the premium on the instrument and give the transaction zero cost, but our recommendation is to book the premium amount on the transaction, in this case 0.02 * 1000000 = 20000:

curl -X POST "https://<your-domain><scope>/<code>/transactions"
  -H "Authorization: Bearer <your-API-access-token>"
  -H "Content-Type: application/json-patch+json"
  -d '[ 
       "transactionId": "fxop-eurusd-buy-01",
       "type": "Buy",
       "instrumentIdentifiers": {
         "instrument/default/LusidInstrumentId": "LUID_00003DGB"
       "transactionDate": "2021-01-20T00:00:00.0000000+00:00",
       "settlementDate": "2021-01-22T00:00:00.0000000+00:00",
       "units": 1000000,
       "transactionPrice": {
         "price": 0.02,
         "type": "Price"
       "totalConsideration": {
         "amount": 20000,
         "currency": "EUR"

Note this transaction uses the built-in Buy transaction type, but you can create your own transaction type to represent FX option purchases if you wish.

You can confirm your position at any time by calling the LUSID GetHoldings API with the appropriate LUID:

curl -X GET "https://<your-domain><scope>/<code>/holdings?filter=instrumentUid%20eq%20%27LUID_00003DGB%27"
   -H "Authorization: Bearer <your-API-access-token>"

Valuing your position

To value your FX option position, you must first load the following market data into LUSID:

  • EUR/USD FX spot rates into the LUSID quote store. These are required for any date on which you want to value the option, and to convert spot cash between the different currencies in the option.
  • EUR and USD discount curves into the LUSID complex market data store. You must create and upsert two OIS curves, one for EUR and one for USD; these curves can be constructed from spot instruments, forwards, or discounts. Take special notice of the discount curve keys when loaded into the store, for example EUR/EUROIS and USD/USDOIS, as you will need to specify these in the recipe when pricing the FX option.
  • At-the-money forward volatilities in the LUSID complex market data store. You must create and upsert a volatility curve comprising a set of at-the-money forward volatility rates for each tenor in the market data.

For a demonstration of loading all these types of market data into LUSID, see section 4 of the accompanying Jupyter Notebook.

Once this market data is loaded you can create a valuation recipe to drive the valuation of the FX option. In the recipe, you must reference the market data and specify the BlackScholes pricing model. This is the classic option valuation model returning price, delta, Gamma, Rho, Theta, and Vega ("the Greeks"). Section 5 of the Notebook demonstrates how to create a recipe to value a FX option.

Section 6 of the Notebook shows how to value the FX option on the trade date (20 January 2021). With the market data and valuation recipe in place, you can call the GetValuation API to return its present value (shown in the Market Value columns in the Notebook). If you chose to book the option premium on the instrument, this is included in the valuation until the premium settlement date has been reached, at which point the value drops out. The delta (shown in Valuation/Delta columns in the Notebook) indicates how much the option price would change with a change in the underlying. For options that are far out-of-the-money, the delta tends towards 0. For options that are far in-the-money, the delta tends towards 1. For an at-the-money option, the delta is around 0.5. 

You can call the GetValuation API again for trade date + 3 days to roll the FX option forward beyond the premium settlement date to value the FX option without the premium.

Assessing risk

LUSID calculates exposure for a FX option contract as QTY * FX Spot * Delta.

You can use LUSID to calculate first and second order risks from the option contract itself. Contact Technical Support if you need more information.

Managing P&L on a regular basis

For FX options, P&L is managed cumulatively for the lifetime of the contract. As shown in section 6 of the accompanying Jupyter Notebook, the example contract described here is shown as the first line entry. The Market Value column in the table shows the (lifetime) unrealised contract gain or loss.

As the instrument is a call option, it only has value at expiry if the EUR/USD forward rate rises above the strike of 1.205. When this occurs, the intrinsic value of the option on the expiry date is the difference between the EUR/USD forward rate and the strike rate, multiplied by the number of contracts. If the EUR/USD forward rate falls below the strike rate at expiry, the value of the holding is 0 (zero).

Typically, a call FX option is bought, as in this case, when it is thought the base currency (EUR) will strengthen against the quote currency (USD) over the period to maturity; this can yield unlimited upside. When the base currency weakens against the quote currency, the loss is limited to the premium that has already been paid.

Closing your position and booking cash settlements

As the instrument nears maturity, you must make decisions. If an option is in-the-money, it is common for a buyer to notify the seller that the position should be exercised.

You can monitor the contract during its lifetime in several ways:

These LUSID features help you mitigate the risk of missing exercise dates or closing out open positions.

The first example FX option 1 in the Notebook expires on 19 February 2021. As shown in section 7 of the accompanying Jupyter Notebook, if you call the GetValuation API again to value the contract on the expiry date the Valuation/Delta field has a value of either 0 or 1, indicating: 

  • 1: You can create a FX forward for EUR/USD with a strike rate of 1.205, as the option is in-the-money at maturity.
  • 0: You cannot create a FX forward for EUR/USD as the option is out-of-the-money at maturity.

When the FX option is in-the-money and you want to take physical delivery (or netted cash) depending on the settlement type agreed, it is important to note:

  1. The cashflows are assumed to have been paid but are not presently auto-generated as such. This means the instrument or cashflow from the instrument drops out of your valuation. We will shortly implement ‘automatic settlement’, so that you can choose to auto-generate the appropriate instrument (or cash flow), link it to the contract or instrument in question, and upsert it to the portfolio.

    For now, you must do this manually by using either the Manage Cashflows dashboard in the LUSID web app, or by calling the GetUpsertablePortfolioCashFlows API on the exercise date to  return and upsert the imminent cashflows into LUSID as transactions. Section 7.1 of the Notebook shows the resulting cash flows for taking physical delivery; two cash flows are generated, a total consideration of 1,000,000.00 in EUR for the domestic currency and a total consideration of -1,205,000.00 in USD for the foreign currency. For the netted cash scenario, a single cash flow is generated: this is calculated as the difference between the exercise and strike rates multiplied by the number of contracts when the option is in-the-money, and is 0 (zero) when the option is out-of-the-money.
  2. An instrument cannot ‘expire’ in LUSID; it is still available post-maturity, although the valuation is 0. If you set your holding to 0, it will no longer appear in reports unless you are deliberately backdating.