A posting module assigns journal entry lines generated by LUSID to represent economic activity in portfolios to general ledger accounts. See how to create a posting module.
A posting module contains posting rules in a specific order. A posting rule assigns debit or credit amounts for journal entry lines matching a set of criteria to a specific account. Syntax of a posting rule.
For each journal entry line, LUSID applies the first matching posting rule found in the posting module. Unmatched journal entry lines remain unassigned. The goal of a posting module is to create a waterfall of logic that ensures all economic activity is assigned.
Consider the following example, of a posting module with five rules:
{ "values": [ { "ruleId": "rule_01", "account": "3-Capital", "ruleFilter": "EconomicBucket startswith 'CA'" }, { "ruleId": "rule_02", "account": "1-Investments", "ruleFilter": "HoldType eq 'P' and EconomicBucket startswith 'NA'" }, { "ruleId": "rule_03", "account": "4-PnL", "ruleFilter": "EconomicBucket startswith 'PL'" }, { "ruleId": "rule_04", "account": "2-Cash", "ruleFilter": "HoldType neq 'P' and EconomicBucket startswith 'NA'" }, { "ruleId": "rule_05", "account": "Error", "ruleFilter": "True" } ] }
For each generated journal entry line, LUSID automatically:
- Assigns the amount to the
3-Capital
account if the economic bucket starts withCA
. - If not, assigns the amount to the
1-Investments
account if the economic bucket starts withNA
and the holding type code isP
(position, signifying a non-currency holding). - If not, assigns the amount to the
4-PnL
account if the economic bucket starts withPL
. - If not, assigns the amount to the
2-Cash
account if the economic bucket starts withNA
and the holding type code is not equal toP
(that is, currency holdings). - If not, assigns the amount to an
Error
account for manual remediation.
In this example, rule 5 is a 'catch all' rule that assigns unmatched journal entry lines to a general-purpose account. You could omit rule 5, in which case any journal entry lines failing to match rules 1, 2, 3 and 4 remain unassigned.
Syntax of a posting rule
A posting rule consists of:
- A
ruleId
that uniquely identifies the posting rule in the posting module. - An
account
that is the code of an account in the parent chart of accounts (CoA). - A
ruleFilter
expression that describes criteria for matching journal entry lines to the account.
The syntax of a ruleFilter
expression is:
<attribute> <operator> <value>
...where:
<attribute>
and<value>
are explained in the table below.<operator>
is one of the LUSID filter operators.
<attribute> | Data type | Example expression | Explanation/origin of <value> |
SourceType | String | SourceType eq 'LusidTransaction' | Either LusidTransaction or LusidValuation . Use LusidValuation to map LUSID's automatic mark-to-market valuation activity to an account. |
ActivityDate | DateTime | ActivityDate gt 2023-01-01 | For a transaction, this is the trade date. For a valuation, this is the date of the latest detected change to market data. |
EconomicBucket | String | EconomicBucket startswith 'PL_Real' | LUSID automatically categorises every journal entry line into a broad economic bucket. More information. |
SourceId | String | SourceId eq 'Txn01' | For a transaction, this is the unique identifier in the portfolio (
|
TaxLotId | String | SourceId eq 'Txn01' | For a transaction, if the underlying instrument is a currency and the trade is settled (holding type of B ), the value is 1 (stored as a string). Otherwise, this is the same as the SourceId . |
LocalAmount | Decimal | LocalAmount lte 1000 | The amount in the transaction currency. |
BaseAmount | Decimal | BaseAmount gt 450000 | The amount in the portfolio base currency. |
DefaultCurrency | String | DefaultCurrency in 'GBP', 'USD' | The currency of the underlying instrument, if specified. |
InstrumentScope | String | InstrumentScope startswith 'Custom' | The instrument scope in which the underlying instrument is mastered. |
LusidInstrumentId | String | LusidInstrumentId not startswith 'CCY' | The LUID (globally unique ID) of the underlying instrument. |
HoldType | String | HoldType eq 'P' | One of the LUSID holding type codes. |
MovementName | String | MovementName eq 'Side1' | For a transaction, this is the name of the movement in the transaction type to which the transaction belongs. If the movement does not have a name (and note its For a valuation, this is always |
MovementSign | String | MovementSign eq 'Long' | Either Long or Short . |
A sub-holding key on the portfolio | User-defined | subholdingkeys[Transaction/Ibor/Strategy] eq 'Income' | Under-the-hood, a SHK is defined as a custom property with a 3-stage key in the Transaction domain. |
A portfolio field | System-defined |
| This can be any of the stored fields for a portfolio except the href , links and version fields, prefixed by Portfolio. Nested fields can be accessed using dot notation. |
A portfolio property | User-defined | properties[Portfolio/Ibor/Manager] in 'John Smith', 'Jane Jones' | This can be any property with a 3-stage key in the Portfolio domain. |
An instrument field | System-defined | Instrument.identifiers['LusidInstrumentId'] eq 'LUID_ZZZZZZZZ' | This can be any of the stored fields for an instrument except the href , links and version fields, prefixed by Instrument. Nested fields can be accessed using dot notation. |
An instrument property | User-defined | properties[Instrument/Ibor/AnalystRating] any (~ startswith 'A') | This can be any property with a 3-stage key in the Instrument domain. |
A transaction field | System-defined |
| This can be any of the stored fields for a transaction, prefixed by Transaction. Nested fields can be accessed using dot notation. |
A transaction property | User-defined | properties[Transaction/Ibor/Broker] eq 'AcmeCorp' | This can be any property with a 3-stage key in the Transaction domain. |
An account field | System-defined | Account.type in 'Asset', 'Liabilities' | This can be any of the stored fields for an account, prefixed by Account. Nested fields can be accessed using dot notation. |
An account property | User-defined | properties[Account/Type/AssetClass] eq 'Equity' | This can be any property with a 3-stage key in the Account domain. |
An ABOR property | User-defined | properties[Abor/Client/Accountant] not in 'Fred Bloggs', 'Sarah Smart' | This can be any property with a 3-stage key in the Abor domain. |
Note the following:
- A
ruleFilter
expression is case-insensitive. - A string
<value>
must be enclosed in single straight quote marks (the%27
UTF-8 encoding). - You can concatenate expressions using the
and
andor
operators, for example:MovementName eq 'Side1' and subholdingkeys[Transaction/Ibor/Strategy] eq 'Income'
If you use both, standard boolean operator precedence applies:
InstrumentScope startswith 'Custom' or (LocalAmount lte 1000 and HoldType eq 'P')