What is a movement?

A movement is a component of a transaction type. It defines the economic impact of all transactions belonging to that type on holdings.

A transaction type must have at least one movement, and can have two or more. For example, the built-in Buy transaction type provided with LUSID—intended to signal a purchase of an instrument such as an equity or bond—has two movements. For each transaction upserted to a portfolio with a transaction type of Buy, LUSID automatically:

  • Increases the quantity of your holding in the underlying instrument (ie. BP or MSFT) by the number of units purchased.

  • Decreases the core cash balance in the transaction currency (ie. GBP or USD) by the total consideration.

Understand how LUSID uses transaction types to generate holdings.

A movement has the following data fields:

Data field

Status

Explanation

name

Optional

Specifies a name for the movement.

movementTypes

Mandatory

One of the built-in movement types controlling how and when holdings are updated.

direction

Mandatory

Controls whether the change is an increase or decrease. Allowed values are 1 and -1.
 

If transactions have unsigned units and amounts then 1 signals an increase and -1 signals a decrease. However, the opposite is true if units and amounts are signed. So for example if a sell transaction is for -30 units, then 1 signals a decrease.

side

Mandatory

A side is a plug-and-play component that determines which holdings are impacted and what attributes of transactions contribute to the change.

Allowed values are either the built-in sides provided with LUSID (currently Side1, Side2, BondInt and Side2WithoutBondInterest), or you can create your own custom sides.

condition

Optional

By default, a movement always occurs for every transaction belonging to a transaction type.

You can make a movement conditional so that it only occurs for particular transactions, or for transactions in particular portfolios.

You can use LUSID's filter syntax to include any field or property of a transaction or a portfolio in the condition, chaining expressions using the and and or operators if necessary:

Example

Movement only occurs if a transaction...

condition = "Transaction.totalConsideration.amount gt 2000"

Has a total consideration of more than 2000.

condition = "Transaction.units gte 100 and Transaction.Properties[Transaction/Broker/Commission] exists"

Is for 100 units or more and records broker commission.

condition = "Portfolio.baseCurrency eq 'GBP'"

Is in a GBP portfolio.

condition = "Portfolio.created gte 2024-01-01 and Portfolio.Properties[Portfolio/Manager/Name] in 'John Doe', 'Jane Doe'"

Is in a 2024 portfolio managed by John Doe or Jane Doe.

condition = "Transaction.units gte 100 and Portfolio.created gte 2024-01-01"

Is for 100 units or more in a 2024 portfolio.

properties

Optional

This can be any number of:

  • Custom properties to extend the data model and store extra information about movements. These properties must be from the TransactionConfiguration domain.

  • System properties that are valid for movements.

mappings

Optional

Allocates one or more sub-holding keys (SHKs) to override or supplement strategy tags applied directly to transactions.

Specify a 3-stage propertyKey representing a SHK registered with the parent portfolio, and either mapFrom the value of another transaction property, or setTo a static value (including an empty string to de-allocate an SHK).

For an example, see this tutorial on breaking out broker commission as a separate cash holding.

settlementDayOverride

Optional

For any movement type that impacts holdings on settlement date, overrides settlement dates specified in transactions and uses dates in the specified custom property added to those transactions instead.

This field must be set to the 3-stage key of a custom property in the Transaction domain, for example Transaction/myscope/mysettlementdate. Note the underlying property type must have a data type that itself has a primitive value type of DateTime. See how to set this up.

Note if a particular transaction does not have a property of this type, or the property value does not resolve to a valid date and time, then the original settlement date for the transaction is used.

movementOptions

Optional

A comma-separated list of options to configure the movement. The following are available:

Option

Notes

DirectAdjustment

Applicability: movementTypes set to StockMovement.

Specify this option to override LUSID's standard logic and:

  1. Adjust the number of holding units by the number of units specified by the side.

  2. Adjust the holding cost by the amount specified by the side.

This is different to LUSID's default closing behavior, which is to scale the cost and calculate realised gain/loss.

This option can be used to adjust the units of holdings without impacting the cost, perhaps to model a 1-for-2 reverse stock split by loading a transaction that halves the number of units but with a total consideration of zero:

  • The units are reduced by the transaction units, as normal.

  • The cost is not affected (that is, adjustment is zero).

Note that taxlots are not supported.

IncludesTradedInterest

Applicability: movementTypes set to either CashCommitment, CashAccrual or CashReceivable.

Specify this option for the cash movement of a transaction to buy or sell a bond to include interest accrued up to the settlement date of that transaction.

By default, only interest accrued up to the trade date is included.

Virtual

Applicability: movementTypes set to StockMovement.

Specify this option to calculate realised gain/loss without actually effecting a sale. See an example for FxForwards.