Skip to main content
CFDL

Credit: Fannie Mae REMIC with a stripped coupon, at six prepayment speeds

Security Group 3 of a Fannie Mae REMIC: a seasoned mortgage pool passing through to a single class, with the coupon stripped between it and an interest-only class that carries no principal.

Every number below is checked against an independent reference implementation on every commit — period by period, and on each metric, inside a declared tolerance. See benchmark methodology.

The case

Fannie Mae REMIC Trust 2019-2 divides $307,727,958 across three groups. Group 3 is $148,372,434 of Fannie Mae mortgage-backed securities, and its priority of payments is a single line:

The Group 3 Principal Distribution Amount to AB until retired.

Which makes it sound like nothing to model. The interest is where the deal is.

The pool passes through at 5.00%. Class AB takes 3.25% of that, and the remaining 1.75% is sold separately as Class IO — an interest-only class with no principal balance at all, entitled instead to 5.00% of a notional balance set at 35.0000000674% of AB's. The two reconstruct the pass-through rate:

3.25%  +  0.350000000674 x 5.00%  =  5.00000000337%

An investor in IO owns a slice of a coupon and nothing else. Their position shrinks as AB amortizes, they receive not one dollar of principal, and if the loans prepay quickly they lose most of what they paid.

The reference

The Prospectus Supplement dated 24 January 2019, page S-14, which publishes for Classes AB and IO the percentage of the original balance outstanding after each January's distribution for thirty years, at seven prepayment speeds, with a weighted average life for each. See SOURCE.md.

This case takes the 198% PSA column, the pricing speed.

The same supplement publishes, on pages S-10 and S-11, the pre-tax yield of Class IO at an assumed price of 19.25% of its original notional balance, at seven prepayment speeds, and the speed at which that yield is zero. The case asserts those too.

Provenance. The expectations are taken from an independent published reference, cited above. The source is not committed with the case; a reader checks the asserted figures against the published document itself.

What it exercises

Packcredit
Contract typescredit.loan; credit.note for Class AB
Language featurestwo waterfalls over one collateral, one for principal and one for interest; entity fields carrying class balances; a class's yield at a price, yield over the interest the waterfall pays it, with the price an assumption
ConventionsPSA on a pool seasoned past the ramp, a servicing and guaranty strip, a stripped coupon, a notional interest-only class

A coupon is stripped. Three rates are in play at once and none of them is the mortgage rate:

  • the loans carry a 5.451% weighted average coupon;
  • 0.451% is the servicing and guaranty strip, carried as servicing_fee, so what reaches the trust is 5.00% exactly;
  • that 5.00% is then split 3.25% / 1.75% between a principal class and a notional one.

The interest waterfall is the test. It declares a residual step, and if the strip is right that step takes nothing:

pay ab_interest to party.ab_holders = asset.ab.balance * (0.0325 / 12.0)
pay io_interest to party.io_holders = asset.io.balance * (0.05 / 12.0)
pay residual    to party.residual   = remaining

The residual is zero in all 361 periods, to ten decimal places.

A note on why the class balances are fields at all. AB is a pass-through, so its balance is the pool's, and IO's is a fixed fraction of AB's — neither carries state of its own, and neither is copied. The field says what the class is (next prev.asset.pool.balance) and derives the number. That the balances land one period behind the distributions is not a workaround here but the deal's own convention: the supplement strikes interest on "the outstanding balance of that Certificate immediately prior to that Distribution Date", which is precisely the number these fields hold.

The result

Worst disagreement 0.3640 percentage points across 60 published balance cells, for Class AB and the interest-only class (180 values asserted in all), against a floor of 0.5 set by the table's whole-percent rounding.

Decrement, worst / mean0.3640 pp / 0.0841 pp
Informative cells (published value neither 0 nor 100)14 of 30
Class AB weighted average life4.6950, published 4.7
Residual to Classes R and RL0.0000000000, every period
Principal returned to AB148,372,434.00 against an original of 148,372,434

Over the 14 informative cells the mean error is 0.1803 pp — the signature of the issuer's rounding and nothing else.

The interest legs are asserted too, and they are external rather than model output: a published balance multiplied by a coupon stated on the cover. Their tolerance is the balance band carried through the coupon.

The class's weighted average life is folded from the principal the waterfall pays it (wal) and asserted at ±0.05, the print floor of a figure published to one decimal. Class AB is a note of the trust, and its principal step is bound to it, so the life counts actual days over 365 from the note's term to each distribution on the 25th, the way the supplement measures it. The note's term opens on 1 February 2019, the first period boundary, two days after settlement, a difference of 0.005 years against a figure published to a tenth.

The supplement's other columns are scenarios of this case, each varying the one term that differs — the prepayment speed — and asserting its own decrement column and class life from its own file:

speedasserted cellsworst balance, ppClass AB lifepublished
100% PSA1800.4146.09776.1
300% PSA1750.4833.66823.7
400% PSA1700.4752.94602.9
700% PSA1500.4271.69201.7
1000% PSA1350.4551.06091.1

Every balance sits inside the half-percent floor and every life inside the print floor of 0.05.

The yield table. The supplement assumes Class IO is bought at 19.25% of its original notional, excluding accrued interest, and publishes its pre-tax bond-equivalent yield at seven speeds. The model states the price as an assumption, adds the 29 days of accrued interest a 30 January settlement carries on a 30/360 basis, and solves the yield over the interest the waterfall pays the class:

assume io_price = 0.1925
metric io_outlay    = asset.io.original_balance * (inputs.io_price + 0.05 * 29.0 / 360.0)
metric io_yield     = yield("g3.interest.io_interest", metric.io_outlay, parse_date("2019-01-30"))
metric io_yield_bey = 2.0 * ((1.0 + metric.io_yield) ^ 0.5 - 1.0)
speedsolved yieldpublished
50% PSA14.99%15.0%
100% PSA11.71%11.7%
198% PSA5.12%5.1%
272% PSA0.00%0%, the published zero-yield speed
300% PSA(1.97)%(2.0)%
400% PSA(9.20)%(9.2)%
700% PSA(32.83)%(32.9)%
1000% PSA(60.61)%(60.6)%

Each is asserted within 0.001, the print floor of a figure published to a tenth of a percent. The worst gap is 0.07 points at 700% PSA, where the class has lost a third of what it cost. The two speeds the decrement table does not print, 50% and 272%, are scenarios that assert the yield alone. The 0% PSA column ships as its own case (fnma_remic_2019_2_g3_psa000): the supplement prepares it on a different collateral assumption, a 360-month original and remaining term at 7.50%, so it is a different pool rather than a different speed.

The delta

Group 3 of three. Groups 1 and 2 are Structured Collateral: their assets are seventeen tranches of other Fannie Mae REMICs issued between 2002 and 2006. The instrument is fully specified for those groups too — one line each, the same as this one — but the cash arriving at them is another instrument's output, and reproducing the published tables would need those seventeen deals' own collateral. That is a compositional boundary, not a gap in this document, and it is why only Group 3 is here.

Seven speeds, one model. What the seven columns prove together is stronger than any one alone: a convention error in the prepayment curve, the seasoning ramp or the payment timing that hides under one column's whole-percent rounding has to hide under all seven columns and seven published lives simultaneously.

The outlay's date. The supplement discounts to a settlement on 30 January 2019, and the yield's outlay sits on that date, two days before the model's first period opens, with each distribution on its 25th. The gap in the yield column is the rounding of a figure published to a tenth.

No losses. Fannie Mae guarantees timely payment of principal and interest, so the collateral cannot default in a way the classes would see.

Seasoned past the ramp. Weighted average loan age is 175 months, so 198% PSA is a flat 11.88% CPR in every period. The ramp is written out in full anyway — the model should say the pool prepays at 198% PSA, not at 11.88% CPR, because the second is a consequence of the first and stops being true if the seasoning changes.

model.total is a regression anchor from this model. Every other assertion is a published figure or derived from one.

Run configuration

{
  "deterministic": {
    "annual_discount_rate": 0.03
  },
  "scenarios": {
    "psa050": {
      "parameters": {
        "inputs.psa": 0.5
      }
    },
    "psa100": {
      "parameters": {
        "inputs.psa": 1.0
      }
    },
    "psa300": {
      "parameters": {
        "inputs.psa": 3.0
      }
    },
    "psa400": {
      "parameters": {
        "inputs.psa": 4.0
      }
    },
    "psa700": {
      "parameters": {
        "inputs.psa": 7.0
      }
    },
    "psa1000": {
      "parameters": {
        "inputs.psa": 10.0
      }
    },
    "psa272": {
      "parameters": {
        "inputs.psa": 2.72
      }
    }
  }
}

Verified results

Checked period by period: 6 series across 60 periods — 180 values in all, each within the tolerance shown.

  • domain.credit.principal_paid_to_date — within ±741862.17
  • asset.ab.balance — within ±741862.17
  • asset.io.balance — within ±259651.76
  • g3.interest.ab_interest — within ±2009.21
  • g3.interest.io_interest — within ±1081.88
  • g3.interest.residual — within ±0.01

Checked per scenario, each a full run under its own parameters:

Scenariometric.io_yield_beymodel.totalmetric.ab_wal
psa0500.15——
psa1000.117193,718,881.036.1
psa300-0.02175,695,352.453.7
psa400-0.092170,337,628.952.9
psa700-0.329161,035,147.511.7
psa1000-0.606156,352,857.61.1
psa2720——

Summary metrics for the base run:

MetricValueTolerance
domain.credit.principal148,372,434±0.01
model.total183,313,276.29±1
domain.credit.wal_years4.7±0.07
metric.ab_wal4.7±0.05
metric.io_yield_bey0.051±0.001