Providing you have suitable access control permissions, you can create (that is, book) an input transaction in a transaction portfolio to register a change to the quantity and/or cost of one or more holdings.
A new transaction must resolve to:
An underlying instrument mastered in LUSID.
A known transaction type defining the precise economic impact; that is, the effect on your holding in the underlying instrument, and also potentially on holdings in other instruments in the portfolio too (for example, currency holdings).
By default, LUSID operates a ‘data load first’ policy, so transactions are upserted and resolution failures must be handled manually as a post-process step. You can increase the level of validation to reject transactions that do not resolve to instruments, to transaction types, or both. Find out more about this.
A transaction in a portfolio is keyed by its unique transaction ID. If you specify the ID of an existing transaction then the original is updated rather than a new one created. Note LUSID stores every update as a separate record so you can see a full change history for a transaction by calling the GetTransactions API with ShowCancelledTransactions=True
, and examining the transactionStatus
field:
A new (never updated) transaction has a single record with a status of
Active
.An updated transaction has one record per update with a status of
Amended
, followed by anActive
record with the latest information unless thetransactionDate
field changed (see below).A transaction has a status of
Cancelled
if you:Explicitly cancelled the transaction.
Updated the
transactionDate
field. This is because LUSID automatically rebooks the transaction on the new transaction date.
Using the LUSID REST API
You can upsert (that is, create or update) up to 10,000 transactions per call to the BatchUpsertTransactions API.
Note: This API is recommended over UpsertTransactions because it resolves transactions to instruments using individual transaction dates rather than the generic date of the upsert operation itself, reducing the likelihood of instrument resolution failures.
Call the
BatchUpsertTransactions
API, passing in your API token and specifying in the URL:The
scope
andcode
of the parent portfolio.A
successMode
ofAtomic
to reject all transactions in the request if one fails validation. The default mode ofPartial
means each transaction is validated on its own merits. Find out more about this.
In the body of the API request, specify for each transaction in the batch:
An ephemeral ID that can be used to track warnings and failures in the response. This can be the same as the
transactionID
(below), or different. It is not stored in LUSID.A
transactionId
that uniquely identifies the transaction in the portfolio. You can use the LUSID sequence APIs to auto-generate unique IDs.A
type
that resolves to a known transaction type determining the precise economic impact, for exampleBuy
orSell
.A
source
in which to locate this transaction type if it is grouped with other types from a particular data provider. If omitted, LUSID searches thedefault
source. Note if the parent portfolio has a transaction type scope set then this transaction type must also be domiciled in that scope. More about scopes and sources.A set of
instrumentIdentifiers
that resolve to an instrument mastered in LUSID, each consisting of a 3-stage key (for example,Instrument/default/Figi
orInstrument/default/LusidInstrumentId
) and an appropriate value (for example,BBG000C6K6G9
orLUID_0000G7H5
). You must specify at least one unique instrument identifier; you can specify as many more (unique and non-unique) as you like to increase the likelihood of successful instrument resolution. See how LUSID resolves transactions to instruments.A
transactionDate
and asettlementDate
. Note that if the settlement date is later, LUSID categorises any cash holdings impacted by the transaction differently between the two dates.A number of
units
to transact. Depending on the underlying instrument, this might represent a number of shares, the principle in an interest rate swap, the face value of a bond, a number of ETO contracts and so on.A
transactionPrice
. Note this field is required if you ask LUSID to automatically calculate gross consideration for you, which is defined as total consideration before fees.A
totalConsideration.currency
that is the ISO 4217 code of the settlement currency, for example GBP.A
totalConsideration.amount
that represents the total amount payable or receivable in the settlement currency. Note the following:While you can store any number you like, total consideration in LUSID is intended to be after fees. So for a purchase transaction, this would be the trade amount payable plus fees. For a sale transaction, this would be the trade amount receivable minus fees.
You can set this field to
0
and ask LUSID to automatically calculate total consideration for you according to a formula.
Note: The mandatory API fields assume that the transaction, settlement and portfolio currencies are all the same. If not, or if you are booking a FX transaction to exchange two currencies, then you must set additional fields and properties. More information.
Optionally in the
properties
collection, any number of custom properties from theTransaction
domain to extend the data model.Optionally in the
properties
collection, any of the available system properties to record additional information that LUSID can subsequently use in business operations, for exampleTransaction/default/GrossConsideration
orTransaction/default/TradeToPortfolioRate
.Optionally in the
properties
collection, one or more sub-holding keys (SHKs) registered with the portfolio to assign the transaction to a specific holding once processed by the transaction type. If omitted, LUSID generates one holding in the portfolio per underlying instrument, with all transactions in that instrument contributing to the holding.
Consider the following example of a transaction to purchase 10 units of BP @ £20, paying and settling in GBP in a EUR-denominated portfolio with a £5 trade commission:
The
totalConsideration.amount
is (10 × £20) + £5 = £205.The transaction has two system properties, one to record the gross consideration (10 × £20 = £200) and the other a GBP/EUR spot rate from the transaction to the portfolio currency.
The transaction has two custom properties, one to record the trade commission and the other to assign the result of processing the transaction to a
Growth
SHK:
curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/Finbourne-Examples/Global-Equity/transactions/$batchUpsert?successMode=Partial'
-H 'Content-Type: application/json-patch+json'
-H 'Authorization: Bearer <your-API-access-token>'
-d '{
"transactionRequest-1": {
"transactionId": "Txn-0000001",
"type": "Buy",
"source": "Bloomberg",
"instrumentIdentifiers": {"Instrument/default/Figi": "BBG000C6K6G9"},
"transactionDate": "2024-05-15T00:00:00.0000000+00:00",
"settlementDate": "2024-05-18T00:00:00.0000000+00:00",
"units": 10,
"transactionPrice": {"price": 20, "type": "Price"},
"totalConsideration": {"amount": 205, "currency": "GBP"},
"properties": {
"Transaction/default/GrossConsideration": {
"key": "Transaction/default/GrossConsideration",
"value": {
"metricValue": {
"value": 200,
"unit": "GBP"
}
}
},
"Transaction/MyProperties/TotalCapitalisedFees": {
"key": "Transaction/MyProperties/TotalCapitalisedFees",
"value": {
"metricValue": {
"value": 5,
"unit": "GBP"
}
}
},
"Transaction/default/TradeToPortfolioRate": {
"key": "Transaction/default/TradeToPortfolioRate",
"value": {
"metricValue": {
"value": 1.2,
"unit": ""
}
}
},
"Transaction/MySHKs/Strategy": {
"key": "Transaction/MySHKs/Strategy",
"value": {
"labelValue": "Growth"
}
}
}
}
}'
Note the following in the response:
LUSID confirms the globally-unique
instrumentUid
(LUID) and theinstrumentScope
of the underlying instrument.LUSID sets the
transactionStatus
toActive
. If you subsequently edit the transaction, this becomesAmended
. See how to cancel a transaction.LUSID sets the
transactionCurrency
to the same as the settlement currency, at anexchangeRate
of 1.We recommend checking the
metadata
section for transactions in a batch that were upserted but failed to resolve to instruments, to transaction types, or both. Find out more about this.If you increased the level of validation, we recommend checking the
failed
section for transactions in a batch that were rejected for failing to resolve to instruments, to transaction types, or both.
{
"values": {
"transactionRequest-1": {
"transactionId": "Txn-0000001",
"type": "Buy",
"instrumentIdentifiers": {
"Instrument/default/Figi": "BBG000C6K6G9",
"Instrument/default/Isin": "GB00BH4HKS39"
},
"instrumentScope": "default",
"instrumentUid": "LUID_R7E12YK8",
"transactionDate": "2024-05-15T00:00:00.0000000+00:00",
"settlementDate": "2024-05-18T00:00:00.0000000+00:00",
"units": 10,
"transactionPrice": {
"price": 20,
"type": "Price"
},
"totalConsideration": {
"amount": 205,
"currency": "GBP"
},
"exchangeRate": 1,
"transactionCurrency": "GBP",
"properties": {
"Transaction/default/GrossConsideration": {
"key": "Transaction/default/GrossConsideration",
"value": {
"metricValue": {
"value": 200,
"unit": "GBP"
}
}
},
"Transaction/MyProperties/TotalCapitalisedFees": {
"key": "Transaction/MyProperties/TotalCapitalisedFees",
"value": {
"metricValue": {
"value": 5,
"unit": "GBP"
}
}
},
"Transaction/default/TradeToPortfolioRate": {
"key": "Transaction/default/TradeToPortfolioRate",
"value": {
"metricValue": {
"value": 1.2,
"unit": ""
}
}
},
"Transaction/MySHKs/Strategy": {
"key": "Transaction/MySHKs/Strategy",
"value": {
"labelValue": "Growth"
}
}
},
"source": "Bloomberg",
"entryDateTime": "2024-05-15T09:00:00.0000000+00:00",
"transactionStatus": "Active"
}
},
"failed": {},
"metadata": {},
...
}
Using Luminesce
You can use the Lusid.Portfolio.Txn.Writer
provider. More information.
Using the LUSID web app
Navigate to Dashboard > Transactions.
Click the Create transaction button and follow the instructions: