Skip to content

Rosetta Syntax Upgrade

Hugo Hills edited this page Sep 24, 2019 · 17 revisions

This document describes the desired state for the Rosetta DSL. The primary focus of this document is on the Syntax, with details on Scoping and Validation features captured inside code examples.

Further Scoping, Validation and Code Generation details to come.

Background

As part of on-going improvement and to facilitate the opening of CDM contributions to the community, we will implement a number of changes to the Rosetta DSL that will make reading and writing easier. Further, simplifications to the meta-model - the Ecore - should make external Code Generator contributions easier.

Current Rosetta DSL concepts:

  • Type (classes, enums, basic types, record types)
  • Synonym (mappings, conditionals, custom)
  • Validation (choice rules, data rules)
  • Calculation (calculation, functions)
  • Function Specification
  • Regulatory Rule

Goal

In essence, we see every model being made up of Types and Functions, and we wish to simplify the Rosetta DSL to reflect this.

The reduced number of objects in Ecore as well as fewer Grammar Rules will support greater reuse of Scoping, Validation and Code Generation features.

Below is a summary of changes to achieve this goal:

  1. Define consistent syntax (with respect to colon, semi-colons, braces, comments, definitions) between Types and Functions
  2. Replace class, enum and record type with Types
  3. Replace calculation, function, alias and spec with Functions
  4. Reuse consistent Function syntax for data rule, choice rule, one of and alias
  5. Support different views for DSL Readers vs. DSL Writers
  6. Regulatory Rules to be tackled in another phase of work

Anatomy

The anatomy of Rosetta concepts are generally described using Extended Backus–Naur form and describes the Grammar Rules that governs the syntax.

We start by specifying three root elements: Types, Function and Annotation. For each root element, we state its form, then as list of tasks to migrate from the current syntax to the proposed along with examples of current vs. proposed.

Types (replaces class, enums and record type)

Defining a Type objects takes the following form:

'type' Name ('extends' [Type])? ':' Definition?
    Annotation*
    Attribute+
    Condition*

where:

  • Definition:

      '<' STRING '>'
    
  • Annotation:

      '[' [Annotation] [Attribute] ']'  // square braces represent cross reference to existing Annotation (by Name) and one of its Attributes
    
  • Attribute:

      Name Type Cardinality (':' Definition)?
          Annotation*
    
  • Condition:

      'condition' Name? ':' Definition?
          Annotation*
          RosettaExpression+
    

Key Tasks with Examples:

  1. Replace class, enum and record type with Type
  2. Remove semi-colon at end of each attribute
  3. Remove angle-brackets in Definitions
  4. Remove quotes in synonym paths and enum synonyms, use a single Grammar tree to represent Synonyms

Current:

class Party key <"A class to specify a party, without a qualification as to whether this party is a legal entity or a natural person, although the model provides the ability to associate a person (or set of persons) to a party, which use case would imply that such party would be a legal entity (even if not formally specified as such). ">
   [synonym FpML_5_10, DTCC_11_0, DTCC_9_0 , CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value Party meta id maps 2]
{
   partyId string (1..*) scheme <"The identifier associated with a party, e.g. the 20 digits LEI code.">;
      [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value partyId meta partyIdScheme]
      [synonym DTCC_11_0, DTCC_9_0 value partyId maps 2 meta partyIdScheme]
      [synonym ISDA_Create_1_0 value id]
   name string (0..1) scheme <"The party name.">;
      [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value partyName meta entityNameScheme]
      [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value entityName meta entityNameScheme]
      [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value entityName path "referenceEntity" meta entityNameScheme]
      [synonym CME_SubmissionIRS_1_0 value SID path "Hdr"]
      [synonym ISDA_Create_1_0 value name]
      [synonym ISDA_Create_1_0 value partyA_name, partyB_name]
   person NaturalPerson (0..*) <"The person(s) who might be associated with the party as part of the execution, contract or legal document.">;
      [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value person]
   account Account (0..1) <"The account that might be associated with the party. At most one account can be specified, as it is expected that this information is used in the context of a contract or legal document where only one account per party can be associated with such object.">;
      [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0, ISDA_Create_1_0 value account]
}

Proposed:

type Party: "A class to specify a party, without a qualification as to whether this party is a legal entity or a natural person, although the model provides the ability to associate a person (or set of persons) to a party, which use case would imply that such party would be a legal entity (even if not formally specified as such)."
        [keyed]
        [synonym FpML_5_10, DTCC_11_0, DTCC_9_0 , CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value Party meta id maps 2]
    partyId string (1..*): <"The identifier associated with a party, e.g. the 20 digits LEI code.">
        [metadata scheme]
        [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value partyId meta partyIdScheme]
        [synonym DTCC_11_0, DTCC_9_0 value partyId maps 2 meta partyIdScheme]
        [synonym ISDA_Create_1_0 value id]
 
    name string (0..1): <"The party name">
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value partyName meta entityNameScheme]
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value entityName meta entityNameScheme]
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value entityName path referenceEntity meta entityNameScheme]
        [synonym CME_SubmissionIRS_1_0 value SID path Hdr]
        [synonym ISDA_Create_1_0 value name]
        [synonym ISDA_Create_1_0 value partyA_name, partyB_name]
 
   person NaturalPerson (0..*): <"The person(s) who might be associated with the party as part of the execution, contract or legal document">
        [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value person]
 
   account Account (0..1): <"The account that might be associated with the party. At most one account can be specified, as it is expected that this information is used in the context of a contract or legal document where only one account per party can be associated with such object.">
        [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0, ISDA_Create_1_0 value account]
  1. Move data rule into condition expression blocks inside Type-Body
  2. Support optional else block in if expression

Current:

class Contract key <"A class to specify a financial contract object...">
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, CME_ClearedConfirm_1_17 meta id path "trade"]
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, CME_ClearedConfirm_1_17, Rosetta_Workbench meta id]
{
    contractIdentifier Identifier (1..*) <"The identifier(s) that uniquely identify a contract...">;
        [synonym FpML_5_10, CME_SubmissionIRS_1_0 value partyTradeIdentifier path "trade.tradeHeader"]
    tradeDate TradeDate (1..1) <"The date on which the contract has been executed.">;
        partyRole PartyRole (0..*) <"The role(s) that party(ies) may have...">;
    ...
}
 
data rule Contract_hedgingParty <"FpML specifies that there cannot be more than 2 hedging parties.">
    when Contract -> partyRole -> role = PartyRoleEnum.HedgingParty
    then Contract -> partyRole -> role count <= 2

Proposed:

annotation keyed: <"Applies to classes. Indicates when a class can be referred to by other classes via an identifier">

type Contract: <"A class to specify a financial contract object...">
        [keyed]
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, CME_ClearedConfirm_1_17 meta id path trade]
        [synonym FpML_5_10, CME_SubmissionIRS_1_0, CME_ClearedConfirm_1_17, Rosetta_Workbench meta id]
    contractIdentifier Identifier (1..*): <"The identifier(s) that uniquely identify a contract...">
        [synonym FpML_5_10, CME_SubmissionIRS_1_0 value partyTradeIdentifier path trade.tradeHeader]
    tradeDate TradeDate (1..1): <"The date on which the contract has been executed.">
        ...
    condition Contract_hedgingParty: <"FpML specifies that there cannot be more than 2 hedging parties.">
         if partyRole -> role = PartyRoleEnum.HedgingParty 
         then partyRole -> role count <= 2
  1. Move choice rule into condition expression blocks inside Type-Body
  2. Support syntactic sugar to pass all Attributes/Inputs into a Function call when none specified

Current:

class SecurityValuationModel one of <"The security valuation model choice, which can either be based on nominal amount as for a bond, or on the number of contract units as for equity.">
{
    bondValuationModel BondValuationModel (0..1) <"The valuation model when the security is a bond.">;
    unitContractValuationModel UnitContractValuationModel (0..1) <"The valuation model when the security is a unit contract like equity.">;
}
 
class InitialMarginCalculation <"Defines the initial margin calculation applicable to a single piece of collateral.">
{
    marginRatio number (0..1) <"An element defining ...">;
        [synonym FpML_5_10 value marginRatio]
    marginRatioThreshold number (0..2) <"An element defining a margin ratio threshold...">;
        [synonym FpML_5_10 value marginRatioThreshold]
    haircut number (0..1) <"An element defining a haircut ...">;
        [synonym FpML_5_10 value haircut]
    ...
}
 
choice rule InitialMarginCalculation_choice
    for InitialMarginCalculation required choice between
    marginRatio and haircut

Proposed:

type SecurityValuationModel: <"The security valuation model choice, which can either be based on nominal amount as for a bond, or on the number of contract units as for equity.">
    bondValuationModel BondValuationModel (0..1): <"The valuation model when the security is a bond.">
    unitContractValuationModel UnitContractValuationModel (0..1): <"The valuation model when the security is a unit contract like equity.">
    condition: one of;  // one of - remains a language feature 
    

type InitialMarginCalculation: <"Defines the initial margin calculation applicable to a single piece of collateral.">
    marginRatio number (0..1): <"An element defining ...">
        [synonym FpML_5_10 value marginRatio]
    marginRatioThreshold number (0..2): <"An element defining a margin ratio threshold...">
        [synonym FpML_5_10 value marginRatioThreshold]
    haircut number (0..1): <"An element defining a haircut ...">
        [synonym FpML_5_10 value haircut]
        ...
    condition InitialMarginCalculation_choice_1: <"Replaces choice rule InitialMarginCalculation_choice">
        RequiredChoice( marginRatio, haircut );

func OptionalChoice: "For the set of inputs, at most 1 exists"
	[validation]
    inputs: inputs any (1..*)
    output: result boolean (1..1)

func RequiredChoice: "For the set of  inputs, exactly 1 exists"
	[validation]
    inputs: inputs any (1..*)
    output: result boolean (1..1)

Enum and Record Type examples to follow...

Function (data rule, choice rule, alias, one of and spec)

calculation, function, spec and alias are 4 language features that are all Functions

  • function is a function signature only i.e. function name, inputs and outputs
  • calculation is a function where the inputs are inferred for readability
  • alias is a function that takes an single object as input and outputs a child of that object
  • spec was recently introduced as a way to consolidate the above 3

Functions take the form:

'func' Name ('implements' [Function])? ':' Definition?
    Annotation*
    Input*
    Output*
    Alias*
    Condition*      
    Assignment*     
    Post-Condition* 

where:

  • Input

     'inputs' ':' 
     	Attribute+
    
  • Output

      'output' ':'
          Attribute
    
  • Alias: used as a bookmark for long Rosetta Paths (ie Contract -> product -> contractualProduct -> payout -> ... -> amount) and complex expressions

      'alias' Name ':' Definition?
          RosettaExpression
    
  • Assignment: used to build the output object

      'assign-output' AttributePath ':' Definition?
          RosettaExpression // Rosetta Expressions do not support assignment operations, hence the 
    
  • AttributePath refers to a reference to an attributes on a Rosetta element i.e. Contract -> product -> ... -> quantity

  • Post-Condition

      'post-condition' Name? ':' Definition?
          Annotation*
          RosettaExpression+
    

Key Actions with Examples:

  1. Migrate spec to func

Current:

spec NewContractFormationFromExecution <"Function specification to create a fully-formed contract following execution on a contractual product. The contract can optionally reference a further legal agreement (such as a CSA or a Master Confirmation).">:
	inputs:
		executionState ExecutionState (1..1)
		partyA Party (1..1)
		partyB Party (1..1)
		legalAgreement LegalAgreement (0..1)
		
	output:
		contractFormation ContractFormation (1..1)
	
	pre-condition <"Parties must be different, and match the contractual parties to the legal agreement when those exists, and the parties to the execution when those exist.">:
		partyA <> partyB;
		 if legalAgreement exists then
		 	legalAgreement -> contractualParty contains partyA and
		 	legalAgreement -> contractualParty contains partyB
		 else True;
		 if executionState -> execution -> party exists then 
		 	executionState -> execution -> party contains partyA and
		 	executionState -> execution -> party contains partyB
		 else True;
		 
	post-condition <"Before state must be the execution, and the contractual product in the after state must be the underlying product of the contract being formed.">:
		contractFormation -> before = executionState;
		
	post-condition <"When an overlaying legal agreement exists, the contract must reference it.">:
		if legalAgreement exists then contractFormation -> after -> contract -> documentation -> legalAgreement = legalAgreement else True;

Proposed:

func NewContractFormationFromExecution: <"Function specification to create a fully-formed contract following execution on a contractual product. The contract can optionally reference a further legal agreement (such as a CSA or a Master Confirmation).">
	inputs:
		executionState ExecutionState (1..1)
		partyA Party (1..1)
		partyB Party (1..1)
		legalAgreement LegalAgreement (0..1)
		
	output:
		contractFormation ContractFormation (1..1)
	
	pre-condition: <"Parties must be different, and match the contractual parties to the legal agreement when those exists, and the parties to the execution when those exist.">
		partyA <> partyB;
		 if legalAgreement exists then
		 	legalAgreement -> contractualParty contains partyA and
		 	legalAgreement -> contractualParty contains partyB;
		 if executionState -> execution -> party exists then 
		 	executionState -> execution -> party contains partyA and
		 	executionState -> execution -> party contains partyB;
		 
	assign-output contractFormation -> before: <"Before state must be the execution, and the contractual product in the after state must be the underlying product of the contract being formed.">
		executionState;
		
	assign-output contractFormation -> after -> contract -> documentation -> legalAgreement: <"When an overlaying legal agreement exists, the contract must reference it.">
		if legalAgreement exists then legalAgreement;  // implicitly else "nothing"
  1. Replace calculation, function with Functions.
  2. Introduce a concept of higher-order functions.
  3. Support resolving and invoking functions based on Enum values.

Current:

calculation FixedAmount <"2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount...">
{
    fixedAmount : calculationAmount * fixedRate * dayCountFraction
    
    where
        calculationAmount   : InterestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue
        fixedRate           : InterestRatePayout -> rateSpecification -> fixedRate -> initialValue
        dayCountFraction    : InterestRatePayout -> dayCountFraction
}

calculation DayCountFractionEnum.ACT_360 <"...">
{
	: daysInPeriod / 360
	
	where
		daysInPeriod <"Number of calendar in the calculation period">:
			CalculationPeriod( InterestRatePayout -> calculationPeriodDates ) -> daysInPeriod
}
 
function ResolveRateIndex( index FloatingRateIndexEnum ) <"The function to specify that...">
{
    rate number;
}

function CalculationPeriod( calculationPeriodDates CalculationPeriodDates ) <"...">
{
	startDate date;
	endDate date;
	daysInPeriod int;
	daysInLeapYearPeriod int;
	isFirstPeriod boolean;
	isLastPeriod boolean;
}

Proposed:

func FixedAmount: <"2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount...">
	inputs:
        interestRatePayout InterestRatePayout (1..1)
   
    output:
        fixedAmount number (1..1)

    alias calculationAmount: <"The calculation amount as extracted from the interest rate payout">
	    interestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue
          
    alias fixedRate: <"a shortcut from the Interest Rate Payout to the Fixed Rate">
        interestRatePayout -> rateSpecification -> fixedRate -> initialValue

    alias dayCountFraction: "..."  
        DayCountFraction( interestRatePayout, interestRatePayout -> dayCountFraction )

    assign-output fixedAmount: <"assigns the output 'fixedAmount' with the result of the mathematical operation">
        calculationAmount * fixedRate * dayCountFraction

// Defines DayCountFraction function. No assignments, first parameter is a dispatch enum, the second is the context object
//
func DayCountFraction: <"A description of inputs and outputs for all day count fraction calculations">
    inputs:
        interestRatePayout InterestRatePayout (1..1)
        dayCountFractionEnum DayCountFractionEnum (1..1)
        
    output:
        result number (1..1)

// implements DayCountFraction for enum value ACT_365. 
// In other words we "preset" dayCountFractionEnum DayCountFractionEnum (1..1) input with a concrete value
//
func DayCountFraction(dayCountFractionEnum: DayCountFractionEnum.ACT_365): <"An concrete specification of a Day Count Fraction calculation, where both inputs and output have been inhereted from its parent: the func DayCountFraction">
	alias daysInPeriod:
		CalculationPeriod( interestRatePayout -> calculationPeriodDates ) -> daysInPeriod
	assign-output result:
		daysInPeriod / 360

func ResolveRateIndex: <"The function to ...">
	inputs: index FloatingRateIndexEnum (1..1)
    output: rate number (1..1)

type CalculationPeriodResult: <"...">
	startDate date (1..1)
	endDate date  (1..1)
	daysInPeriod int  (1..1)
	daysInLeapYearPeriod int  (1..1)
	isFirstPeriod boolean  (1..1)
	isLastPeriod boolean  (1..1)

func CalculationPeriod: <"...">
	inputs: calculationPeriodDates CalculationPeriodDates (1..1)
	output: result CalculationPeriodResult (1..1) 

--- Alternative Proposal (not yet accepted): ---

func FixedAmount: "2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount..."
	inputs:
        interestRatePayout InterestRatePayout (1..1)
   
    output:
        fixedAmount number (1..1)

    alias calculationAmount: "The calculation amount as extracted from the interest rate payout"
	    interestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue
          
    alias fixedRate: "a shortcut from the Interest Rate Payout to the Fixed Rate"
        interestRatePayout -> rateSpecification -> fixedRate -> initialValue

    alias dayCountFraction: "..."
        interestRatePayout -> dayCountFraction func

    assign-output fixedAmount: "assigns the output 'fixedAmount' with the result of the mathematical operation"
        calculationAmount * fixedRate * dayCountFraction( interestRatePayout )

Notes on func FixedAmount

  • the func keyword in alias dayCountFraction resolves the function that is attached to the Enum's value
  • The data-type of alias dayCountFraction is function whose inputs and output are specified by func DayCountFraction
  • Scoping: an alias can be created on inputs or output
  • Scoping: a condition can reference only global elements, inputs and alias's based on inputs
  • Scoping: a post-condition can reference global elements, inputs, the output and any alias
  • Scoping: The name of the assign-output block should reference only the output
  • Scoping: The expression within the assign-output can reference global elements, inputs, the output and any alias
  • Validation: output is optional in the grammar but is mandatory for funcs that don't implement other funcs
  • Validation: when the func keyword is used to resolve a Function, check that DayCountFractionEnum is attached to a func and said func has at least 1 implementation
func DayCountFraction: "A description of inputs and outputs for all day count fraction calculations"
    [attached to DayCountFractionEnum]
    inputs:	
	    interestRatePayout InterestRatePayout (1..1)
	    
    output:	
	    result number (1..1)

func ACT_365 implements DayCountFraction : "An concrete specification of a Day Count Fraction calculation, where both inputs and output have been 'inhereted' from its parent: the func DayCountFraction"    
    alias daysInPeriod:
        CalculationPeriod( interestRatePayout -> calculationPeriodDates ) -> daysInPeriod
        
    assign-output result:
        daysInPeriod / 360

Notes on func DayCountFraction

  • The attached to Annotation states that this Function is associated with the Enum DayCountFractionEnum
  • Implicitly, all implementations of DayCountFraction will be attached to values on DayCountFractionEnum
  • Validation: each Enum type has only a single func attached.

Notes on func ACT_365

  • funcs can implement at most 1 other func
  • inputs and output are inherited from the parent with no overriding of inputs or outputs allowed
  • Validation: input and output definitions are not allowed
  • Validation: the func's name needs to be a value from the Enum specified in the annotation of the parent
  • Validation: for each enum value, only a single func is attached

--- End of Alternative proposal ---

  1. Replace alias with Functions

Current:

alias forwardFX
    ForwardPayout -> underlier -> singleUnderlier -> underlyingProduct -> foreignExchange

Proposed:

func ForwardFX:
        [alias]
    inputs: forwardPayout ForwardPayout (1..1)
    output: foreignExchange ForeignExchange (1..1)
    assign-output foreignExchange: forwardPayout -> underlier -> singleUnderlier -> underlyingProduct -> foreignExchange

// support for syntactic sugar?
//
alias forwardFX
	ForwardPayout -> underlier -> singleUnderlier -> underlyingProduct -> foreignExchange

Usage

Any Function invocation must be done by a Client, where a Client is someone or some system that makes use of the generated code. Functions can call other Functions

Annotation (replaces metadata, reference, scheme, key, synonym)

Annotations will be a new concept that represents non-core information. For example, the mandatory parts of Types are its name and attributes, therefore all other descriptors should be placed inside annotations. For Attributes, the name, type and cardinality are mandatory and so synonyms are represented in annotations.

Annotations can be defined in the language or in the grammar. Those defined in the language take the following form:

'annotation' Name Definition?
    Attribute*

For annotations defined in grammar, they can take on any form definable via the xText Grammar syntax.

Examples

Annotation usage take the following forms:

  1. Annotation - an annotation with attributes

     annotation metadata: "Example definition of an annotation type"
         scheme string (0..1)
         reference string (0..1)
     
     type Party: "..."
         partyId string (1..*): "..."
             [metadata scheme]
    
  2. Marker Annotation - an annotation with no attributes

     annotation keyed: "Indicates whether an object should support storage of a `global key`"
     
     type Party: "..."
         [keyed]
         partyId string (1..*): "..."
         name string (0..1): "..."
    
  3. Structured Annotation - where the strucutre of the annotation is defined in grammar

     type Party: "..."
         partyId string (1..*): "..."
             [synonym FpML_5_10 value partyId meta partyIdScheme]  // re-uses existing synonym grammar rules
    

Views

We recognise that a Rosetta reader and a Rosetta editor may want different views of the DSL and so we wish to support in Rosetta Core the ability to switch between "views". When writing Rosetta, the writer needs to be specific about type and cardinality, i.e. when passing object references into functions or nesting function calls.

Everything that is between square brackets is an annotation that provides additional information and can be folded (hidden) in the editor. Taking an example of the data type Party from CDM, the example "reader" view should look like the below

Before:

 class Party key <"A class to specify a party, without a qualification as to whether this party is a legal entity or a natural person, although the model provides the ability to associate a person (or set of persons) to a party, which use case would imply that such party would be a legal entity (even if not formally specified as such). ">
   [synonym FpML_5_10, DTCC_11_0, DTCC_9_0 , CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value Party meta id maps 2]
{
   partyId string (1..*) scheme <"The identifier associated with a party, e.g. the 20 digits LEI code.">;
      [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value partyId meta partyIdScheme]
      [synonym DTCC_11_0, DTCC_9_0 value partyId maps 2 meta partyIdScheme]
      [synonym ISDA_Create_1_0 value id]
   name string (0..1) scheme <"The party name.">;
      [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value partyName meta entityNameScheme]
      [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value entityName meta entityNameScheme]
      [synonym FpML_5_10, CME_SubmissionIRS_1_0, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17 value entityName path "referenceEntity" meta entityNameScheme]
      [synonym CME_SubmissionIRS_1_0 value SID path "Hdr"]
      [synonym ISDA_Create_1_0 value name]
      [synonym ISDA_Create_1_0 value partyA_name, partyB_name]
   person NaturalPerson (0..*) <"The person(s) who might be associated with the party as part of the execution, contract or legal document.">;
      [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0 value person]
   account Account (0..1) <"The account that might be associated with the party. At most one account can be specified, as it is expected that this information is used in the context of a contract or legal document where only one account per party can be associated with such object.">;
      [synonym FpML_5_10, DTCC_11_0, DTCC_9_0, CME_ClearedConfirm_1_17, CME_SubmissionIRS_1_0, ISDA_Create_1_0 value account]
}

Proposed

Party: "A class to specify a party..."
  - partyId : "The identifier associated with a party, e.g. the 20 digits LEI code."
  - name    : "The party name"
  - person  : "The person(s) who might be associated with the party as part of the execution, contract or legal document"
  - account : "The account that might be associated with the party. At most one account can be specified, as it is expected that this information is used in the context of a contract or legal document where only one account per party can be associated with such object."
  - 

An example of the function FixedAmount from CDM in the "reader" view:

Current:

calculation FixedAmount <"2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount...">
{
    fixedAmount : calculationAmount * fixedRate * dayCountFraction
    
    where
        calculationAmount   : InterestRatePayout -> quantity -> notionalSchedule -> notionalStepSchedule -> initialValue
        fixedRate           : InterestRatePayout -> rateSpecification -> fixedRate -> initialValue
        dayCountFraction    : InterestRatePayout -> dayCountFraction
}

Proposed

FixedAmount: "2006 ISDA Definition Article 5 Section 5.1. Calculation of a Fixed Amount..."
    = calculationAmount * fixedRate * dayCountFraction
 
    where:
        calculationAmount:  "The quantity or notional used to compute the Fixed Amount."
        fixedRate:          "The observed rate."
        dayCountFraction:   "The Day Count Convention used to count the number of days within a period."

An example of how choice rules in "reader" view

type InitialMarginCalculation: <"Defines the initial margin calculation applicable to a single piece of collateral.">
 - marginRatio: <"An element defining ...">
 - marginRatioThreshold: <"An element defining a margin ratio threshold...">
 - haircut: <"An element defining a haircut ...">
 - InitialMarginCalculation_choice: <"Replaces choice rule InitialMarginCalculation_choice">
        RequiredChoice between marginRatio and haircut

Digital Regulatory Reporting

Digital Regulatory Reporting is an extension case to core CDM modelling (Products and Events) and will be addressed once the above work has come reached a conclusion.

There are 4 aspects to the report:

  1. When to report (daily)
  2. If the event is eligible for reporting
  3. Define the fields to be reported from the cdm model classes
  4. Define the mappings to the output reporting format (e.g. ISO 20022)

This is the way we currently can define regulatory context. We define a regulatoryRegime, mandate and segment and combine them to reference a provision.

regulatoryRegime ESMA_MiFID_I
regulatoryRegime ESMA_MiFID_II
regulatoryRegime ESMA_MiFIR
regulatoryRegime CFTC_DFA
 
mandate regulation
mandate specification
mandate guideline
 
segment article
segment whereas
segment annex
segment section
segment field
 
reportingStandard ISO_20022
 
// Example usage (you can annotate any class, attribute or rule)
// [regulatoryReference ESMA_MiFIR regulation "RTS 22" article "2" provision "Do what I say, not what I do."]
 

Proposed syntax example:

MifidIITransactionReport
  [Report]
  reported daily for T-1
  when ESMA_MiFIR regulation "RTS 22" applies
  using reportingStandard ISO_20022
  report fields
     // The fields need to reference two rules. One to get data from and one to project data to.
     // To start with - we can just use the entire path, then refactor if/when it gets more complex.
     - reportStatus from Event -> xxx -> yyy to ISO_20022 -> xxx
     - price from Event -> zzz -> ccc to ISO_20022 -> xxx
     - txid from Event -> vvv -> ddd to ISO_20022 -> xxx
 

RTS_22_Is_Transaction: "When eligible for rts 22"
        [Eligibility]
        [regulatoryReference ESMA_MiFIR regulation "RTS 22" article "2" provision "For the purposes of Article 26 of Regulation (EU) No 600/2014, the conclusion of an acquisition or disposal of a financial instrument referred to in Article 26(2) of Regulation (EU) No 600/2014 shall constitute a transaction."]
  
   for Event
    primitive ->  inception -> must exist
          or
    primitive ->  termination -> must exist