Lesson 02 · 6 min
Rates: the Swap Engine
Calculation periods, resets, payments, and day counts: the three date machines behind every swap leg.
The deal on the desk
Pershing Square pays Goldman Sachs 3.5% fixed on USD 10,000,000 for five years; Goldman pays back SOFR plus 50 basis points. Two interestRatePayout legs with mirrored payerReceiver, exactly as the protocol predicts. What Foundations skipped is the machinery inside each leg: how the model knows which days to accrue over, when to observe SOFR, and when cash actually moves. Three date machines, one engine.
calculationPeriodDates carves the calendar
From
effectiveDatetoterminationDate, acalculationPeriodFrequency(here 3M) slices the life of the leg into accrual periods. Everything else hangs off these slices.resetDates observes, paymentDates pays
The floating leg needs a rate observation per period:
resetDatessays when to look.paymentDatessays when cash moves, withpayRelativeToanchoring payments to period ends here. Observation and payment are separate machines on purpose.dayCountFraction prices the slice
A period is dates; interest needs a year fraction.
ACT/360,30/360, and friends are competing conventions for that conversion, so the model makes the choice explicit on the leg.rateSpecification is the fixed-or-floating fork
A three-way choice: fixed, floating, or inflation. Which branch is populated is what the swap qualifier reads to tell the legs apart.
Inside the floating leg
Here is Goldman's leg, trimmed from a payload that runs against the real qualifier. Note the RateSpecification choice picking its floating branch: rateOption names the index to observe, and spreadSchedule adds the 50 basis points on top.
{ "payerReceiver": { "payer": "Party2", "receiver": "Party1" }, "rateSpecification": { "floatingRateSpecification": { "rateOption": { "value": "USD-SOFR" }, "spreadSchedule": { "price": { "value": 0.005 } } } }, "dayCountFraction": "ACT/360", "calculationPeriodDates": { "effectiveDate": { "adjustableDate": { "unadjustedDate": "2026-04-17" } }, "terminationDate": { "adjustableDate": { "unadjustedDate": "2031-04-17" } }, "calculationPeriodFrequency": { "periodMultiplier": 3, "period": "M", "rollConvention": "17" } }, "paymentDates": { "paymentFrequency": { "periodMultiplier": 3, "period": "M" }, "payRelativeTo": "CalculationPeriodEndDate" }, "priceQuantity": { "resolvedQuantity": { "value": 10000000, "unit": { "currency": "USD" } } }}
fixedRateSpecification carrying a rateSchedule priced at 0.035. Same dates, same day count, mirrored payerReceiver.One subtlety worth respecting: real calendars fight back. Period boundaries can land on weekends, so calculationPeriodDatesAdjustments carries a business day convention like MODFOLLOWING and the business centers to check, and the roll convention pins the day each period turns over. Determinism is the goal: both parties can regenerate the exact same schedule from the same data.
From two legs to a name
Run the protocol: two interestRatePayout legs, one fixed branch, one floating branch, nothing else. Qualify_InterestRate_IRSwap_FixedFloat pattern-matches exactly that and the product earns its name. Siblings cover the variations: an overnight-indexed version, a zero coupon version, basis swaps for float-versus-float. Nobody declares "this is a swap"; the legs do.
01Which machine decides when cash actually moves?