How do I create a matching ruleset?

Prev Next

You can create a matching ruleset to define how LUSID compares data for a reconciliation (rec) type, such as holding, input transaction, or valuation. Once you create a matching ruleset, you can use it in any number of reconciliation definitions.

Recommended reading: Understanding advanced reconciliations

Methods

  1. Navigate to Advanced Recs > Matching Rulesets.

  2. Click the Create matching ruleset button and populate the form. Continue reading this article to learn more about the fields you can populate in a matching ruleset.

Call the CreateMatchingRuleset API, for example:

curl -X POST "https://<your-domain>.lusid.com/api/api/recs/[TBC: endpoint path]"
  -H "Authorization: Bearer <your-API-access-token>"
  -d "{
  "id": {
    "scope": "Finbourne-Examples",
    "code": "HoldingUnits"
  },
  "displayName": "Compare holding units",
  "recType": "Holding",
  "filters": {
    "left": "holdingType eq 'P'",
    "right": "holdingType eq 'P'"
  },
  "coreRules": [
    {
      "ruleName": "Instrument",
      "leftFormula": "Properties[Instrument/default/Figi]",
      "rightFormula": "Properties[Instrument/default/Figi]",
      "isCaseSensitive": false
    }
  ],
  "aggregateRules": [
    {
      "ruleName": "Units",
      "leftFormula": "units",
      "leftOperation": "Sum",
      "rightFormula": "units",
      "rightOperation": "Sum"
    }
  ],
  "allowPartialMatching": true
}"

Fields

Rec type

Specifies the reconciliation type this matching ruleset applies to, out of:

  • Holding

  • Cash holding

  • Valuation

  • Input transaction

  • Output transaction

  • Settlement activity

Pre-filters

You can specify a left and right LUSID filtering expression that LUSID applies to that side’s data before comparing anything.

Core rules

Core rules tell LUSID how to pair up records from each side of the reconciliation.

Each core rule defines a value that must agree on both sides for LUSID to treat two records as the same. For a holdings reconciliation, for example, this could be an instrument identifier such as a FIGI or ISIN.

Each core rule has:

  • A Name, which you see as a column heading in your results.

  • A Left formula and Right formula which use LUSID filtering syntax to tell LUSID where to find the value on each side. See Appendix A for more information on accepted formula values.

If you add more than one core rule, LUSID only pairs two records together when the values for every core rule agree, or fall within that rule’s core tolerances.

💡 Tip

Choose a core rule (or set of core rules) that:

  • Identifies each record uniquely

  • Contains a value for every record on both sides

For example, cash balances don’t have a FIGI, so a FIGI core rule gives every cash balance the same empty value. Use pre-filters to exclude records like these, and reconcile them separately with a suitable rec type, such as Cash holding.

Core tolerances

You can add core tolerances to relax how your core rules behave, so LUSID can pair records whose values for that rule aren’t identical.

LUSID always attempts to pair exact records first; it only uses core tolerances for records it can’t pair exactly.

You can add up to five core tolerances to a matching ruleset. For each core tolerance, you must specify:

Aggregate rules

Aggregate rules tell LUSID which values to compare on records it has already paired, such as the number of units held. For each pair, LUSID shows you the following:

  • The value from each side

  • The difference between them

For each aggregate rule, you specify:

  • A Name, which you see as a column heading in your results.

  • A Left formula and Right formula which tell LUSID where to find the value to compare on each side. See Appendix A for more information on accepted formula values.

  • A Left operation and Right operation which tell LUSID how to combine the values on each side when more than one record shares the same core rule values. For example, Sum adds up the units across all those records.

Aggregate tolerances

You can add aggregate tolerances to allow compared values to differ by an acceptable amount without the result becoming a partial match. You can only use the numeric tolerance type for aggregate rules.

LUSID applies the numeric tolerance to each side’s total, after it has combined the values using the rule’s operation. See Appendix B: Tolerances for more information.

Updating a matching ruleset

Once created, you can update a matching ruleset in the following ways:

  • Via the LUSID web app: Find the ruleset you need to update and click the Edit icon.

  • Via the LUSID API: Call the UpdateMatchingRuleset endpoint.

When you update a matching ruleset:

  • All subsequent reconciliation runs that use the ruleset will use the updated version.

  • Reruns of an existing reconciliation instance that use the ruleset will use the updated version.

Appendix A: Using built-in fields and properties in formulas for each rec type

The built-in fields you can refer to in a rule formula depend on the rec type. Core rules and aggregate rules refer to the same fields.

The following table shows some examples for each rec type:

Rec type

What built-in fields can I use?

What properties can I use?

Holding

Holding fields, for example:

  • InstrumentUid

  • HoldingType

  • Units

  • SettledUnits

  • Cost.Amount

Properties from the following domains:

  • Holding

  • Instrument

  • Portfolio

  • CustodianAccount

For example, Properties[Instrument/default/Isin].

Cash holding

Holding fields, for example:

  • Units

  • SettledUnits

  • UnsettledUnits

  • HoldingTypeName

  • Cost.Currency

Valuation

Valuation fields, for example:

  • AddressKeys[Valuation/PV/Amount]

  • AddressKeys[Holding/Units]

  • AddressKeys[Instrument/default/Name]

  • AddressKeys[Valuation/PV].Units

  • AddressKeys[Valuation/EffectiveAt]

Properties accessed via address key, for example AddressKeys[Instrument/Properties[Instrument/<scope>/<code>]]

Input transaction

Input transaction fields, for example:

  • TransactionId

  • Type

  • TransactionDate

  • Units

  • TotalConsideration.Amount

Properties from the Transaction domain, for example Properties[Transaction/Finbourne-Examples/Strategy]

Output transaction

Output transaction fields, for example:

  • TransactionId

  • Description

  • TransactionDate

  • TransactionAmount

  • AccountingDate

Settlement activity

Settlement activity fields, for example:

  • ActivityType

  • ActivityDate

  • Direction

  • Units

  • Transaction.TransactionId

Properties from the following domains:

  • Accessed via Transaction.Properties[...]:

    • Transaction

  • Accessed via SettlementInstruction.Properties[...]:

    • SettlementInstruction

    • Portfolio

    • Instrument

Appendix B: Tolerances

Tolerance type

Applicable rule type

Data type rule formula must return

String cross

Core rule

Text

Attribute optionality

Core rule

Any

Date

Core rule

Dates

Numeric

Aggregate rule

Numbers

Tolerance type: String cross

A string cross tolerance treats one specific value on a side as equal to a different value on the other side.

Use this tolerance type for known differences in how each side records the same thing.

Important

LUSID reports records paired using a string cross tolerance as one of the following in the results:

  • A Cross if the aggregate rules agree.

  • A Partial Cross if the aggregate rules disagree.

You can check which tolerance LUSID used for a result in its Applied tolerance column.

Field

Description

Reference side

The side where LUSID expects to find the Reference value:

  • Left or Right: Use if the two values should be treated as equal one way round and not the other.

  • Either (default): Use if you don't mind which side each value is on.

Reference value

The value LUSID looks for on the reference side.

Cross value

The value on the other side that LUSID treats as equal to Reference value.

Note

To treat more than one pair of values as equal, add a separate tolerance for each pair.

For example, you could set a string cross tolerance when one side uses GBP, whilst the other uses GBp (and you want GBp to be considered GBP for the rec run):

If you’re creating a ruleset via API, you might specify the following:

{
  "toleranceType": "CoreStringCross",
  "ruleName": "Currency",
  "referenceValue": "GBP",
  "crossValue": "GBp",
  "referenceSide": "Left"
}

Tolerance type: Attribute optionality

An optionality tolerance allows LUSID to pair records when one side has no value for the core rule, for example because a property isn't set.

Field

Description

Optional side

Sets which side is allowed to have no value:

  • Left

  • Right

  • Either (default)

For example, you could set a tolerance where a right side with no strategy pairs with any strategy on the left side, whilst a left side with no strategy still has to agree with the right side exactly:

If you’re creating a ruleset via API, you might specify the following:

{
  "toleranceType": "CoreAttributeOptionality",
  "ruleName": "Strategy",
  "optionalSide": "Right"
}

Tolerance type: Date

A date tolerance pairs records when the date on one side is within an interval of the date on the other side.

Field

Description

Reference side

The side whose date LUSID measures the interval from: Left or Right.

Interval

How far the other side's date can be from the reference date, as an ISO 8601 period. For example:

  • P1D is one day

  • PT12H is 12 hours

Offset

Which direction the other side's date can differ in:

  • Earlier

  • Later

  • Either (default)

Note

  • The date range includes the dates at each end.

  • A record with no date never falls within a date tolerance.

For example, you could set a tolerance where a left settlement date 1 Oct 2026 pairs with a right settlement date anywhere from 30 Sep to 2 Oct 2026:

If you’re creating a ruleset via API, you might specify the following:

{
  "toleranceType": "CoreDateTolerance",
  "ruleName": "SettlementDate",
  "referenceSide": "Left",
  "interval": "P1D",
  "offset": "Either"
}

Tolerance type: Numeric

A numeric tolerance allows the totals for an aggregate rule to differ by a specified acceptable amount.

Field

Description

Reference side

Whether LUSID should measure the difference from the Left or Right total.

Absolute threshold

The difference allowed, in the rule’s own units. Must be greater than 0.

Relative threshold

The difference allowed, as a percentage of the reference side’s total. Must be greater than 0.

For example, 10 allows a 10% difference.

Threshold priority

If you set both Absolute threshold and Relative threshold, this specifies how LUSID combines the two thresholds:

  • GreaterOf: Passes the difference if it’s within either threshold.

  • LesserOf: Only passes the difference if it’s within both thresholds.

Offset

Which direction the non-reference side’s total can differ in:

  • Above

  • Below

  • Either (default)

Note

  • The range includes the values at each end.

  • A side with no total never falls within a numeric tolerance.

  • If you add more than one numeric tolerance to the same rule, the totals pass if they’re within any one of them.

  • For Relative threshold, the inputs vary depending on whether you’re using the LUSID web app or LUSID API:

    • LUSID web app: Specify a percentage, for example 10 allows a 10% difference

    • LUSID API: Specify a fraction, for example 0.1 allows a 10% difference

For example, this is how different thresholds could apply if the left side’s total is 100 and the right side’s total is 90 (a difference of 10, or 10% of the reference total):

Threshold scenario

Absolute threshold

Relative threshold (%)

Threshold priority

Within tolerance?

Absolute threshold equals the difference.

10

Not set

Not set

✅

Absolute threshold is less than the difference.

9

Not set

Not set

❌

Relative threshold equals the relative difference.

Not set

10

Not set

✅

Specifying both an Absolute and Relative threshold, with a Threshold priority of GreaterOf.

9

10

GreaterOf

✅

Specifying both an Absolute and Relative threshold, with a Threshold priority of LesserOf.

9

10

LesserOf

❌

Creating the final threshold scenario in the LUSID web app looks like this:

If you’re creating a ruleset via API, you might specify the following:

{
  "toleranceType": "Numeric",
  "ruleName": "Units",
  "referenceSide": "Left",
  "absoluteThreshold": 9,
  "relativeThreshold": 0.1,
  "thresholdPriority": "LesserOf",
  "offset": "Either"
}