Documentation Index

Fetch the complete documentation index at: https://support.lusid.com/llms.txt

Use this file to discover all available pages before exploring further.

Compliance rule template syntax

Prev Next

This article describes how parameters are bound to steps in a custom compliance rule template, and the expression language you can use for filtering, grouping, and calculating values within a rule.

If you’re using a standard system compliance template as-is, you won’t need this reference. For an introduction to compliance rules in general, see What is compliance in LUSID?

Mapping rule parameters to template steps

A compliance template is made up of steps, and each step has a label. When you create a compliance rule from that template, you supply values for that step using a parameter key made up of the step’s label and the name of the setting you’re providing, joined with .:

"{StepLabel}.{SettingName}"

For example, if your template has a step labelled Compare, you can target its settings with keys like Compare.Numerator and Compare.UpperBound.

The settings available for a step depend on its type. The following sections cover the step types you can use, and the parameter keys and value types each one accepts.

FilterStep

Filters individual holdings or orders. Drops anything that does not meet the condition before running subsequent steps.

Parameter key

Value type

What it does

{StepLabel}.Predicate

FilterPredicateComplianceParameter

A boolean condition using LUSID filtering syntax that is checked against each holding or order. Keeps true results, drops false results.

GroupByStep

Splits holdings or orders into groups based on your chosen value (for example portfolio or asset class). Subsequent steps run separately for each group.

Parameter key

Value type

What it does

{StepLabel}.GroupingKey

GroupBySelectorComplianceParameter

A value used to determine which group each holding or order belongs to

BranchStep

Works like GroupByStep, but each resulting branch is evaluated independently rather than nested as a sub-group.

Parameter key

Value type

What it does

{StepLabel}.BranchingKey

GroupBySelectorComplianceParameter

A value used to determine which branch each holding or order belongs to

GroupFilterStep

Filters at the group level, dropping an entire group if it fails the condition (rather than individual holdings or orders).

Parameter key

Value type

What it does

{StepLabel}.Predicate

GroupFilterPredicateComplianceParameter

A boolean condition using LUSID filtering syntax that is checked against each group. Keeps true results, drops false results.

CheckStep

A general pass/fail check, applied to each group.

Parameter key

Value type

What it does

{StepLabel}.HardPredicate

GroupFilterPredicateComplianceParameter

A boolean condition using LUSID filtering syntax that is checked against each group. false results set the rule result for that group to Failed.

{StepLabel}.SoftPredicate

GroupFilterPredicateComplianceParameter

A boolean condition using LUSID filtering syntax that is checked against each group. If this result is false but the HardPredicate is true, the rule result for the group is Warning.

Note

Both parameter keys are required. A group must fail the HardPredicate to be a breach; failing SoftPredicate but passing HardPredicate produces a warning, not a failure.


To disable warnings, set SoftPredicate to the same condition as HardPredicate.

PercentCheckStep

A dedicated step for percentage-based pass/fail checks. It calculates  for each group and checks the result against your bounds.

Parameter key

Value type

What it does

{StepLabel}.Numerator

GroupCalculationComplianceParameter

A valuation metric used as the numerator for this group

{StepLabel}.Denominator

GroupCalculationComplianceParameter

A valuation metric used as the denominator for this group; typically a total from an earlier group

{StepLabel}.UpperBound

DecimalComplianceParameter

The hard upper limit %; exceeding this produces a Failed result

{StepLabel}.LowerBound

DecimalComplianceParameter

The hard lower limit %; falling below this produces a Failed result

{StepLabel}.UpperWarning

DecimalComplianceParameter

The soft upper limit %; exceeding this, but not UpperBound, produces a Warning

{StepLabel}.LowerWarning

DecimalComplianceParameter

The soft lower limit %; falling below this, but not LowerBound, produces a Warning

Note

If you want a simple "no more than X% of the portfolio" check, set the denominator to reference the portfolio-level group created by an earlier GroupByStep, rather than the group the PercentCheckStep itself is working with.

RecombineStep

Merges grouped holdings or orders back together. This step doesn’t require any parameters.

Expression language

The following parameter types all use LUSID filtering syntax for their expressions:

  • Filter (FilterPredicateComplianceParameter)

  • Group by (GroupBySelectorComplianceParameter)

  • Group filter (GroupFilterPredicateComplianceParameter)

  • Group calculation (GroupCalculationComplianceParameter)

Fields you can group by

For single holdings or orders, you can group by any of the following:

Field

Description

Accessors

PortfolioId

The portfolio scope and code

.Code, .Scope

OrderId

For pre-trade checks, specify the order scope and code

.Code, .Scope

LusidInstrumentId

The instrument’s LUID

N/A

HoldingType

The type of holding, for example Position or Cash

HoldingId

The holding’s unique identifier

InstrumentType

The LUSID instrument type, for example Equity or Bond

Properties[...]

A property value referenced by key, for example Properties[Instrument/default/AssetClass]

Fields you can filter on

You can filter on any of the following fields:

Field

Filters

Description

Accessors

PortfolioId

Single holdings/orders

The portfolio scope and code

.Code, .Scope

OrderId

Single holdings/orders

For pre-trade checks, specify the order scope and code

.Code, .Scope

LusidInstrumentId

Single holdings/orders

The instrument’s LUID

N/A

HoldingType

Single holdings/orders

The type of holding, for example Position or Cash

HoldingId

Single holdings/orders

The holding’s unique identifier

InstrumentType

Single holdings/orders

The LUSID instrument type, for example Equity or Bond

SecurityCount

Groups

The number of securities in the group

GroupKey

Groups

The value that was used to create this group

Results[…]

Both groups and single holdings/orders

A calculated value referenced by address key, for example Results[Valuation/PV] (single). At group level, this returns every value in the group, so aggregate the values, for example Sum(...).

Properties[...]

Both groups and single holdings/orders

A property value referenced by key, for example Properties[Instrument/default/AssetClass]

At group level, append .Singular to get the single shared value (if every holding or order in the group has the same one).

ReferenceLists[…]

Both groups and single holdings/orders

Filter on membership in a reference list, for example HoldingType in ReferenceLists[Scope/RestrictedTypes] (single) or GroupKey in ReferenceLists[Scope/ExcludedIssuers] (group)

N/A

Referencing an earlier step’s result

You can refer to a group created by an earlier step in the same rule using its label:

PreviousStep[StepLabel]

This is most often used in a PercentCheckStep, where the denominator needs to be a pre-filtering total, for example a portfolio's total value, calculated before a step filtered down to just international equities.

All functions you can apply to groups can also be applied through PreviousStep, for example:

Sum(PreviousStep[PortfolioIdGroup].Results[Valuation/PvInPortfolioCcy])

PreviousStep[PortfolioIdGroup].GroupKey

Aggregate functions

Function

Example

Result

Sum

Sum(Results[Valuation/PvInPortfolioCcy])

The total of all values in the group

Average

Average(Results[Holding/Units])

The average of all values in the group

Abs

Abs(Sum(Results[Valuation/PvInPortfolioCcy]))

The absolute value of the result

Available operators

See Appendix A: Supported operators for more information on each operator:

  • eq

  • neq

  • gt

  • gte

  • lt

  • lte

  • in

  • not in

  • and

  • or

Note

String comparisons are case-insensitive.

Example: Limiting exposure to international equities

In this example, a compliance rule checks that international equities do not exceed 10% of a portfolio’s value. To do so, the rule uses a custom template with four steps:

  1. ExcludeCash

  2. PortfolioIdGroup

  3. InternationalEquityFilter

  4. Compare

The example uses the LUSID Python SDK:

parameters = {
    # Remove cash before working out the portfolio total
    "ExcludeCash.Predicate": lm.FilterPredicateComplianceParameter(
        value="Properties[Instrument/default/AssetClass] != 'Cash'",
        compliance_parameter_type="FilterPredicateComplianceParameter"
    ),

    # Group by portfolio — this group's total becomes the denominator
    "PortfolioIdGroup.GroupingKey": lm.GroupBySelectorComplianceParameter(
        value="PortfolioId",
        compliance_parameter_type="GroupBySelectorComplianceParameter"
    ),

    # Narrow down to international equities for the numerator
    "InternationalEquityFilter.Predicate": lm.FilterPredicateComplianceParameter(
        value="Properties[Instrument/default/AssetClass] == 'Equity'"
              "and Properties[Instrument/default/DomicileCountry] != 'GB'",
        compliance_parameter_type="FilterPredicateComplianceParameter"
    ),

    # Numerator: value of international equities remaining after the filter
    "Compare.Numerator": lm.GroupCalculationComplianceParameter(
        value="Sum(Results[Valuation/PvInPortfolioCcy])",
        compliance_parameter_type="GroupCalculationComplianceParameter"
    ),

    # Denominator: total portfolio value, from before the filter was applied
    "Compare.Denominator": lm.GroupCalculationComplianceParameter(
        value="Sum(PreviousStep[PortfolioIdGroup].Results[Valuation/PvInPortfolioCcy])",
        compliance_parameter_type="GroupCalculationComplianceParameter"
    ),

    "Compare.UpperBound": lm.DecimalComplianceParameter(
        value=10.0, compliance_parameter_type="DecimalComplianceParameter"
    ),
    "Compare.LowerBound": lm.DecimalComplianceParameter(
        value=-1.0, compliance_parameter_type="DecimalComplianceParameter"
    ),
    "Compare.UpperWarning": lm.DecimalComplianceParameter(
        value=8.0, compliance_parameter_type="DecimalComplianceParameter"
    ),
    "Compare.LowerWarning": lm.DecimalComplianceParameter(
        value=-1.0, compliance_parameter_type="DecimalComplianceParameter"
    ),
}

For an end-to-end tutorial, see Performing daily post-trade compliance runs. For more examples using the LUSID Python SDK, see the GitHub repo.