Home/AI Orchestration · Model Risk/Part II

Series 2 · Episode 02 · SOLUTION · Discount (equity book) · L02

Cashflow contracts as as-of hashes

An instrument is not a price and not a schedule, it is schedule plus credit assumption plus yield convention, hashed at a clock, and anything missing from that hash is a refuse rather than a rounding error

Cashflow contract hash: schedule + credit + yield, or incomplete refuse.

flowchart LR
  subgraph IN["Instrument claim"]
    CF["Schedule + credit + yield"]:::input
  end
  subgraph HASH["As-of contract"]
    H["CASHFLOW_CONTRACT hash H"]:::process
  end
  subgraph OUT["Rights"]
    OK["Promote under H"]:::gate
    NO["Incomplete schedule refuse"]:::risk
  end
  CF --> H --> OK
  H -->|missing pillar| NO

  classDef input fill:#CCFBF1,stroke:#0F766E,color:#134E4A,stroke-width:2px
  classDef decision fill:#FEF3C7,stroke:#B45309,color:#78350F,stroke-width:2px
  classDef risk fill:#FEE2E2,stroke:#B91C1C,color:#7F1D1D,stroke-width:2px
  classDef gate fill:#DCFCE7,stroke:#15803D,color:#14532D,stroke-width:2px
  classDef process fill:#E0E7FF,stroke:#4338CA,color:#312E81,stroke-width:2px
  classDef artifact fill:#F5F5F4,stroke:#57534E,color:#1C1917,stroke-width:2px

Simple claim: an instrument is schedule plus credit assumption plus yield convention, hashed at a clock; anything missing from that hash is refuse, not a rounding error. The trench is the cashflow contract that makes dual frames comparable without inventing 1.80.

The problem we left open

In the last post I used silent rate conventions to name a failure that never throws an exception. Simple, compound and continuous are three rulers wearing the same name. On a ten-year leg the convention swap alone is worth 0.96 per hundred of face, which is more than the 0.60 that separates the two live CEH-001 marks near 1.50 and 2.10. So the desk argues about models while the disagreement partly lives in a shared helper function, and Friday resolves it by shipping 1.80, the one number no allowed setup can produce.

Declaring the convention is necessary. It is not sufficient. A perfectly declared discount frame applied to a half-known instrument still gives you a confident wrong answer, because a fixed-income instrument is not a rate problem. It is a contract problem: contractually scheduled cash, with a credit caveat, quoted on a convention. Miss any of the three and you have priced something adjacent to the trade.

So the question for this post: if the frame must be declared, what is the smallest object that makes an instrument identity checkable?

The solution, as one stack

The core idea: make the instrument its own contract, hash the contract at a decision clock, and let nothing spend against anything but that hash. Schedule, credit, convention, clock, owner. Five moves.

### 1. The schedule is the instrument, and it must be complete

Not "quarterly coupons for three years." Every dated cashflow, enumerated: date, amount or amount rule, currency, and whether it is contractual or contingent. This sounds bureaucratic until you price the same bond twice. Face 100, five percent annual coupon, three years, yield six percent: the price is 97.33. Drop a single coupon date from the calendar, the kind of loss a schema-less join produces without complaint, and the same code returns 92.88. That is 4.45 of error from one missing row, on an instrument with only four rows.

The rule that follows is unpleasant and load-bearing: an incomplete schedule is not an approximate instrument. It is a different instrument. The harness must return refuse, not a value with a warning, because a value with a warning is a value.

Regular structures still get compact rules. A perpetual annuity is a/r; a finite annuity is the difference of two perpetuities; an amortising loan sizes its instalment straight out of the PV identity, 23.74 a year for five years retires 100 at six percent. Rules are welcome on the card. Absent dates are not.

### 2. The credit assumption is a field, not a footnote

Contractually scheduled is not the same as certain. Sovereign paper and a mid-rating corporate can have identical schedules and different objects. So the card carries the default assumption explicitly: hazard or rating input, recovery, and whether spreads are already inside the quoted discount curve.

The magnitude argues for itself. That same three-year bond, priced with a two percent annual default hazard and forty percent loss given default, comes back at 95.35 instead of 97.33. The credit assumption is worth 1.98, fifty times the four-cent gap between annual and semiannual conventions on the same paper, and a third of the entire CEH-001 dispute. A pipeline that guards conventions and leaves credit implicit has guarded the small term.

### 3. Bind the convention to the schedule, then compute yield inside the card

Yield is the internal rate of this stream on this basis. Priced annually, the bond is 97.33; on a semiannual basis at the same nominal yield it is 97.29. Small here, not small at ten years, and never small as a comparison error, because yields get ranked against each other and rankings drive tickets.

Two disciplines follow. First, a yield never travels without its basis; a bare yield: 0.06 is an untyped field and should fail a schema check. Second, solve the internal rate only where the stream permits a unique answer, one sign change, an outflow followed by inflows, gives you the single positive root you can defend. On a stream that changes sign repeatedly, the honest output is a set or an inconclusive, never the first root the solver happened to land on.

### 4. Hash the whole card as of a clock, and make the hash the unit of trust

Schedule, credit assumption, convention fields, curve identity and as_of, canonicalised and hashed. The hash is what a permit token binds to, what a backtest records, what a mark cites, what an audit replays. If the schedule gains a date or the recovery assumption changes, the hash changes, and every artefact still quoting the old hash is visibly stale rather than quietly wrong.

This is the same move as freezing an eval pack, applied to instrument identity. It converts a class of disputes from "whose model is right" into "these two numbers cite different hashes," which a machine can settle in milliseconds and a meeting cannot settle at all.

### 5. Agents draft the card; the harness signs it

There is real work here that language models are good at: reading a term sheet, proposing a schedule, flagging that the coupon basis in section four contradicts the summary table, drafting the credit assumption with its justification. Let them. What they may not do is complete a card by inference. An agent that fills a missing coupon date because the pattern was obvious has manufactured the exact failure move 1 exists to catch. So the card has a completeness bit set by validation, not by the drafter, and the three verdicts stay honest: allow on a complete hashed card, refuse on an incomplete one, inconclusive when fields are present but mutually contradictory and a human has to choose.

The example: CEH-001 through the cashflow contract

Same never-traded family. Under the old regime CEH-001 had two marks and a convention argument. Now it has a card, and the card has to pass before anyone quotes.

The funding leg enumerates cleanly, dates and all, and the convention field is populated: annual accrual, matching the term sheet's coupon calendar. Good, that is the 0.96 per hundred of ruler risk removed from the dispute by declaration rather than by debate.

Then the completeness check runs on the structured leg and fails. One contingent payment on the note is described in the documentation and not dated in the card, because it depends on an observation window the schedule never enumerated. Under the old stack that gap was invisible: the pricer used the coupon it could see and reported a number. Under the contract, that is SCHEDULE_INCOMPLETE, and the verdict is refuse. Not a mark with a caveat. No mark.

The credit field fails differently. Two feeds are legal at this clock and they disagree about recovery. Present, populated, contradictory, that is inconclusive, escalate-only. A human picks the assumption, the pick lands in the hash, and the pick is auditable next quarter when someone asks why the mark moved 1.98.

End state: the spread-frame reading near 1.50 and the curve-frame reading near 2.10 now cite two different hashes. That is the whole win. They are no longer two opinions about one object; they are two objects, and the difference is a diff, not a debate. And 1.80 has nowhere to come from. There is no hash whose card produces it, so no artefact can cite it, so the Friday compromise fails the schema before it reaches the report. The honest output is two marks and an escalation.

The flow in one breath

Problem: a declared discount frame still prices a half-known instrument, and missing schedule or credit fields cost more than the convention gap everyone is arguing about. Solution: make the instrument a contract, complete dated schedule, explicit credit assumption, convention bound to the stream, all hashed as of a clock, with agents drafting and the harness signing. Example: CEH-001's undated contingent payment turns a confident mark into a refuse, contradictory recovery feeds turn into an escalation, and the invented 1.80 loses the hash it would have needed to exist.

Curious how others keep instrument identity hashed without freezing their ability to onboard new structures, and how they stop a helpful agent from completing a schedule it should have refused.

Clearance coupling. Promote a mark only with cashflow_contract_hash equal across research and serve. Mismatch is FRAME_UNDECLARED or SILENT_CONVERSION refuse — not a methodology meeting. Agents may propose frames; harnesses spend only on matched hashes.

Book couple. Rates spine chapter owns the contract object; ops harness treats missing hash as hard gate before powered eval even runs.

Next. Open S2-03: Tomorrow's 10y is already in the table. Previous: S2-01 (Silent rate conventions and the two marks nobody reconciled). Part II index.