Table of Contents

Class MBSFixedRateBond

Namespace
NanoQL.Extensions.Instruments
Assembly
NanoQL.Extensions.dll

A fixed-rate mortgage pass-through with prepayment: a pool of level-payment mortgages at a weighted-average coupon (WAC), whose expected principal and pass-through interest reach the holder each period, the prepayments as a model gives them.

public sealed class MBSFixedRateBond : Bond
Inheritance
MBSFixedRateBond
Inherited Members

Remarks

Each period pays a FixedRateCoupon at the pass-through rate on the pool's balance at the period's start, its scheduled principal (AmortizingPayment), the level-payment schedule's at the WAC scaled to the balance, and its prepayment (VoluntaryPrepay), the balance after the scheduled principal times the period's single monthly mortality (SMM); the bond's leg holds them in that order on each date, as a bond's redemptions follow its coupons. The model reads the pool's age: a date of the bond's schedule plus the original length less the remaining one, so a seasoned pool starts its PSA ramp part way.

Ported from QLNet, which derives it from its AmortizingFixedRateBond; here it builds on Bond, its schedule and the level-payment notionals from AmortizingFixedRateBondFunctions. Its departures from QLNet: the notional schedule and the redemptions are the pool's expected ones, so the yields price the pool's balance at the settlement, where QLNet's read the level-payment schedule's; the flows pay on the period ends adjusted by the payment convention on the calendar, which QLNet ignores; a period of a frequency other than monthly survives the product of its months' prepayments (or, for a period counted in weeks or days, its share of a month's), where QLNet applies one month's SMM a period; the monthly yield's bracket widens past QLNet's [0, 1]% a month when that doesn't hold the root; and the yields refuse a pool fully paid off at the settlement, where QLNet's throw on its stale notional, and price the settlement date's flows as paid whatever the context's settings, where QLNet's read them. MonthlyYield(EvaluationContext) keeps QLNet's whole periods with no delay; Yield(double, int, EvaluationContext, Date?) and Price(double, int, EvaluationContext, Date?) are SIFMA's standard yield and price.

Constructors

MBSFixedRateBond(int, Calendar?, double, Date, Period, Period, Frequency, double, double, DayCounter, IPrepayModel?, BusinessDayConvention, Date?)

Initializes a new instance of the MBSFixedRateBond class.

public MBSFixedRateBond(int settlementDays, Calendar? calendar, double faceAmount, Date startDate, Period bondTenor, Period originalLength, Frequency sinkingFrequency, double wacRate, double passThroughRate, DayCounter accrualDayCounter, IPrepayModel? prepayModel, BusinessDayConvention paymentConvention = BusinessDayConvention.Following, Date? issueDate = null)

Parameters

settlementDays int

The settlement days.

calendar Calendar

The calendar of the settlement and the payment dates, or null, QuantLib's empty calendar, which takes only an Unadjusted payment convention.

faceAmount double

The pool's balance at the start date.

startDate Date

The start date of the bond's first period.

bondTenor Period

The remaining term, the bond's length.

originalLength Period

The loans' original term: the pool's age is it less the remaining term.

sinkingFrequency Frequency

The payment frequency.

wacRate double

The weighted-average coupon of the loans, which sets the scheduled principal.

passThroughRate double

The rate paid to the holder on the pool's balance.

accrualDayCounter DayCounter

The pass-through coupons' day counter.

prepayModel IPrepayModel

The prepayment model, or null for none.

paymentConvention BusinessDayConvention

The convention adjusting the payment dates on the calendar.

issueDate Date?

The issue date, or null for none.

Exceptions

ArgumentNullException

accrualDayCounter is null.

ArgumentOutOfRangeException

settlementDays is negative, or paymentConvention isn't a member of its type.

ArgumentException

The frequency or the tenor isn't one the level-payment schedule takes (SinkingNotionals(Period, Frequency, double, double)).

NanoQLException

The calendar is null and the payment convention adjusts.

Properties

BondFactors

Gets the level-payment schedule's factors: its notionals over the first, one a date of the bond's schedule, the last 0.

public ImmutableArray<double> BondFactors { get; }

Property Value

ImmutableArray<double>

DayCounter

Gets the pass-through coupons' day counter.

public DayCounter DayCounter { get; }

Property Value

DayCounter

ExpectedCashflows

Gets the expected cash flows: each period's pass-through coupon, scheduled principal and prepayment, the bond's own leg.

public ImmutableArray<CashFlow> ExpectedCashflows { get; }

Property Value

ImmutableArray<CashFlow>

Frequency

Gets the payment frequency.

public Frequency Frequency { get; }

Property Value

Frequency

Methods

BondEquivalentYield(EvaluationContext)

The bond-equivalent yield of MonthlyYield(EvaluationContext), its semi-annual equivalent, as SIFMA converts a monthly yield: 2 ((1 + y)^6 − 1), or for a pool of another frequency 2 ((1 + y)^(f/2) − 1) on its yield per period.

public double BondEquivalentYield(EvaluationContext context)

Parameters

context EvaluationContext

The evaluation context, whose evaluation date sets the settlement date.

Returns

double

The yield, a fraction a year, compounded semi-annually.

Exceptions

ArgumentNullException

context is null.

ArgumentException

The pool is fully paid off at the settlement date.

NanoQLException

The solver finds no root.

MonthlyYield(EvaluationContext)

The monthly yield at par, QLNet's: the rate per month at which the expected flows after the settlement date, discounted by whole periods per payment date with no delay, are worth the pool's balance at the settlement date.

public double MonthlyYield(EvaluationContext context)

Parameters

context EvaluationContext

The evaluation context, whose evaluation date sets the settlement date.

Returns

double

The yield per month, a fraction.

Remarks

The solve is QLNet's: Brent from a guess of 0.02% a month over [0, 1]% a month, to 1e-10, in 100 evaluations; where that range doesn't bracket the root, Brent's step search from the same guess, above −100% a month. On a pool of another frequency the root is a yield per period, and the result its monthly equivalent. The settlement date's flows count as paid, as the balance takes them, whatever the context's IncludeReferenceDateEvents and IncludeTodaysCashFlows.

Exceptions

ArgumentNullException

context is null.

ArgumentException

The pool is fully paid off at the settlement date.

NanoQLException

The solver finds no root.

Price(double, int, EvaluationContext, Date?)

SIFMA's standard price at a yield (Uniform Practices, Chapter SF, SF-48): the expected flows' value at the bond-equivalent yield, less the accrued interest, per 100 of the balance at the start of the period holding the settlement, as Yield(double, int, EvaluationContext, Date?) reads them.

public double Price(double yield, int delayDays, EvaluationContext context, Date? settlementDate = null)

Parameters

yield double

The bond-equivalent yield, a fraction a year, compounded semi-annually.

delayDays int

The actual delay, in days from each period's end to its payment (SF-44).

context EvaluationContext

The evaluation context, whose evaluation date sets the settlement date.

settlementDate Date?

The settlement date; the bond's when null.

Returns

double

The clean price per 100 of the current balance.

Exceptions

ArgumentNullException

context is null.

ArgumentOutOfRangeException

delayDays is negative.

ArgumentException

The pool is fully paid off at the settlement date.

SMM(Date)

The prepayment model's single monthly mortality at a date plus the pool's age, QLNet's function. It isn't always a period's SMM: the flows read the model at the start's anniversaries, the start plus the age plus the months before the period, which a schedule date plus the age misses by a month from a start after the 28th, and a period of another frequency survives the product of its months' prepayments.

public double SMM(Date d)

Parameters

d Date

The date, before the pool's age is added.

Returns

double

The model's SMM at d plus the pool's age; 0 with no model.

Yield(double, int, EvaluationContext, Date?)

SIFMA's standard yield (Uniform Practices, Chapter SF, SF-48): the bond-equivalent yield Y at which the expected flows due after the settlement, each discounted by (1 + Y/2)^(−2T), are worth the dollar price.

public double Yield(double cleanPrice, int delayDays, EvaluationContext context, Date? settlementDate = null)

Parameters

cleanPrice double

The price per 100 of the current balance, without accrued interest.

delayDays int

The actual delay, in days from each period's end to its payment (SF-44).

context EvaluationContext

The evaluation context, whose evaluation date sets the settlement date.

settlementDate Date?

The settlement date; the bond's when null.

Returns

double

The yield, a fraction a year, compounded semi-annually.

Remarks

The dollar price is the clean price per 100 of the balance at the start of the period holding the settlement, times that balance, plus the interest accrued at the pass-through rate from that period's start (SF-46). T is in years on SIFMA's 30/360 (SF-44), from the settlement to each period's unadjusted end, plus the delay days, so the payment convention doesn't enter; SIFMA's yield is semi-annual whatever the pool's frequency.

Exceptions

ArgumentNullException

context is null.

ArgumentOutOfRangeException

delayDays is negative.

ArgumentException

The pool is fully paid off at the settlement date.

NanoQLException

The solver finds no root.