Skip to main content

Calculations (MXL)

The calculations app provides MXL (Maybern Expression Language), a formula language for dynamic financial calculations and data transformations.

What is MXL?

MXL allows users to define dynamic business logic through formulas instead of hardcoded values:
IF(CREDIT_FACILITY[TOTAL_UNUSED] / CREDIT_FACILITY[TOTAL_COMMITMENTS] > 0.5, 0.25, 0.20)
This enables:
  • Complex conditional calculations
  • Real-time adaptation to data changes
  • Transparent audit trails

Basic Syntax

Literals

# Numbers
42, 3.14, 100.5

# Strings
"USD", "capital"

# Booleans
TRUE, FALSE

# Null
NULL

# Arrays
[1, 2, 3], ["USD", "EUR"]

# Time intervals
1 day, 2 months, 3 quarters, 1 year

Column Access

# Simple column
Transaction[capital_amount]

# Qualified column (for joins)
Transaction[InvestmentAdjustedTransaction.capital_amount]

# Computed expressions
Transaction[capital_amount * -1]
Transaction[capital_amount > 0]

Operators

TypeOperators
Arithmetic+, -, *, /, ^
Comparison=, <>, <, <=, >, >=
LogicalAND, OR, NOT

Contexts

Each MXL calculation has a context that determines available tables, columns, and variables.
Tables: Transaction, TransactionsBySecurityOwnershipUse Cases: Allocation rule basis

Common Functions

Aggregation

SUM(Transaction[capital_amount])
COUNT(Transaction[id])
MIN(Transaction[effective_date])
MAX(Transaction[effective_date])
AVG(Transaction[capital_amount])

Conditional

IF(condition, true_value, false_value)
IFS(cond1, val1, cond2, val2, ...)
SWITCH(expr, case1, val1, case2, val2, default)

Date Functions

TODAY()
YEAR(date)
MONTH(date)
DAY(date)
DATEDIF(start, end, unit)

Financial

XIRR(dates, values)
XNPV(rate, dates, values)

Integration Pattern

Model Setup

# Static value OR calculation
unused_fee_rate = models.DecimalField(null=True)
unused_fee_rate_calculation = models.ForeignKey(
    "calculations.CalculationVersion",
    null=True,
)

class Meta:
    constraints = [
        models.CheckConstraint(
            name='exactly_one_method',
            check=(
                Q(unused_fee_rate__isnull=False, unused_fee_rate_calculation__isnull=True) |
                Q(unused_fee_rate__isnull=True, unused_fee_rate_calculation__isnull=False)
            )
        )
    ]

Dynamic Resolution

def get_rate(ctx, model_version, effective_date, variables):
    # Path 1: Static value
    if model_version.static_rate is not None:
        return model_version.static_rate
    
    # Path 2: MXL calculation
    if model_version.rate_calculation_id:
        execution_context = get_mxl_context(ctx, model_version.id, effective_date)
        formula = get_formula(ctx, model_version.rate_calculation_id)
        
        result = CalculationService.calculate(
            execution_data=execution_context,
            formula=formula,
            variables=variables,
        )
        return result.to_dataframe()["result"].iloc[0]
    
    return default_rate

Audit Integration

MXL calculations create audit documents:
AuditDocumentService.create_calculation_audit_models_for_event(
    ctx=ctx,
    calculation_id_to_formula=calc_formulas,
    context=CalculationContextType.CREDIT_FACILITY,
    calc_variables=variables,
    effective_event_id=event.id,
    audit_document_type=AuditDocumentType.FEE_CALCULATION,
)

Best Practices

Only one of static value OR calculation should be set. Use database constraints to enforce this.
Keep existing static field behavior. Add calculation as an alternative, not a replacement.
Provide graceful fallbacks when calculations fail:
try:
    return calculate_mxl(...)
except Exception as e:
    logger.error(f"MXL failed: {e}")
    return default_value
Lock calculation version at event creation time. Don’t use latest version for historical events.