Bonds and fixed income¶
A deployment holds fixed income: bonds, agency pools, TBAs, agency CMO
tranches and certificates of deposit. Each is a record under its own
template, held in face, priced per 100 of face and serviced in the
book of record. Every operation and record here
is preview.
The templates¶
| Template | What it describes |
|---|---|
bond |
A government, agency, supranational, municipal or corporate bond: its issuer, seniority, coupon (fixed, floating, zero or step) and frequency, day count and conventions, its dates and record dates, denominations, a floater's terms, its call, put and sinking-fund schedules, and what it was stripped from |
mbs_pool |
An agency pass-through pool: its agency, program, pass-through rate, payment day and payment delay |
tba |
A to-be-announced agency trade: its agency, program, coupon and settlement month |
cmo_tranche |
An agency REMIC class: its interest types (fixed, floating, inverse floating, interest only, principal only, Z) and principal types |
certificate_of_deposit |
A bank's CD: the bank as issuer, whether the deposit is insured, and its survivor option |
A bond known only by its CUSIP or ISIN stays a deployment-local LCL-
record, its CUSIP never sent to the platform: see
One ID per instrument. A record lists what it lacks until it is
complete.
Bond terms and offered terms¶
A record's terms are its template's fields. A plugin holding reference
offers the terms its source states for a security the deployment
lists, field by field, with
offer_template_fields:
under the bond template a bond's coupon, dates, day count and issuer (by
its LEI), and under certificate_of_deposit a CD's. An offer is kept with
its source and time beside the record. It never overwrites a value a
person set, and a person can see each offer on the instrument's record and
choose it.
A bond's offered terms come as one bond value per offering plugin: the
terms the record holds with that source's terms laid over them, shown on
the Instruments page in their coupon and maturity. Accept offered
values takes it whole, with its source, and the terms are then in force
on the record (sourced under its bond field), the change in the record's
history. Terms on a record whose type is not a bond, a date that is no
plain date, or a decimal out of range are refused naming the field.
dashboard__complete_instruments takes bond as the read answers it.
An agency's disclosure plugin offers a pool's or a tranche's terms from the same files it reads factors from.
Money: face, percent of par and the dollar price¶
- A debt record's quantity is face, and its price is per 100 of face.
- A fill's price is the dollar price per 100 of face (
Execution.price), always. A yield or a spread the source quoted travels beside it as it was quoted, never in its place (price_basis,yield). - Cash is face times price times 0.01, exact: percent of par.
- Accrued interest moves cash. An allocation's accrued is its own cash line at booking, so settlement is principal plus accrued. A coupon received is two cash lines: the purchased accrued returned, and the income.
- Accrual uses FIX's day counts. A day count the engine does not
compute is named, never guessed:
NOT_EVALUATED_REASON_NOT_SUPPORTED. - A quoted yield may leave its day count unstated. Where the source
quotes a yield without one, the price, trade or quote keeps it as quoted
(
debt.quoted_yield(...)with noday_count), and the analytics component never computes with it. A day count that is not one of the defined ones is still refused.
The lake's prices take the same bases: Price, Trade and Quote carry a
PriceBasis of percent of par, yield or spread (with the benchmark a
spread is over), and a capped size, such as "5MM+", is recorded as at
least that size (Trade.quantity_capped, Quote.bid_size_capped).
The factor is the security's¶
A pool's or a tranche's outstanding principal is its original face times its factor, which its agency publishes each month. In Open Meridian the factor belongs to the security, not to a fill:
- An agency's data plugin records each held pool's or class's factor
as published, one row per pool or class and factor month, with its record
and payment dates and, where the disclosure states them, the pool's WAC,
WAM and WALA (
record_factors). Factors are recorded only for the records the deployment names. A corrected file's factor is the row's next version. - A fill states original face. The book takes the factor published for
the fill's settlement month (the row whose factor month is the one before
the month it settles in) and keeps it with the fill as
Execution.factor_taken, pricing its cash, its lots and any later relief. factor_usedis only an override, final, changed only by a correction of the fill. A booking whose fills state conflicting overrides is refused, namingfactor_used.- A paydown relieves each lot's cost by its cost times the fall over the prior factor. A split cost is exact where it ends within the cost's places, and half-even at them otherwise, the remainder kept in the lot or given to the last part, so no cost is made or lost.
A fill before its factor¶
A fill can settle in a month whose factor is not published yet. Then:
- It books provisionally. The latest published factor prices it, and
the fill and its lots say which month's factor they await
(
Execution.factor_month_awaited,Lot.factor_month_awaited). - It is revised when the factor arrives. On publication, or on a
republication, the book writes its own record of the revision
(
LIFECYCLE_EVENT_KIND_FACTOR_REVISION): the old and new factor, thecashandcost_change, and theexecution_idit revises. Before the fill's settlement date the revision is pending, and settles with the fill. - After settlement, a claim is opened. A revision arriving after the
settlement date is held as an open claim
(
LIFECYCLE_EVENT_STATE_CLAIM_OPEN), the money difference to be collected or paid, until a person marks it settled. This follows the market's own practice of settling on the last available factor and correcting once the current one is published.
A fill whose settlement date is not yet known keeps its security and cash pending, dated nothing, until a correction states the date.
Rounding. A pool's or a tranche's fill's cash rounds to the cent, half-even; its lot's cost is that rounded cash; a provisional amount and each revision's differences round alike.
In force¶
In force is the version a default read serves. A row key's version in force is its latest; a rate's is its latest by published time, so an older publication heard late is kept as the next version and never takes force. A change of quality state alone is a restatement, the next version of its row key. Every count a dataset reports, its quality counts and its unconverted, closed-day and outside-coverage counts, is of the rows in force.
The book's records¶
A custodian reports, once each: coupon_received, redemption,
paydown, accretion, tba_allocation, strip and reconstitution.
A servicing plugin proposes what it expects from the terms and the
published factors: expected_coupon, expected_maturity and
expected_paydown (a paydown, or an accretion for a Z or an IO class). A
factor revision is the book's own record, as above.
The engine's measures¶
analytics.DEBT_MEASURES: accrued interest, bond yield, price, risk,
key-rate durations and spreads, the Treasury curve, historical prepayment,
WAL at the pool's own CPR (its 3-month historical CPR, else its life CPR,
naming the speed used) and the make-whole amount, and expected_move. See
The analytics component.
The SDK's helpers¶
meridian.helpers.debt holds the money rules once, so every plugin
computes them the same way:
| Names | What |
|---|---|
percent_of_par, current_face, fill_cash, paydown_cash, coupon_split |
Cash from face and price; current face from the latest factor; a fill's cash and a paydown's principal, half-even to the cent; a coupon's two lines |
year_fraction, accrued_per100, coupon_dates, coupon_period |
Accrual by FIX's day counts |
factor, read_factors, latest, factor_month, settlement_month |
A factor row built; a pool's history read every page; the version in force; the months |
taken, awaited, open_claims |
What the book decided: the factor taken, the month awaited, the open claims. Read them, never re-derive them |
quoted_yield, capped, characteristics |
A yield or spread quote, a capped size, and the fixed-income trade characteristics by meaning |
meridian.helpers.lifecycle reports the custodian's records once
(lifecycle.report), proposes servicing's expectations
(lifecycle.expected_paydown, lifecycle.propose), and marks an open claim
settled (lifecycle.settle_claim).
from meridian.helpers import debt, lifecycle
from meridian.roles import servicing
class Servicing(servicing.Role):
async def on_factors_recorded(self, heard) -> None:
pool_id = heard.message.factor.meta.subjects[0].entity_id
rows = await debt.read_factors(self, [pool_id], "2026-01-01", "2026-11-30")
if len(rows) < 2:
return
prior, current = rows[-2], rows[-1]
for account_id, original_face in held(pool_id): # the plugin's own positions
expected = lifecycle.expected_paydown(account_id, pool_id, original_face,
prior, current, currency="USD")
if expected is not None:
await lifecycle.propose(self, [expected])
Where the data comes from¶
The data plugins listed on Integrations include fixed-income sources: bond terms and curves, quotes and prints, new-issue prices, and the agencies' pool and class factors. Each plugin's own documentation says what it records and what its access needs.