Lesson 03 · 5 min

The Tradable Product

Products are compositions, not labels. Describe the legs and the classification follows.

Products are compositions, not labels

Most systems treat "interest rate swap" as a product code: a label someone picks from a dropdown, with the real meaning buried in convention. The CDM turns this inside out. A product is defined by what it's made of. Describe the legs, and the classification follows from the data itself.

Key ideas
  • EconomicTerms is the contract's engine room

    Effective and termination dates, date adjustments, and the heart of it: a list of payout legs.

  • Payouts are the building blocks

    An InterestRatePayout pays interest, an OptionPayout grants a right, a PerformancePayout tracks return. Combine them and you have described a product. (The next lesson tours the family.)

  • TradableProduct = product + size + parties

    The product alone is abstract. TradableProduct binds it to tradeLot (how much, at what price) and exactly two counterparty roles.

  • Classification is computed

    Qualification functions inspect the composition and derive names like "InterestRate_IRSwap_FixedFloat". Nobody types the product name in.

TradableProducttradeLotTradeLot · 1..*productNonTransferableProductcounterpartyCounterparty · 2..2economicTermsEconomicTerms · 1..1payout · 1..*InterestRatePayout, OptionPayout, …how much, at what pricewho plays each rolethe legs ARE the product

Reading the tree

Start at TradableProduct. Its product field holds a NonTransferableProduct with identifiers, taxonomy, and one required EconomicTerms. Inside that, the payout list (cardinality 1..*) carries the legs. A fixed-versus-floating swap is simply two InterestRatePayout legs: one with a fixed rate specification, one with a floating rate.

{} economicTerms, fixed/float swap, trimmed
{  "effectiveDate": {    "adjustableDate": {      "unadjustedDate": "2026-06-15"    }  },  "terminationDate": {    "adjustableDate": {      "unadjustedDate": "2031-06-15"    }  },  "payout": [    {      "interestRatePayout": {        "payerReceiver": {          "payer": "Party1",          "receiver": "Party2"        },        "rateSpecification": {          "fixedRateSpecification": {            "rateSchedule": {              "price": {                "value": 0.0425              }            }          }        },        "dayCountFraction": "30E/360"      }    },    {      "interestRatePayout": {        "payerReceiver": {          "payer": "Party2",          "receiver": "Party1"        },        "rateSpecification": {          "floatingRateSpecification": {            "rateOption": {              "floatingRateIndex": "USD-SOFR-OIS Compound"            }          }        },        "dayCountFraction": "ACT/360"      }    }  ]}
Two legs, mirrored payerReceiver roles, one fixed and one floating rateSpecification. That composition is the definition of a fixed/float swap, and it's exactly what the qualifier checks.
Try itOpen Qualify_InterestRate_IRSwap_FixedFloat in the Playground (it opens in a new tab) and run the bundled samples. You'll see the composition rules from this lesson checked live, predicate by predicate.
◆ Checkpoint

01In the CDM, what makes a product an interest rate swap?

1 / 3