The recommended way to model a foreign exchange or currency forward contract ("FxForward") in LUSID is to create an instrument in the LUSID Security Master with the contract details (size of the forward exchange), and then book a unitised transaction in a portfolio (that is, one unit of the instrument).
You can model either a:
- Standard FxForward
The exchange of two quantities of two different currencies at a specified date and time. - Non-Deliverable Forward (NDF)
The payment of a settlement amount based on the exchange rate between two different currencies and amounts at a specified date and time.
This article focuses on modelling a Standard FxForward. There is also an accompanying Jupyter Notebook that demonstrates many of the concepts and operations.
Note: You can forgo mastering an instrument and simply book a forward-settled cash transaction directly in a portfolio, but note LUSID's full suite of analytical capability is not guaranteed to be available. See how to do this.
Mastering the instrument
To create an instrument modelling an FxForward, call the LUSID UpsertInstruments API and specify a definition with an instrumentType
of FxForward
, a domestic (sell currency) amount, a foreign (buy currency) amount, and start and maturity dates. For more information on constructing a suitable economic definition, examine the API documentation and choose FxForward
from the dropdown box:
For example, providing you have a valid API access token, you could run the following command in your LUSID domain to create an FxForward instrument representing an obligation to buy 1,200,000 USD at a cost of 1,000,000 GBP on 15 May 2022 (that is, 6 months from the instrument start date, at a strike rate of 1.2):
curl -X POST "https://<your-domain>.lusid.com/api/api/instruments" -H "Authorization: Bearer <your-API-access-token>" -H "Content-Type: application/json" -d '{"upsert-request-1": { "name": "GBPUSD 6M FxForward 20211115", "identifiers": { "ClientInternal": { "value": "FWD-GBPUSD-20211115", } }, "definition": { "instrumentType": "FxForward", "startDate": "2021-11-15T10:00:00.0000000+00:00", "maturityDate": "2022-05-15T10:00:00.0000000+00:00", "domAmount": -1000000, "domCcy": "GBP", "fgnAmount": 1200000, "fgnCcy": "USD" } } }'
Note the following:
domCcy
is the sell or pay currency anddomAmount
a negative quantity (in our example, we are selling -1,000,000 GBP in 6 months from the start date).fgnCcy
is the buy or receive currency andfgnAmount
a positive quantity (in our example, we are buying +1,200,000 USD in 6 months).
Providing the request is valid, the response contains an automatically-generated LUID (a system ID, in this case LUID_00003D58
) that is guaranteed to be unique and never change. You can use this LUID to reference the instrument in subsequent API calls:
{
"values": {
"upsert-request-1": {
"href": "https://<your-domain>.lusid.com/api/api/instruments/LusidInstrumentId/LUID_00003D58",
"lusidInstrumentId": "LUID_00003D58",
"version": {
"effectiveFrom": "0001-01-01T00:00:00.0000000+00:00",
"asAtDate": "2021-11-13T14:12:12.3335390+00:00"
},
"name": "GBPUSD 6M FxForward 20211115",
"identifiers": {
"LusidInstrumentId": "LUID_00003D58",
"ClientInternal": "FWD-GBPUSD-20211115"
},
"properties": [],
"instrumentDefinition": {
"startDate": "2021-11-15T10:00:00.0000000+00:00",
"maturityDate": "2022-05-15T10:00:00.0000000+00:00",
"domAmount": -1000000.0,
"domCcy": "GBP",
"fgnAmount": 1200000.0,
"fgnCcy": "USD",
"refSpotRate": 0.0,
"isNdf": false,
"fixingDate": "0001-01-01T00:00:00.0000000+00:00",
"instrumentType": "FxForward"
},
"state": "Active",
"assetClass": "FX",
"domCcy": "GBP"
}
},
...
}
Booking a transaction to establish a position
Once the instrument is mastered, you can call the LUSID UpsertTransactions API to record a purchase of the contract in a particular portfolio.
As mentioned above, FxForwards should be created with the currency amounts encapsulated in the instrument, and the transaction itself unitised (that is, with the units set to 1 and the cost to 0):
curl -X POST "https://<your-domain>.lusid.com/api/api/transactionportfolios/<scope>/<code>/transactions" -H "Authorization: Bearer <your-API-access-token>" -H "Content-Type: application/json" -d '[ { "transactionId": "fxfwd-gbp-usd-6m-01", "type": "StockIn", "instrumentIdentifiers": { "instrument/default/LusidInstrumentId": "LUID_00003D58" }, "transactionDate": "2021-11-15T00:00:00.0000000+00:00", "settlementDate": "2021-11-15T00:00:00.0000000+00:00", "units": 1, "transactionPrice": { "price": 0, "type": "Price" }, "totalConsideration": { "amount": 0, "currency": "USD" }, "transactionCurrency": "USD", "exchangeRate": 1 } ]'
Note this transaction uses the built-in StockIn
transaction type rather the built-in Buy
, since there is no cash outlay. However, you could define your own custom transaction type to represent FxForward 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>.lusid.com/api/api/transactionportfolios/<scope>/<code>/holdings?filter=instrumentUid%20eq%20'LUID_00003D58'" -H "Authorization: Bearer <your-API-access-token>"
Valuing your position
You can value your position against actual or estimated exchange rates at any time, and calculate the notional profit or loss (that is, the amount you have gained or lost by virtue of having entered into the fixed rate contract, relative to not having done so). You might do this to comply with IAS 39 or other hold-to-maturity accounting treatments (that is, without discounting, which is a separate treatment that is not discussed further in this article; contact Technical Support for more information).
In the example above, we are obliged to buy 1,200,000 USD at a cost of 1,000,000 GBP in 6 months from the instrument start date, which means the strike rate is 1.2. If we value the contract after 3 months and the current spot rate has decreased to 1.1, then you would expect LUSID to show your position with a notional profit of 100,000 USD (and equivalent in GBP at that rate), since you have ‘gained’ this amount by fixing the forward rate. On the other hand, if the spot rate has increased to 1.3, then you would expect LUSID to show a notional loss of 100,000 USD (and equivalent in GBP at that rate).
Loading market data into LUSID
You must first load suitable market data into LUSID. This can be:
- A FxForward curve loaded into the Complex Market Data Store; see section 4.2 of the accompanying Jupyter Notebook for a demonstration. This enables you to value the contract without having to specify an exact date; LUSID can interpolate and extrapolate from the curve to resolve dated forwards.
- A discount factor curve loaded into the Complex Market Data Store encapsulating the idea that money today is not worth the same as money in the future.
- A FX spot rate loaded into the Quote Store.
Creating a valuation recipe
You must create a valuation recipe that specifies which valuation model to use. Choose either:
SimpleStatic
to add your own quotes in for the instrument.Discounting
to discount each cashflow by a discounting curve for the currency. This model is not discussed further in this article; contact Technical Support for more information.ForwardWithPointsUndiscounted
to value your position using dated pips, orForwardSpecifiedRateUndiscounted
to value your position using rates loaded into the Quote Store, as demonstrated in the previous section.ForwardFromCurveUndiscounted
to value your position using an FxForward curve loaded into the Complex Market Data Store. For a demonstration of creating such a recipe, see section 5 of the accompanying Jupyter Notebook.
Note: By default, a recipe creates a single valuation for your position. Set the produceSeparateResultForLinearOtcLegs
flag to True
in the recipe to generate separate valuations for each currency leg, as demonstrated in section 5 of the Jupyter Notebook.
Understanding P&L
Assuming the IAS 39 accounting treatment is preferred, the NAV of the instrument is simply comprised of the P&L difference of the currency legs when the foreign leg is converted back to the reporting currency at the appropriate forward exchange rate. This assumes one leg of the FxForward is in the portfolio currency, and that one leg is the cash amount to be modelled.
If the legs are split for display purposes, the forward cash amounts are displayed in their domestic currency amount.
For a demonstration, see the valuations on Days 1, 2 and 3 in section 6.1 of the accompanying Jupyter Notebook.
Assessing risk
LUSID provides an exposure calculation and supports both analytic and bump and valuation mechanisms for assessing risk; contact Technical Support if you need more information.
Monitoring the lifecycle of the instrument
At some point you must decide whether to roll an FxForward contract or hold it until maturity. Rolling a contract means extending its maturity date; typically, the old contract is closed by setting a holding of zero (with a cash amount booked to reflect the P&L) and a new contract with a longer time to expiry is executed to replace the old. For a demonstration, see section 7.1 of the accompanying Jupyter Notebook.
If you choose to let the contract expire you can monitor your position in several ways:
- Use the Cash Ladder dashboard in the LUSID web app.
- Call the LUSID GetPortfolioCashLadder API directly.
- Schedule a job to create a regular report.
Note that once the maturity date passes your position will drop out of LUSID valuation reports.
When an instrument cashflow or maturity event occurs in LUSID, it's important to note two things:
- 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 cashflow or instrument, link it to the contract or instrument in question, and upsert it to the portfolio.
For now, this must be done manually, using either the Manage Cashflows dashboard in the LUSID web app, or by calling the LUSID GetUpsertablePortfolioCashFlows API, which returns imminent cashflows as upsertable DTOs ready to push into LUSID as transactions. For a demonstration, see sections 7.2 and 7.3 of the Jupyter Notebook. - 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. For a demonstration, see section 7.3 of the Jupyter Notebook.